退出狀態(tài)
每一條命令;不管是內(nèi)置的,shell 函數(shù),還是外部的,當它退出時,都會返回一個小的整數(shù)值給引用它的程序,這就是大家所熟知的程序的退出狀態(tài)。在 shell 下執(zhí)行進程是,有很多方式可取用程序的退出狀態(tài)。
以管理來說,退出狀態(tài)為 0 表示 “成功”,也就是,程序執(zhí)行完成且為遭遇到任何問題。其他任何的退出退出狀態(tài)都為失敗。內(nèi)置變量?(使用命令 echo $?
) 查看上一條命令的退出狀態(tài)。
案例:當你輸入 ls -l /dev/null
時。
輸出:crw-rw-rw- 1 root root 1,3 6 月 25 15:41 /dev/null
接著使用命令:echo $?
輸出為 0
接著使用命令:ls foo
輸出:ls:無法訪問 foo:沒有那個文件或目錄
echo $?
輸出:2
表示沒有成功的執(zhí)行。
POSIX 的結(jié)束狀態(tài)
值
意義
0
命令成功地退出
\>0
在重定向或單詞展開期間 (~,變量,命令,算數(shù)展開,以及單詞切割) 失敗
1-125
命令不成功的退出。特定的退出值的含義,是由各個單獨的命令定義的。
126
命令找到了,但文件無法執(zhí)行
127
命令沒找到
\>128
命令因受到信號而死亡
POSIX 留下退出狀態(tài) 128 未定義,僅要求他表示某種失敗。因為只有低位的 8 個位會返回給父進程,所以大于 255 的退出狀態(tài)都會替換成該值除以 256 之后的余數(shù)。
在 shell 腳本可以使用 exit 命令傳遞一個退出之給踏的調(diào)用者。只要將一個數(shù)字傳遞給它,作為一個參數(shù)即可。腳本會立即退出,并且調(diào)用者會受到該數(shù)字且作為腳本的退出值。
說白了 exit 就是退出當前的 shell,在 shell 腳本中可以終止當前腳本執(zhí)行。
exit
語法:
exit [exit-value]
用途:
目的是從 shell 腳本返回一個退出狀態(tài)給腳本的調(diào)用者。
主要選項:
無
行為模式:
如果沒有提供,則以最后一個執(zhí)行命令的退出狀態(tài)作為默認的退出狀態(tài)。如果這就是你要的,則最好明白的在 shell 腳本里這么寫:exit $?
案例一:exit
輸出為 logout,表示退出當前 shell
案例二:腳本代碼 cd $(dirname $0) || exit 1
進入腳本所在目錄,否則退出
案例三:腳本中判斷參數(shù)數(shù)量,不匹配就打印使用方式,退出
代碼:
if ["$#" -ne "2"]; then
echo "usage:$0 <area> <hours>"
exit 2
fi
案例四:在腳本里,退出時刪除臨時文件
代碼:trap “入門 -rf tempfile;echo Bye.” exit
案例五:檢查上一行的退出碼 代碼:
EXCODE=$?
if ["$EXCODE" == "0"]; then
echo "O.K"
fi
if-elif-else-fi 語句
if 語法:
if pipeline
[pipeline...]
then
statement-if-true-1
elif pipeline
[pipeline...]
then
statement-iftrue2
else
statement-if-all-else-fails
if
使用方括號作為開始與結(jié)束的關鍵字將語句組織起來。
案例 1:提示用戶指定備份目錄的路徑,若目錄存在則顯示信息跳過,否則顯示相應提示信息,并創(chuàng)建該目錄。 bash 代碼:
\#!/bin/bash
read -p "what is your backup directoy :" BakDir
if [-d $BakDir];then
echo "$BakDir alerdy exist"
else
echo "$BakDir is not exist,will make it"
mkdir $BakDir
fi
案例 2:統(tǒng)計當前登錄到系統(tǒng)中的用戶數(shù)量,若判斷是否超過三個,若是則顯示實際數(shù)量并給出警告信息,否則列出登錄的用戶賬戶名稱及所在終端
bash 代碼:
UserNum='who | wc -l'
if [$UserNum -gt 3];
then
echo "Alert, too many login users (Total:$UserNum)."
else
echo "Login Users:"
who | awk '{print $1,$2}'
fi
注意:
邏輯的 not,and 與 or
“如果 john 不在家,則...” ,在 shell 下這種情況的做法是: 將驚嘆號放在管道前:
if ! grep pattern myfile > /dev/null
then
模式不在這里
fi
“如果 john 在家,且他不忙,則....”,使用邏輯 and。
if grep pattern1 myfile && grep pattern2 myfile
then
myfile 包含兩種模式
fi
相對的,|| 運算符則用來測試兩個條件中是否有一個為真。:
if grep pattern1 myfile || grep pattern2 myfile
then
myfile 包含兩種模式之一
fi
邏輯 and 和 or 都是快捷運算符,即當判斷出整個語句塊的真?zhèn)螘r,shell 會立即停止執(zhí)行命令。舉例來說,在 command1&&command2
下,如果 aommand1
失敗,則整個結(jié)果不可能為真,所以 command2 也不會被執(zhí)行;以此類推,command1||command2
指的是: 如果 command1
成功,那么也沒有理由執(zhí)行 command2
。
不要嘗試過度” 簡練” 未使用 && 和 || 來取代 if 語句。我們不反對簡短且簡單的事情,例如:
命令:who | grep root > /dev/null && echo root is login on root is login on
輸出:root is login on
分析:上面的命令實際做法是: 執(zhí)行 who | grep...
且如果成功,就顯示信息。而我們曾見過廠商提供 shell 腳本,所使用的是這樣的結(jié)構(gòu):
some_command &&{
one command
a decond command
and a third command
}
這個命令的意思是說將所有的語句塊放在一塊,只有在 some_command
成功時他們才被執(zhí)行。使用 if 可以讓他更簡潔:
if some_command
then
one command
a second command
and a third command
fi
最后在判斷語句中常用的運算符:
1、字符串判斷
str1 = str2 當兩個串有相同內(nèi)容、長度時為真
str1 != str2 當串 str1 和 str2 不等時為真
-n str1 當串的長度大于 0 時為真 (串非空)
-z str1 當串的長度為 0 時為真 (空串)
str1 當串 str1 為非空時為真
2、數(shù)字的判斷
int1 -eq int2 兩數(shù)相等為真
int1 -ne int2 兩數(shù)不等為真
int1 -gt int2int1 大于 int2 為真
int1 -ge int2int1 大于等于 int2 為真
int1 -lt int2int1 小于 int2 為真
int1 -le int2int1 小于等于 int2 為真
3、文件的判斷
-r file 用戶可讀為真
-w file 用戶可寫為真
-x file 用戶可執(zhí)行為真
-f file 文件為正規(guī)文件為真
-d file 文件為目錄為真
-c file 文件為字符特殊文件為真
-b file 文件為塊特殊文件為真
-s file 文件大小非 0 時為真
-t file 當文件描述符 (默認為 1) 指定的設備為終端時為真
4、復雜邏輯判斷
-a 與
-o 或
! 非
test 命令
test 命令可以處理 shell 腳本里的各類工作。它產(chǎn)生的不是一般輸出,而是可使用的退出狀態(tài)。test 接受各種不同的參數(shù),可控制它要執(zhí)行哪一種測試。
test 命令有另一種形式:[...],這種永福的作用完全與 test 命令一樣。因此,下面這兩個案例表達的意思相同
if test "$str1"="$str2"
then
...
fi
和
if ["$str1" = "$str2" ]
then
...
fi
一樣
test 的語法:
test [expression] [[expression] ]
用途:
為了測試 shell 腳本里的條件,通過退出狀態(tài)返回其結(jié)果。要特別注意的是:這個命令的第二種形式,方括號根據(jù)字面意義逐字的輸入,且必須與括起來的 expression 以空白隔開。
主要選項: 和使用用于 if 的選項一致。 其中
選項
含義
string
如果... 則為真
-b file
file 是塊設備文件
-d file
file 是目錄
-c file
file 是字符設備文件
-e file
file 存在
-f file
file 為一般文件
-g file
file 有設置他的 setgid 位
-h file
file 是一符號鏈接
-L file
file 是一符號鏈接 (等同于 -h)
-n string
string 是非 null
-p file
file 是一命名的管道 (FIGO 文件)
-r file
file 是可讀的
-S file
file 是 socket
-s file
file 不是空的
-t n
文件描述符 n 指向一終端
-u file
file 有設置它的 setuid 位
-w file
file 是可寫入的
-x file
file 是可執(zhí)行的,或 file 是可被查找的目錄
-z string
string 為 null
s1=s2 或者 s1!=s2
字符串相不相等
n1 -eq n2
整數(shù) n1 等于 n2
n1 -ne n2
整數(shù) n1 不等于 n2
n1 -lt n2
n1 小于 n2
n1 -gt n2
n1 大于 n2
n1 -le n2
n1 小于或等于 n2
n1 -ge n2
n1 大于或等于 n2
案例:
bash 代碼:
\#!/bin/bash
cd /bin
if test -e ./bash // 其實這里相當于 if [-e ./bahs]
then
echo 'the file already exist!'
else
echo 'the file not exist!'
fi
輸出結(jié)果為:the file already exist!
另外,shell 還提供了 -a
(邏輯 AND),-o
(邏輯 OR),-a
的優(yōu)先級高于 -o
,而 = 與!= 優(yōu)先級則高于其他的二元運算符。
注意:在使用 -a
和 -o
(這兩個事 test 運算符) 與 &&
和 ||
(這兩個事 shell 運算符) 之間有一個差異:
if [-n "$str" -a -f "$file" ]
一個 test 命令,兩種條件if [-n "str"] && [-f "$file" ]
兩個命令,一塊接方式計算if [-n "$str" && -f "$file"]
語法錯誤第一個案例,test 會計算兩種條件。而第二個案例,shell 執(zhí)行第一個 test 命令,且只有在第一個命令是成功的情況下,才會執(zhí)行第二個命令。最后一個案例,&&
為 shell 運算符,所以它會終止第一個 test 命令,然后這個命令會抱怨它找不到結(jié)束的] 字符,且以失敗的值退出。即使 test 可以成功的退出,接下來的檢查還會失敗,因為 shell(最有可能) 找不到一個名為 -f
的命令
精簡表達式:
使用命令:[1 eq1] &&echo'OK'
輸出:ok
使用命令:[2 < 1] &&echo 'OK'
輸出:-bash:1:No such file or directory
使用命令:[2 \< 1] &&echo 'OK'
這樣就可以了
使用命令:[2 -gt 1 -a 3 -lt 4]&&echo 'Ok'
輸出:Ok
使用命令:[2 -gt 1 && 3 -lt 4]&&echo 'Ok'
輸出:-bash:[:missing `]'
注意:在 []
表達式中,常見的 >
,<
需要加轉(zhuǎn)義字符,表示字符串大小比較,以 acill 碼位置作為比較。不直接支持 <>
運算符,還有邏輯運算符 ||
和 &&
它需要用 -a[and] –o[or]
表示。
剛才使用的 []
,現(xiàn)在再來看使用 [[]]
案例:
使用命令:[[2 < 3]]&&echo 'OK'
輸出 OK。
使用命令:[[2 < 3 && 4 < 5]] && echo 'ok'
輸出:ok
注意:[[]]
運算符只是 []
運算符的擴充。能夠支持 <
,>
符號運算不需要轉(zhuǎn)義符,它還是以字符串比較大小。里面支持邏輯運算符 ||
和 &&
。 bash 的條件表達式中有三個幾乎等效的符號和命令:test
,[]
和 [[]]
。通常,大家習慣用 if []
;then
這樣的形式。而 [[]]
的出現(xiàn),根據(jù) ABS 所說,是為了兼容 ><
之類的運算符。
不考慮對低版本 bash 和對 sh 的兼容的情況下,用 [[]]
是兼容性強,而且性能比較快,在做條件運算時候,可以使用該運算符。