shell腳本的三種元素
● 第一行的腳本聲明(#!):指定解釋此腳本文件的 Shell 程序;
● 第二行的注釋信息(#):對腳本功能和某些命令的介紹信息;
● 第三行的可執行語句:執行的Linux命令。
[root@kylin ~]# vim hello.sh#!/bin/bash#Example of printing "hello world!"echo "Hello World!"
運行腳本的兩種方法
● 作為可執行程序
[root@kylin ~]# chmod +x ./hello.sh #使腳本具有執行權限[root@kylin ~]# ./hello.sh #執行腳本
● 作為解釋器參數
[root@kylin ~]# /bin/bash hello.sh[root@kylin ~]# /bin/sh hello.sh
變量
使用變量
● 變量外的花括號加不加都能正常引用變量,但推薦所有變量都加上{},幫助解釋器識別變量的邊界,養成好的編程習慣。
[root@kylin ~]# vim company.sh#!/bin/bash#Examples of using variablescompany="kylin"echo $companyecho ${company}
刪除變量
● 使用unset刪除變量,變量刪除后不能再次使用。以下實例執行后無輸出:
[root@kylin ~]# vim unset.sh#!/bin/bash#Example of deleting variablesmyUrl="https://www.kylinos.cn"unset myUrlecho $myUrl
傳遞參數
● shell腳本內設了接受參數的變量,傳遞參數時使用空格間隔。常用傳參變量如下表: | 變量 | 含義 |
---|---|---|
$0 | 當前Shell腳本程序的名稱 | |
$# | 總共有幾個參數 | |
$* | 所有位置的參數值 | |
$? | 顯示上一次命令的執行返回值 | |
$1、$2、$3 | 分別對應著第N個位置的參數值 |
● 以下實例在運行腳本時,向腳本傳遞5個參數,在腳本中調用參數:
[root@kylin ~]# vim para.sh#!/bin/bash#Example of passing parametersecho "當前腳本名稱為$0"echo "總共有$#個參數,分別是$*。"echo "第1個參數為$1,第5個為$5。"[root@kylin ~]# bash para.sh one two three four five six
給腳本添加執行權限,執行結果如下:
[root@kylin ~]# chmod +x para.sh[root@kylin ~]# ./para.sh
當前腳本名稱為para.sh
總共有6個參數,分別是one two three four five six
第1個參數為one,第5個為five
運算符
文件測試運算符
判斷文件是否存在或權限是否滿足等,常用的參數列表如下: | 操作符 | 說明 |
---|---|---|
-d | 測試文件是否為目錄類型,如果是,則返回true | |
-e | 檢查文件(包括目錄)是否存在,如果是,則返回true | |
-f | 測試是否為一般文件(既不是目錄,也不是設備文件),如果是,則返回true | |
-r | 測試當前用戶是否有權限讀取,如果有,則返回true | |
-w | 測試當前用戶是否有權限寫入,如果有,則返回true | |
-x | 測試當前用戶是否有權限執行,如果有,則返回true |
● 實例:判斷/etc/fstab是否為目錄類型的文件:返回值為非零值,代表它不是目錄,或這個目錄不存在
[root@kylin ~]# vim file.sh#!/bin/bashfile="/etc/fstab"if [ -d $file ]then echo "文件$file是一個目錄"else echo "文件$file不是一個目錄或不存在"fi
執行腳本,輸出結果如下:
文件/etc/fstab不是一個目錄或不存在
邏輯運算符
運算符 | 含義 |
---|---|
&& | 邏輯"與" && 前面的命令執行成功后才會執行它后面的命令 |
|| | 邏輯"或" || 前面的命令執行失敗后才會執行它后面的命令 |
! | 邏輯"非" 把條件測試中的判斷結果取相反值,之前是正確則變錯誤,錯誤則變正確 |
● 實例1:判斷/dev/cdrom文件是否存在,若存在則輸出Exist字樣
[root@kylin ~]# [ -e /dev/cdrom ] && echo "Exist"Exist
● 實例2:使用環境變量USER,判斷當前用戶是否為非管理員身份
[root@kylin ~]# echo $USERroot[root@kylin ~]# [ $USER = root ] || echo "user"[root@kylin ~]# su - test [test@kylin ~]$ [ $USER = root ] || echo "user"user
● 實例3:判斷當前登錄的用戶是否為非管理員用戶,若條件成立則輸出user字樣,條件不滿足則輸出root字樣
[root@kylin ~]# [ ! $USER = root ] && echo "user" || echo "root"root
整數比較運算符(關系運算符) 只支持對數字的操作,不能將數字與字符串、文件等內容一起操作。可用的整數比較運算符如表所示: | 操作符 | 作用 |
---|---|---|
-eq | 是否等于 | |
-ne | 是否不等于 | |
-gt | 是否大于 | |
-lt | 是否小于 | |
-le | 是否等于或小于 | |
-ge | 是否大于或等于 |
● 實例1:判斷當前剩余內存大小是否小于1024,若小于則提示"Insufficient Memory",否則提示"Sufficient Memory"(使用free -m命令查看內存使用量情況(單位為MB),通過grep Mem:命令過濾出剩余內存量的行,再用awk {print $4}命令只保留第四列,即可得到剩余內存大小)
[root@kylin ~]# vim mem.sh#!/bin/bashFreeMem=`free -m | grep Mem: | awk {print $4}`[ $FreeMem -lt 1024 ] && echo "Insufficient Memory" || echo "Sufficient Memory"[root@kylin ~]# [root@kylin ~]# chmod +x mem.sh[root@kylin ~]# ./mem.shSufficient Memory
字符串運算符
判斷字符串是否為空值,或兩個字符串是否相同,可用來判斷某個變量是否被定義(即內容為空值)。字符串比較中常見的運算符如表所示: | 操作符 | 作用 |
---|---|---|
= | 比較字符串內容是否相同 | |
!= | 比較字符串內容是否不同 | |
-z | 判斷字符串內容是否為空 |
● 實例1:通過判斷String變量是否為空值,進而判斷是否定義了該變量,返回值為0,則未定義該變量
[root@kylin ~]# [ -z $String ][root@kylin ~]# echo $?0
● 實例2:判斷當前語言環境變量值LANG是否為非英文(en.US),若是,則輸出"Not en.US"字樣
[root@kylin ~]# echo $LANG[root@kylin ~]# [ ! $LANG = "en.US" ] && echo "Not en.US"
流程控制
if條件測試語句
單分支結構:if then fi
● 實例1:適用于終端命令提示符的寫法,如果10等于10,那么輸出"true"
[root@kylin ~]# if [ 10 -eq 10 ]; then echo "true"; fitrue
● 實例2:判斷/media/cdrom目錄是否存在,若不存在就創建這個目錄,反之則結束條件判斷和整個Shell腳本
[root@kylin ~]# vim mkcdrom.sh#!/bin/bashDIR="/media/cdrom"if [ ! -d $DIR ]then mkdir -p $DIRfi
驗證/media/cdrom目錄是否已經成功創建:
[root@kylin ~]# bash mkcdrom.sh[root@kylin ~]# ls -ld /media/cdromdrwxr-xr-x. 2 root root 6 Oct 13 21:34 /media/cdrom
雙分支結構:if then else fi
● 實例1:驗證某臺主機是否在線。返回值若為0,顯示主機在線信息,否則顯示主機不在線信息。(使用ping命令來測試與對方主機的網絡聯通性,-c參數來規定嘗試的次數,-i參數定義每個數據包的發送間隔,-W參數定義等待超時時間。)
[root@kylin ~]# vim chkhost.sh#!/bin/bashping -c 3 -i 0.2 -W 3 $1 &> /dev/nullif [ $? -eq 0 ]then echo "Host $1 is On-line."else echo "Host $1 is Off-line."fi
驗證腳本的效果:
[root@kylin ~]# bash chkhost.sh 10.1.160.183Host 10.1.160.183 is On-line.[root@kylin ~]# bash chkhost.sh 10.1.160.184Host 10.1.160.184 is Off-line.
多分支結構:if then elif then else fi
● 實例1:判斷用戶輸入的分數在哪個成績區間內,輸出Excellent、Pass、Fail等提示信息。(read用來讀取用戶輸入的信息,把接收到的用戶輸入信息賦值給后面的指定變量,-p參數給予用戶一些提示信息。) | 用戶輸入的分數(GRADE) | 輸出信息 |
---|---|---|
85≤GRADE≤100 | Excellent | |
70≤GRADE≤84 | Pass | |
others | Fail |
[root@kylin ~]# vim chkscore.sh#!/bin/bashread -p "Enter your score(0-100):" GRADEif [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; then echo "$GRADE is Excellent"elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then echo "$GRADE is Pass"else echo "$GRADE is Fail" fi[root@linuxprobe ~]# bash chkscore.shEnter your score(0-100):8888 is Excellent[root@linuxprobe ~]# bash chkscore.sh Enter your score(0-100):8080 is Pass
for條件循環語句
● 實例1:批量創建用戶
創建用戶名列表文件,一行一個用戶名:
[root@kylin ~]# vim users.txttest1test2test3test4test5test6
使用read命令讀取用戶輸入的密碼值,賦值給PASSWD變量,通過-p參數向用戶顯示一段提示信息,告訴用戶正在輸入的內容即將作為賬戶密碼。在執行該腳本后,會自動使用從列表文件users.txt中獲取到所有的用戶名稱,然后逐一使用“id 用戶名”命令查看用戶的信息,并使用$?判斷這條命令是否執行成功,也就是判斷該用戶是否已經存在。
[root@kylin ~]# vim addusers.sh#!/bin/bashread -p "Enter The Users Password : " PASSWDfor UNAME in `cat users.txt`do id $UNAME &> /dev/null if [ $? -eq 0 ] then echo "$UNAME , Already exists" else useradd $UNAME &> /dev/null echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null echo "$UNAME , Create success" fidone
運行腳本,并檢查是否創建成功
[root@kylin ~]# bash addusers.shEnter The Users Password : linuxprobetest1 , Create successtest2 , Create successtest3 , Create successtest4 , Create successtest5 , Create successtest6 , Create success[root@kylin ~]# tail -6 /etc/passwd
while條件循環語句
● 實例1:猜測數值大小
使用$RANDOM變量調取一個隨機數(范圍為0~32767),將這個隨機數對1000進行取余操作,并使用expr命令取得其結果,再用這個數值與用戶通過read命令輸入的數值進行比較判斷。
判斷語句分為三種情況,分別是判斷用戶輸入的數值是等于、大于還是小于使用expr命令取得的數值。
while條件循環語句中的條件測試始終為true,因此判斷語句會無限執行下去,直到用戶輸入的數值等于expr命令取得的數值后,運行exit 0命令,終止腳本的執行。
[root@kylin ~]# vim Guess.sh#!/bin/bashPRICE=$(expr $RANDOM % 1000)TIMES=0echo "商品實際價格為0-999之間,猜猜看是多少?"while truedo read -p "請輸入您猜測的價格數目:" INT let TIMES++ if [ $INT -eq $PRICE ] ; then echo "恭喜您答對了,實際價格是 $PRICE" echo "您總共猜測了 $TIMES 次" exit elif [ $INT -gt $PRICE ] ; then echo "太高了!" else echo "太低了!" fidone
運行腳本:
[root@kylin ~]# bash Guess.sh商品實際價格為0-999之間,猜猜看是多少?請輸入您猜測的價格數目:500太低了!請輸入您猜測的價格數目:800太高了!請輸入您猜測的價格數目:650太低了!請輸入您猜測的價格數目:720太高了!請輸入您猜測的價格數目:690太低了!請輸入您猜測的價格數目:700太高了!請輸入您猜測的價格數目:695太高了!請輸入您猜測的價格數目:692太高了!請輸入您猜測的價格數目:691恭喜您答對了,實際價格是 691您總共猜測了 9 次
case條件測試語句
case語句在多個范圍內匹配數據,若匹配成功則執行相關命令并結束整個條件測試;如果數據不在所列出的范圍內,則去執行星號(*)中所定義的默認命令。
● 實例1:判斷用戶輸入內容的類型
提示用戶輸入一個字符并將其賦值給變量KEY,根據變量KEY的值向用戶顯示其值是字母、數字還是其他字符。
[root@kylin ~]# vim Checkkeys.sh#!/bin/bashread -p "請輸入一個字符,并按Enter鍵確認:" KEYcase "$KEY" in [a-z]|[A-Z]) echo "您輸入的是 字母。" ;; [0-9]) echo "您輸入的是 數字。" ;; *) echo "您輸入的是 空格、功能鍵或其他控制字符。"esac[root@linuxprobe ~]# bash Checkkeys.sh請輸入一個字符,并按Enter鍵確認:6您輸入的是 數字。[root@linuxprobe ~]# bash Checkkeys.sh請輸入一個字符,并按Enter鍵確認:p您輸入的是 字母。[root@linuxprobe ~]# bash Checkkeys.sh請輸入一個字符,并按Enter鍵確認:^[[15~您輸入的是 空格、功能鍵或其他控制字符。