Shell腳本命令的工作方式有兩種: 交互式(Interactive):用戶每輸入一條命令就立即執(zhí)行。 批處理(Batch):由用戶事先編寫好一個(gè)完整的Shell腳本,Shell會(huì)一次性執(zhí)行腳本中諸多的命令。 一、編寫簡單的腳本一個(gè)Shell腳本主要由三部分組成:腳本聲明、腳本注釋、腳本命令。
Shell腳本的名稱可以任意,但為了方便用戶辨認(rèn),建議加上.sh后綴以表示這是一個(gè)腳本文件。下面通過Vim編輯器簡單編寫一個(gè)Shell腳本: [root@linuxprobe ~]# vim example.sh
#!/bin/bash //腳本聲明
# for example by xuliang //腳本注釋
pwd //腳本命令
ls -al
可以通過bash命令直接運(yùn)行腳本文件,也可以通過輸入完整路徑的方式來執(zhí)行,但是需要先對腳本文件添加可執(zhí)行權(quán)限。 [root@linuxprobe ~]# bash example.sh //通過bash命令執(zhí)行腳本文件
/root
total 21260
dr-xr-x---. 17 root root 4096 Feb 23 16:57 .
drwxr-xr-x. 17 root root 4096 Feb 23 10:34 ..
drwxr-xr-x. 3 root root 14 Feb 18 15:26 a
-rw-------. 1 root root 1032 Feb 18 2019 anaconda-ks.cfg
-rw-------. 1 root root 6039 Feb 23 10:57 .bash_history
---------------------省略部分輸出內(nèi)容------------------------------
[root@linuxprobe ~]# ./example.sh //通過完整路徑執(zhí)行腳本文件,需要可執(zhí)行權(quán)限
二、接收用戶的參數(shù) 上面的腳本只能執(zhí)行一些預(yù)先定義好的命令,未免太過于死板了。為了增加Shell腳本的靈活性,必須讓腳本可以接收用戶輸入的參數(shù)。Linux系統(tǒng)中的Shell腳本語言已經(jīng)內(nèi)設(shè)了用于接受參數(shù)的變量,變量之間使用空格間隔,相關(guān)變量如下所示:
“百聞不如一見,看書不如實(shí)踐”,接下來通過編寫一個(gè)腳本,引用上面的變量參數(shù)來看一下實(shí)際效果: [root@linuxprobe ~]# vim example.sh
#!/bin/bash
# for example by xuliang
echo "當(dāng)前腳本名稱$0"
echo "總共有$#個(gè)參數(shù),分別是$*"
echo "第一個(gè)參數(shù)為$1,第3為$3"
三、判斷用戶的參數(shù)接下來學(xué)習(xí)如何處理接收到的用戶參數(shù)。Shell腳本中的條件測試語法可以判斷表達(dá)式是否成立,若條件成立則返回?cái)?shù)字0,否則返回其他隨機(jī)數(shù)字(一般都是返回1),條件測試語句的執(zhí)行格式如下所示。切記,條件表達(dá)式兩邊必須要有一個(gè)空格。 按照測試對象來劃分,條件測試語句可以分為4種:
1、文件測試語句指使用指定條件來判斷文件是否存在或權(quán)限是否滿足等情況的運(yùn)算符,具體參數(shù)如下所示:
實(shí)驗(yàn)1:使用文件測試語句判斷/etc/fstab是否為一個(gè)目錄類型文件,然后通過Shell解釋器的內(nèi)設(shè)$?變量來顯示上一條命令執(zhí)行后的返回值。如果上一條命令執(zhí)行成功,則$?變量的數(shù)值為0;反之則為一個(gè)非零值(一般都是1)。 [root@linuxprobe ~]# [ -d /etc/fstab ]
[root@linuxprobe ~]# echo $? //顯示上條命令執(zhí)行結(jié)果
1 //非零值表示執(zhí)行失敗
[root@linuxprobe ~]#
實(shí)驗(yàn)2:使用條件測試語句判斷/etc/fstab是否為一個(gè)一般文件。 [root@linuxprobe ~]# [ -f /etc/fstab ]
[root@linuxprobe ~]# echo $?
0 //執(zhí)行成功
[root@linuxprobe ~]#
2、邏輯測試語句指對測試結(jié)果進(jìn)行邏輯分析,根據(jù)測試結(jié)果實(shí)現(xiàn)不同的效果。主要有3種邏輯運(yùn)算符,如下所示:
實(shí)驗(yàn)1:判斷/dev/cdrom文件是否存在,若存在則輸出Exist字樣。 [root@linuxprobe ~]# [ -e /dev/cdrom ] && echo "Exist" //邏輯與
Exist
實(shí)驗(yàn)2:判斷當(dāng)前登錄的用戶是否為管理員身份: [root@linuxprobe ~]# su - linuxprobe //切換至linuxprobe用戶
Last login: Mon Feb 24 10:26:51 BNT 2020 on pts/1
[linuxprobe@linuxprobe ~]$
[linuxprobe@linuxprobe ~]$ [ $USER = root ] || echo "not root" //邏輯或
not root
實(shí)驗(yàn)3:判斷當(dāng)前登錄用戶為非管理員身份: [linuxprobe@linuxprobe ~]$ su - root //切換至root用戶
Password:
Last login: Mon Feb 24 11:13:05 BNT 2020 on pts/1
[root@linuxprobe ~]# [ ! $USER = root ] || echo "It's root" //邏輯非
It's root
實(shí)驗(yàn)4:判斷當(dāng)前登錄的用戶,若是普通用戶則輸出“user”,若是管理員用戶則輸出“root” [root@linuxprobe ~]# [ ! $USER = root ] && echo "user" || echo "It's root"
It's root //root用戶
[root@linuxprobe ~]# su - linuxprobe //切換至linuxprobe用戶
Last login: Mon Feb 24 14:41:29 BNT 2020 on pts/1
[linuxprobe@linuxprobe ~]$ [ ! $USER = root ] && echo "user" || echo "It's root"
user //普通用戶
3、整數(shù)比較運(yùn)算符僅僅是對數(shù)字的操作,即運(yùn)算符的兩邊必須是數(shù)字,不能將數(shù)字與字符串、文件等內(nèi)容一起操作,而且一定要使用規(guī)范的整數(shù)比較運(yùn)算符來進(jìn)行操作。整數(shù)比較運(yùn)算符如下所示:
實(shí)驗(yàn):判斷當(dāng)前主機(jī)空閑內(nèi)存是否小于1024M,若小于1024M,則輸出“Insufficient Memory”的字樣。 [linuxprobe@linuxprobe ~]$ FreeMem=`free -m | grep Mem: | awk '{print $4}'` //獲取當(dāng)前主機(jī)空閑內(nèi)存值,注意賦值號的兩邊不能有空格
[linuxprobe@linuxprobe ~]$
[linuxprobe@linuxprobe ~]$ [ $FreeMem -lt 1024 ] && echo "Insuficient Memory"
Insuficient Memory
4、字符串比較語句用于判斷測試字符串是否為空值,或兩個(gè)字符串是否相同,常見的字符串運(yùn)算符如下所示:
實(shí)驗(yàn)1:判斷變量String是否空值,即判斷是否定義了該變量。 [linuxprobe@linuxprobe ~]$ [ -z $String ]
[linuxprobe@linuxprobe ~]$ echo $?
0
實(shí)驗(yàn)2:判斷當(dāng)前LANG環(huán)境變量值是否為“en.US”。 [linuxprobe@linuxprobe ~]$ echo $LANG
en_US.UTF-8
[linuxprobe@linuxprobe ~]$ [ $LANG = "en.US" ] || echo "Not en.US"
Not en.US
四、流程控制語句在Shell腳本中,我們可以通過if、for、while、case這4中流程控制語句來編寫難度更大、功能更強(qiáng)的腳本,來匹配實(shí)際的生產(chǎn)需求。 1、if條件測試語句if條件測試語句分為單分支結(jié)構(gòu)、雙分支結(jié)構(gòu)、多分支結(jié)構(gòu),下面逐一進(jìn)行介紹: (1)單分支結(jié)構(gòu) 由if、then、fi關(guān)鍵詞組成,只有在判斷條件成立之后才執(zhí)行預(yù)設(shè)的命令,相當(dāng)于口語的“如果........那么........”。語法格式如下所示:
實(shí)驗(yàn):判斷/root/test目錄文件是否存在,如存在則結(jié)束Shell腳本,否則創(chuàng)建該目錄。 [root@linuxprobe ~]# vim mkcdrom.sh
#!/bin/bash
DIR="/root/test"
if [ ! -e $DIR ]
then
mkdir -p $DIR
fi
[root@linuxprobe ~]# bash mkcdrom.sh //執(zhí)行腳本
[root@linuxprobe ~]# ls -d /root/test/ //檢查目錄是否創(chuàng)建成功
/root/test/
?。?)多分支結(jié)構(gòu) 由if、then、else、fi關(guān)鍵詞組成,它進(jìn)行一次條件匹配判斷,若匹配成功,則執(zhí)行預(yù)設(shè)的命令,否則去執(zhí)行匹配失敗時(shí)的預(yù)設(shè)命令。語法格式如下所示:
實(shí)驗(yàn):用戶自行輸入IP地址,并判斷該主機(jī)是否在線。 [root@linuxprobe ~]# vim chkhost.sh
#!/bin/bash
ping -c 3 -i 0.2 -w 3 $1 &> /dev/null ###其中參數(shù)表示ping3次、每次間隔0.2秒、等待超時(shí)時(shí)間為3秒
if [ $? -eq 0 ]
then
echo "Host $1 is On-line"
else
echo "Host $1 is Off-line"
fi
[root@linuxprobe ~]# bash chkhost.sh 192.168.134.10
Host 192.168.134.10 is On-line //主機(jī)在線
[root@linuxprobe ~]# bash chkhost.sh 192.168.134.20
Host 192.168.134.20 is Off-line //主機(jī)不在線
[root@linuxprobe ~]#
?。?)多分支結(jié)構(gòu) 由if、then、else、elif、fi關(guān)鍵詞組成,它進(jìn)行多次條件匹配判斷,這么多次判斷中的任一項(xiàng)匹配成功都會(huì)執(zhí)行相應(yīng)的預(yù)設(shè)命令,相當(dāng)于口語的“如果.....那么......如果.......那么.....”。多分支語句可以多次嵌套,語法格式如下所示: 實(shí)驗(yàn):判斷用戶輸入的分?jǐn)?shù)在哪個(gè)區(qū)間,然后輸出Excellent、Pass、Fail等提示信息。 [root@linuxprobe ~]# vim chkscore.sh
#!/bin/bash
read -p "Enter your score(0-100):" GRADE
2、for條件循環(huán)語句for循環(huán)語句允許腳本一次性讀取多個(gè)信息,然后逐一對信息進(jìn)行操作處理。當(dāng)要處理有范圍的數(shù)據(jù)時(shí),使用for循環(huán)語句再適合不過了,其語法格式如下所示:
實(shí)驗(yàn)1:從列表文件中讀取多個(gè)用戶名,然后為其逐一創(chuàng)建用戶賬號并設(shè)置密碼。 [root@linuxprobe ~]# vim users.txt //首先創(chuàng)建包含用戶名稱的文件
zhangsan
lisi
wangwu
zhaoliu
[root@linuxprobe ~]# vim CreateUser.sh //編寫腳本
#!/bin/bash
read -p "Enter the Users Password:" PASSWD
補(bǔ)充:假如用戶名文件users.txt內(nèi)容寫成以下形式(即所有用戶名寫成一行,用空格分開),CreateUser.sh腳本同樣執(zhí)行成功。 [root@linuxprobe ~]# cat users.txt
andy barry carl
[root@linuxprobe ~]#
[root@linuxprobe ~]# bash CreateUser.sh
Enter the Users Password:123456
andy create success
barry create success
carl create success
實(shí)驗(yàn)2:讀取文件中的主機(jī)列表,然后逐個(gè)測試這些主機(jī)是否在線。 [root@linuxprobe ~]# vim ipaddrs.txt //創(chuàng)建主機(jī)列表文件
192.168.134.10
192.168.134.20
192.168.134.30
192.168.134.40
[root@linuxprobe ~]# vim chkhosts.sh //編寫腳本
#!/bin/bash
HLIST=$(cat ~/ipaddrs.txt) //其中$(命令)相當(dāng)于`命令`
3、while條件循環(huán)語句while條件語句是一種讓腳本根據(jù)某些條件來重復(fù)執(zhí)行命令的語句,它的循環(huán)結(jié)構(gòu)往往在執(zhí)行前并不確定最終執(zhí)行的次數(shù),它通過判斷條件測試的真假來決定是否繼續(xù)執(zhí)行命令,條件為真就繼續(xù)執(zhí)行,為假就結(jié)束循環(huán),語法結(jié)構(gòu)如下所示:
實(shí)驗(yàn):編寫一個(gè)猜數(shù)的腳本,若用戶輸入的數(shù)值與腳本隨機(jī)生成的數(shù)值一致,則結(jié)束游戲。 [root@linuxprobe ~]# vim guess.sh
#!/bin/bash
PRICE=$(expr $RANDOM % 1000) ##獲取一個(gè)1000以內(nèi)的隨機(jī)數(shù)
TIMES=0
echo "商品的實(shí)際價(jià)格為0-999之間,請猜猜看是多少?"
while true
do
read -p "請輸入你猜測的價(jià)格:" INT
let TIMES++ ##TIMES變量自增1
if [ $INT -eq $PRICE ] ; then
echo "恭喜你猜對啦,實(shí)際價(jià)格為 $PRICE"
echo "您總共猜了 $TIMES 次"
exit
elif [ $INT -gt $PRICE ] ; then
echo "您猜高了"
else
echo "您猜低了"
fi
done
[root@linuxprobe ~]# bash guess.sh
商品的實(shí)際價(jià)格為0-999之間,請猜猜看是多少?
請輸入你猜測的價(jià)格:500
您猜低了
請輸入你猜測的價(jià)格:800
您猜高了
-------------------省略部分內(nèi)容---------------------
您猜高了
請輸入你猜測的價(jià)格:516
您猜低了
請輸入你猜測的價(jià)格:517
恭喜你猜對啦,實(shí)際價(jià)格為 517
您總共猜了 14 次
4、case條件測試語句case語句是在多個(gè)范圍內(nèi)匹配數(shù)據(jù),若匹配成功則執(zhí)行相關(guān)命令并結(jié)束整個(gè)條件測試;如果數(shù)據(jù)在所列的范圍內(nèi),則會(huì)去執(zhí)行星號(*)中所定義的默認(rèn)命令,語法結(jié)構(gòu)如下所示: 實(shí)驗(yàn):判斷用戶輸入的數(shù)據(jù)是字母、數(shù)字還是其他字符。 [root@linuxprobe ~]# cat chkkeys.sh
#!/bin/bash
read -p "請輸入一個(gè)字符:" KEY
case "$KEY" in
[a-z]|[A-Z])
echo "您輸入的是字母"
;;
[0-9])
echo "您輸入的是數(shù)字"
;;
*)
echo "您輸入的是特殊字符"
esac
[root@linuxprobe ~]# bash chkkeys.sh
請輸入一個(gè)字符:2
您輸入的是數(shù)字
[root@linuxprobe ~]# bash chkkeys.sh
請輸入一個(gè)字符:s
您輸入的是字母
[root@linuxprobe ~]# bash chkkeys.sh
請輸入一個(gè)字符:`
您輸入的是特殊字符
[root@linuxprobe ~]#
補(bǔ)充:上述關(guān)于檢查字符的腳本是有缺陷的,當(dāng)用戶輸入兩位及以上的數(shù)字或字母時(shí),會(huì)提示輸入的是特殊字符。 [root@linuxprobe ~]# bash chkkeys.sh
請輸入一個(gè)字符:12
您輸入的是特殊字符
解決方法:修改匹配條件,如下所示。但是當(dāng)輸入三位數(shù)字時(shí),依然提示輸入的是特殊字符,需要繼續(xù)修改匹配條件。所以該方法只能算打補(bǔ)丁,不能算真正的解決方法。 [root@linuxprobe ~]# cat chkkeys.sh
#!/bin/bash
read -p "請輸入一個(gè)字符:" KEY
case "$KEY" in
[a-z]|[A-Z])
echo "您輸入的是字母"
;;
[0-9]|[0-9][0-9]) ##匹配一位或兩位數(shù)字
echo "您輸入的是數(shù)字"
;;
*)
echo "您輸入的是特殊字符"
esac
[root@linuxprobe ~]# bash chkkeys.sh
請輸入一個(gè)字符:34
您輸入的是數(shù)字
四、計(jì)劃任務(wù)服務(wù)程序在實(shí)際的運(yùn)維工作中,需要在指定的時(shí)間段自動(dòng)啟動(dòng)或停止某些服務(wù)或命令,從而實(shí)現(xiàn)運(yùn)維的自動(dòng)化。接下來介紹如何設(shè)置服務(wù)器的計(jì)劃任務(wù)服務(wù),把周期性、規(guī)律性的工作交給系統(tǒng)自動(dòng)完成。 計(jì)劃任務(wù)分為一次性任務(wù)和長期性任務(wù),如下所示:
1、一次性計(jì)劃任務(wù)顧名思義,一次性計(jì)劃任務(wù)只執(zhí)行一次,一般用于滿足臨時(shí)的工作需求,可以用at命令實(shí)現(xiàn)這種功能,相關(guān)功能如下所示:
實(shí)驗(yàn)1:設(shè)置在今天11:24重啟系統(tǒng)主機(jī) [root@linuxprobe ~]# at 11:24
at> reboot
at> <此處按下Ctrl+d組合鍵來結(jié)束編寫計(jì)劃任務(wù)>
job 2 at Sat Feb 29 11:24:00 2020
[root@linuxprobe ~]# at -l
2 Sat Feb 29 11:24:00 2020 a root
[root@linuxprobe ~]#
實(shí)驗(yàn)2:at命令默認(rèn)采用交互式的方式,接下使用非交互式的方法創(chuàng)建一個(gè)一次性計(jì)劃任務(wù)。 [root@linuxprobe ~]# echo "systemctl restart network" | at 11:35
job 4 at Sat Feb 29 11:35:00 2020
[root@linuxprobe ~]#
[root@linuxprobe ~]# at -l
4 Sat Feb 29 11:35:00 2020 a root //其中"4"就是任務(wù)序號
實(shí)驗(yàn)3:刪除一個(gè)一次性計(jì)劃任務(wù)。 [root@linuxprobe ~]# atrm 4
[root@linuxprobe ~]# at -l
[root@linuxprobe ~]#
2、長期性計(jì)劃任務(wù)Linux系統(tǒng)中默認(rèn)啟動(dòng)的crond服務(wù)能夠周期性地、有規(guī)律地執(zhí)行某些具體的任務(wù),相關(guān)地命令如下所示:
使用crond服務(wù)設(shè)置計(jì)劃任務(wù)時(shí),語法格式為“分 時(shí) 日 月 星期 命令”。需要注意的是,如果有些字段沒有設(shè)置,則必須使用星號(*)占位,如下圖所示:
使用crond設(shè)置任務(wù)的參數(shù)字段說明,如下表所示:
實(shí)驗(yàn)1:設(shè)置在每周一、三、五的凌晨3點(diǎn)25分,使用tar命令打包網(wǎng)站的數(shù)據(jù)。 [root@linuxprobe ~]# crontab -e //默認(rèn)進(jìn)入Vim編輯器界面
no crontab for root - using an empty one
crontab: installing new crontab
[root@linuxprobe ~]# crontab -l
25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot
[root@linuxprobe ~]#
補(bǔ)充說明:這里補(bǔ)充幾點(diǎn)關(guān)于時(shí)間周期的設(shè)置,如下所示:
crond服務(wù)可以包含多條計(jì)劃任務(wù),注意每條計(jì)劃任務(wù)占一行。比如我們要增加一條計(jì)劃任務(wù),它的功能是每周一至周五的凌晨1點(diǎn)自動(dòng)清空/tmp目錄內(nèi)的所有文件。 [root@linuxprobe ~]# whereis rm //使用whereis命令查詢絕對路徑
rm: /usr/bin/rm /usr/share/man/man1/rm.1.gz /usr/share/man/man1p/rm.1p.gz
[root@linuxprobe ~]#
[root@linuxprobe ~]# crontab -e
crontab: installing new crontab
[root@linuxprobe ~]# crontab -l
25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot
0 1 * * 1-5 /usr/bin/rm -rf /tmp/*
注意事項(xiàng): (1)在Vim編輯器中配置計(jì)劃任務(wù)時(shí),可以以#號開頭寫上注釋信息。 (2)計(jì)劃任務(wù)中的“分”字段必須有數(shù)值,絕對不能為空或*號。 (3)“日”和“星期”字段不能同時(shí)使用,否則會(huì)發(fā)生沖突。
|
|