?
?
?Shell腳本并不能作為正式的編程語言,因?yàn)樗窃?span style="font-family:'Times New Roman';">Linux的shell中運(yùn)行的,所以稱為shell腳本。事實(shí)上,shell腳本就是一些命令的集合。比如,我想實(shí)現(xiàn)這樣的操作:(1) 進(jìn)入/tmp/目錄;
(2) 列出當(dāng)前目錄中所有的文件名;
(3) 把所有當(dāng)前的文件復(fù)制到/root/目錄下;
(4) 刪除當(dāng)前目錄下所有的文件。
完成以上簡單的4步需要在shell窗口中輸入4次命令,按4次回車,這不算太難。但如果是輸入復(fù)雜的命令,一次一次敲鍵盤會很麻煩。我們不妨把所有的操作都記錄到一個文檔中,然后去調(diào)用文檔中的命令,這樣一
步操作就可以完成。其實(shí)這個文檔就是shell腳本,只是這個shell腳本有它特殊的格式。
Shell腳本能幫助我們很方便地管理服務(wù)器,因?yàn)槲覀兛梢灾付ㄒ粋€任務(wù)計劃,定時去執(zhí)行某個shell腳本以滿足需求。這對于Linux系統(tǒng)管理員來說是一件非常值得自豪的事情。我們可以在Linux服務(wù)器上部署監(jiān)控的
shell腳本,然后腳本中可以加上郵件通知來告之出現(xiàn)故障。比如,網(wǎng)卡流量出現(xiàn)異常或者Web服務(wù)器停止服務(wù),就可以發(fā)一封郵件給管理員。這樣可以讓管理員及時知道服務(wù)器出問題了。
在正式編寫shell腳本之前,阿銘建議凡是自定義的腳本都放到/usr/local/sbin/目錄下。這樣做的目的是:一來可以更好地管理文檔;二來以后接管你工作的管理員都知道自定義腳本放在哪里,方便維護(hù)。
13.1.1 shell腳本的創(chuàng)建和執(zhí)行
下面請跟著阿銘編寫第一個shell腳本,如下所示:
# cd /usr/local/sbin/
# vim first.sh //加入如下內(nèi)容
## This is my first shell script.
## Writen by Aming 2022-12-02.
date
echo "Hello world!"
shell腳本通常都以.sh為后綴名。這并不是說不加.sh的腳本就不能執(zhí)行,只是大家的一個習(xí)慣而已。所以,以后如果發(fā)現(xiàn)了以.sh為后綴的文件,那么它可能是一個shell腳本。本例中,腳本文件first.sh的第1行要以#! /bin/bash開頭,表示該文件使用的是bash語法。如果不設(shè)置該行,你的shell腳本也可以執(zhí)行,但是不符合規(guī)范。#表示注釋,后面跟一些該腳本的相關(guān)注釋內(nèi)容,以及作者、創(chuàng)建日期或者版本等。當(dāng)然,這些注釋并非必需的,但阿銘不建議省略。因?yàn)殡S著工作時間的逐漸過渡,寫的shell腳本也會越來越多,如果有一天你回頭查看自己寫過的某個腳本,很有可能忘記該腳本是用來干什么的以及什么時候?qū)懙摹K詫懮献⑨屖怯?br /> 必要的。另外,系統(tǒng)管理員并非只有你一個,寫上注釋有助于其他管理員查看你的腳本。
下面我們執(zhí)行一下這個腳本,如下所示:
# sh first.sh
Fri Dec 2 22:16:56 CST 2022
Hello world!
其實(shí)shell腳本還有一種執(zhí)行方法,如下所示:
# ./first.sh
./first.sh: 權(quán)限不夠
: # chmod +x first.sh
# ./first.sh
Fri Dec 2 2256 CST 2022
Hello world!
使用該方法運(yùn)行shell腳本的前提是腳本本身有執(zhí)行權(quán)限,所以需要給腳本加一個x權(quán)限。另外,使用sh命令執(zhí)行一個shell腳本時,可以加-x選項(xiàng)來查看這個腳本的執(zhí)行過程,這樣有利于我們調(diào)試這個腳本。如下所示:
# sh -x first.sh
+ date
Fri Dec 2?2243?CST?2022
+ echo 'Hello world!'
Hello world!
本例中有一個date命令,之前阿銘從未介紹過,這個命令在shell腳本中使用非常頻繁,因此有必要介紹一下它的用法。13.1.2 命令date
date命令在shell腳本中最常用的幾個用法如下。
- date +%Y:表示以四位數(shù)字格式打印年份。
- ?
- date +%y:表示以兩位數(shù)字格式打印年份。
- ?
- date +%m:表示月份。
- ?
- date +%d:表示日期。
- ?
- date +%H:表示小時。
- ?
- date +%M:表示分鐘。
- ?
- date +%S:表示秒。
- ?
- date +%w:表示星期。結(jié)果顯示0則表示周日。 ? ?
date +"%Y-%m-%d %H:%M:%S"
2022-12-02?2203
有時,在腳本中會用到一天前的日期,如下所示:
date -d "-1 day" +%d
01
或者一小時前,如下所示:
date -d "-1 hour" +%H
21
甚至一分鐘前,如下所示:
# date -d "-1 min" +%M
17
?13.2 shell腳本中的變量在shell腳本中使用變量會使我們的腳本更加專業(yè),更像是一門語言。如果你寫了一個長達(dá)1000行的shell腳本,并且腳本中多次出現(xiàn)某一個命令或者路徑,而你覺得路徑不對想修改一下,就得一個一個修改,或者使用批量替換的命令修改。這樣做很麻煩,并且腳本也顯得臃腫了很多。變量就是用來解決這個問題的。定義變量的格式為:“變量名=變量的值”。在腳本中引用變量時需要加上符號$,這跟前面介紹的在shell中自定義變量是一致的。
下面我們編寫第一個與變量相關(guān)的腳本,如下所示: ?
# vim variable.sh
#! /bin/bash
## In this script we will use variables.
## Writen by Aming 2022-12-02.
d=`date +%H:%M:%S`
echo "The script begin at $d."
echo "Now we'll sleep 2 seconds."
sleep 2
d1=`date +%H:%M:%S`
echo "The script end at $d1."
本例中使用到了反引號,它的作用是將引號中的字符串當(dāng)成shell命令執(zhí)行,返回命令的執(zhí)行結(jié)果。d和d1在腳本中作為變量出現(xiàn)。下面來看看該腳本的執(zhí)行結(jié)果,如下所示:
# sh variable.sh
The script begin at 2204.
Now we'll sleep 2 seconds.
The script end at 2206.
?13.2.1 數(shù)學(xué)運(yùn)算
示例命令如下:
# vim sum.sh
## For get the sum of two numbers.
##?Aming?2022-12-02.
a=1
b=2
sum=$[$a+$b]
echo "$a+$b=$sum"
數(shù)學(xué)計算要用[ ]括起來,并且前面要加符號$。該腳本的結(jié)果如下:
# sh sum.sh
1+2=3
?13.2.2 和用戶交互示例腳本如下:
# cat read.sh
## Using 'read' in shell script.
## Aming 2022-12-02.
read -p "Please input a number: " x
read -p "Please input another number: " y
sum=$[$x+$y]
echo "The sum of the two numbers is: $sum"
read命令用于和用戶交互,它把用戶輸入的字符串作為變量值。該腳本的執(zhí)行過程如下:
# sh read.sh
Please input a number: 2
Please input another number: 10
The sum of the two numbers is: 12
我們不妨加上-x選項(xiàng)再來看看這個執(zhí)行過程:
# sh -x read.sh
+ read -p 'Please input a number: ' x
Please input a number: 22
+ read -p 'Please input another number: ' y
Please input another number: 13
+ sum=35
+ echo 'The sum of the two numbers is: 35'
The sum of the two numbers is: 35
?13.2.3 shell腳本預(yù)設(shè)變量有時我們會用到類似/etc/init.d/iptables restart(該命令來源于早期CentOS系統(tǒng))命令,前面的/etc/init.d/iptables文件其實(shí)就是一個shell腳本。腳本后面為什么可以跟一個restart字符串呢?這就涉及shell腳本的預(yù)設(shè)變量了。實(shí)際上,shell腳本在執(zhí)行時,后面可以跟一個或者多個參數(shù)。比如下面的腳本:
# vim option.sh //內(nèi)容如下
sum=$[$1+$2]
echo "sum=$sum"
該腳本的執(zhí)行結(jié)果如下:
# sh -x option.sh 1 2
+ sum=3
+ echo sum=3
sum=3
你可能會問:腳本中的$1和$2是從哪里來的?這其實(shí)就是shell腳本的預(yù)設(shè)變量。本例中,$1和$2的值就是在執(zhí)行時分別輸入的1和2,$1就是腳本的第一個參數(shù),$2是腳本的第二個參數(shù),以此類推。當(dāng)然一個shell腳本的預(yù)設(shè)變量是沒有限制的。
另外還有一個$0,它代表腳本本身的名字。我們不妨把腳本修改一下,如下所示:
echo "$1 $2 $0"
該腳本的執(zhí)行結(jié)果如下:
# sh option.sh 1 2
1 2 option.sh
?13.3 shell腳本中的邏輯判斷如果你學(xué)過C等語言,相信你不會對if感到陌生。在shell腳本中,我們同樣可以使用if邏輯判斷。
13.3.1 不帶else
具體格式如下:
if 判斷語句; then
command
fi
示例腳本如下:
# cat if1.sh
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
fi
if1.sh中出現(xiàn)了((a<60))這樣的形式,這是shell腳本中特有的格式,只用一個小括號或者不用都會報錯,請記住這個格式。阿銘還會用另外一種格式,后面會介紹到。該腳本的執(zhí)行結(jié)果如下:
# sh if1.sh
Please input your score: 90
# sh if1.sh
Please input your score: 33
You didn't pass the exam.
?13.3.2 帶有else具體格式如下:
if 判斷語句; then
command
else
command
fi
示例腳本如下:
# vim if2.sh //內(nèi)容如下
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
else
echo "Good! You passed the exam."
fi
該腳本的執(zhí)行結(jié)果如下:
# sh if2.sh
Please input your score: 80
You passed the exam.
# sh if2.sh
Please input your score: 25
You didn't pass the exam.
腳本if2.sh和腳本if1.sh唯一的區(qū)別是:如果輸入大于或等于60的數(shù)字會有提示。13.3.3 帶有elif具體格式如下:
if 判斷語句1; then
command
elif 判斷語句2; then
command
else
command
fi
示例腳本如下:
# vim if3.sh //內(nèi)容如下
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
elif ((a>=60)) && ((a<85)); then
echo "Good! You pass the exam."
else
echo "Very good! Your score is very high!"
fi
這里的&&表示“并且”的意思,當(dāng)然也可以使用||表示“或者”。該腳本的執(zhí)行結(jié)果如下:
# sh if3.sh
Please input your score: 90
Very good! Your score is very high!
# sh if3.sh
Please input your score: 60
You pass the exam.
以上只是簡單介紹了if語句的結(jié)構(gòu)。判斷數(shù)值大小除了可以用(())的形式外,還可以使用[]。但是不能使用>、<、=這樣的符號了,要使用-lt?(小于)、-gt(大于)、-le(小于或等于)、-ge(大于或等于)、-eq(等于)、-ne(不等于)。下面阿銘就以命令行的形式簡單比較一下,不再寫shell腳本。示例代碼如下:
a=10; if [ $a -lt 5 ]; then echo ok; fi
a=10; if [ $a -gt 5 ]; then echo ok; fi
ok
a=10; if [ $a -ge 10 ]; then echo ok; fi
ok
a=10; if [ $a -eq 10 ]; then echo ok; fi
ok
a=10; if [ $a -ne 10 ]; then echo ok; fi
下面是在if語句中使用&&和||的情況,示例代碼如下:
# a=10; if [ $a -lt 1 ] || [ $a -gt 5 ]; then echo ok; fi
ok
# a=10; if [ $a -gt 1 ] || [ $a -lt 10 ]; then echo ok; fi
ok
?13.3.4 和文檔相關(guān)的判斷Shell腳本中if還經(jīng)常用于判斷文檔的屬性,比如判斷是普通文件還是目錄,判斷文件是否有讀、寫、執(zhí)行權(quán)限等。if常用的選項(xiàng)有以下幾個。- -e:判斷文件或目錄是否存在。
- -d:判斷是不是目錄以及是否存在。
- -f:判斷是不是普通文件以及是否存在。
- -r:判斷是否有讀權(quán)限。
- -w:判斷是否有寫權(quán)限。
- -x:判斷是否可執(zhí)行。 ? ?
if [ -e filename ] ; then
command
fi
示例代碼如下:
if [ -d /home/ ]; then echo ok; fi
ok
if [ -f /home/ ]; then echo ok; fi
因?yàn)?span style="font-size:15px;font-family:'Times New Roman';">/home/是目錄而非文件,所以并不會顯示ok。其他示例如下所示:
# if [ -f /root/test.txt ]; then echo ok; fi
ok
# if [ -r /root/test.txt ]; then echo ok; fi
ok
# if [ -w /root/test.txt ]; then echo ok; fi
ok
# if [ -x /root/test.txt ]; then echo ok; fi
# if [ -e /root/test1.txt ]; then echo ok; fi
審核編輯:湯梓紅
評論
查看更多