[TOC]
shell script (純文本文件) 在系統(tǒng)管理上是一個(gè)好工具, 但是用在處理大量數(shù)值運(yùn)算上就不好了, 因其速度較慢, 且使用CPU資源較多, 容易造成主機(jī)資源分配不良.
? shell script的執(zhí)行至少需要 r 權(quán)限, 若需要命令執(zhí)行, 至少需要 rx權(quán)限.
? && 代表and, || 代表or.
? var=$( 命令 ) 引用命令結(jié)果
? var=$((整數(shù)的運(yùn)算))
? var=${命令或參數(shù)或值}, 變量引用
? 與一般編程語(yǔ)言不同, 等號(hào)左右兩邊不可分.
0. 判斷式
特別要注意一種簡(jiǎn)單的判斷式寫(xiě)法: [ -e $var ] && echo "?$var is existing."
0.1 文件類型
test -e filename 或 [ -e "filename" ]
測(cè)試標(biāo)志 | 代表意義 |
---|---|
-e | 文件名是否存在 |
-f | 文件名是否存在且為文件 (file) |
-d | 文件名是否存在且為目錄 (directory) |
-b | 文件名是否存在且為 bolck device 設(shè)備 |
-c | 文件名是否存在且為 character device 設(shè)備 |
-S | 文件名是否存在且為 Socket device 設(shè)備 |
-p | 文件名是否存在且為 FIFO (pipe) 文件 |
-L | 文件名是否存在且為一個(gè)連接文件 |
0.2 文件權(quán)限
test -r filename 或 [ -r "filename" ]
測(cè)試標(biāo)志 | 代表意義 |
---|---|
-r | 檢測(cè)該文件名是否存在且具有"可讀"的權(quán)限 |
-w | 檢測(cè)該文件名是否存在且具有"可寫(xiě)"的權(quán)限 |
-x | 檢測(cè)該文件名是否存在且具有"可執(zhí)行"的權(quán)限 |
-u | 檢測(cè)該文件名是否存在且具有"SUID"的權(quán)限 |
-g | 檢測(cè)該文件名是否存在且具有"SGID"的權(quán)限 |
-k | 檢測(cè)該文件名是否存在且具有"SBIT"的權(quán)限 |
-s | 檢測(cè)該文件名是否存在且為"非空白文件" |
0.3 文件比較
test file1 -nt file2 或 [ "file1" -nt "file2" ]
測(cè)試標(biāo)志 | 代表意義 |
---|---|
-nt | (newer than) 判斷file1是否比f(wàn)ile2新 |
-ot | (older than) 判斷file1是否比f(wàn)ile2舊 |
-et | 判斷file1于file2是否為同一文件, 可用在hard link的判定上. <br />主要意義在于判定兩個(gè)文件是否均指向同一個(gè)inode |
0.4 整數(shù)判定
test n1 -eq n2 或 [ "n1" -eq "n2" ]
測(cè)試標(biāo)志 | 代表意義 |
---|---|
-eq | equal |
-ne | not equal |
-gt | greater than |
-lt | less than |
-ge | greater than or equal |
-le | less than or equal |
0.5 字符串
test -z str1 或 [ -z "str1" ]
test str1 == str2 或 [ "str1" != "str2" ]
測(cè)試標(biāo)志 | 代表意義 |
---|---|
-z | 判斷str1是否為0, 若為空字符串, 則為true |
-n | 判斷str1是否為非0, 若為空字符串, 則為false<br />注: -n可省略 |
== | 判斷str1和str2是否相等, 若相等, 則回傳true |
!= | 判斷str1和str2是否不相等, 若相等, 則回傳false |
0.6 多重條件
test -r filename -o -w filename 或 [ -r "filename" -o -w "filename" ] 或 [ -r "filename" ] -o [ -w "filename" ]
測(cè)試標(biāo)志 | 代表意義 |
---|---|
-a | 且 |
-o | 或 |
! | 非 |
1. 條件判斷
1.1 if...then...
if [ condition ]; then
程序段
elif [ condition ]; then
程序段
else
程序段
if
1.2 case...esac
只針對(duì)某幾種特殊情況進(jìn)行設(shè)置.
系統(tǒng)很多服務(wù)的啟動(dòng)script都是用這種寫(xiě)法的.
case ${變量名稱} in
"第一個(gè)變量?jī)?nèi)容") #每個(gè)變量?jī)?nèi)容雙引號(hào)括起來(lái), 關(guān)鍵字則為小括號(hào)
程序段
;; #每個(gè)類型結(jié)尾使用兩個(gè)連續(xù)的分號(hào)來(lái)處理
"第二個(gè)變量?jī)?nèi)容")
程序段
;;
*) #最后一個(gè)變量?jī)?nèi)容都會(huì)用*來(lái)代表其他所有值
程序段
exit 1 #此處千萬(wàn)不要忘記!
;;
esac
case支持glob風(fēng)格的通配符:
- * : 任意長(zhǎng)度任意字符
- ? : 任意單個(gè)字符
- [ ] : 指定范圍內(nèi)的任意單個(gè)字符
- a|b : a或b
2. 函數(shù)
實(shí)現(xiàn)功能, 減少重復(fù).
注意shell script的執(zhí)行方式從上到下, 從左到右, 因此shell script中function的設(shè)置一定要寫(xiě)在最前面.
function也是有內(nèi)置變量的.
# 語(yǔ)法一:
function fname() {
...函數(shù)體... #函數(shù)的內(nèi)置變量在函數(shù)定義的代碼塊中有$, 在程序塊中引用函數(shù)時(shí), 無(wú)$
}
# 語(yǔ)法二:
f_name () {
...函數(shù)體...
}
調(diào)用: 函數(shù)只有被調(diào)用才會(huì)執(zhí)行
調(diào)用: 給定函數(shù)名 (函數(shù)名出現(xiàn)的地方, 會(huì)被自動(dòng)替換為函數(shù)代碼)
函數(shù)的生命周期: 被調(diào)用時(shí)創(chuàng)建, 返回時(shí)終止
return命令返回自定義的狀態(tài)結(jié)果:
0: 成功
1 - 255: 失敗
函數(shù)可以接受參數(shù):
傳遞參數(shù)給函數(shù): 調(diào)用函數(shù)時(shí), 在函數(shù)名后面以空白分隔參數(shù)列表即可, 例如: testfunc arg1 arg2
在函數(shù)體中, 可使用$1, $2, ...調(diào)用這些參數(shù), 還可使用$@, $*, $#等特殊變量
變量作用域:
本地變量: 當(dāng)前shell進(jìn)程(當(dāng)前shell腳本程序文件)
局部變量: 函數(shù)的生命周期, 函數(shù)結(jié)束時(shí)被自動(dòng)銷毀
如果函數(shù)中有變量與本地變量名稱相同, 若不用local聲明該變量為局部變量, 則在函數(shù)操作時(shí)會(huì)修改本地變量的值
? 在函數(shù)中定義局部變量的方法:
? local NAME=VALUE
函數(shù)遞歸:
函數(shù)直接或間接調(diào)用自身:
n!=n(n-1)(n-2)...1
斐波那契數(shù)組: 1 1 2 3 5 8 13 ...
foo () {
if [ $1 = 0 -o $1 = 1 ]; then
echo 1
else
echo $[$1*$(foo $[$1-1])]
fi
}
foo 6
febo () {
if [ $1 = 1 -o $1 = 2 ]; then
echo 1
else
echo $[$(febo $[$1-1])+$(febo [$1-2])]
fi
}
febo 10
3. 循環(huán)
3.1 不定循環(huán)
3.1.1 while do done
當(dāng)條件成立, 執(zhí)行循環(huán), 否則停止.
while [ condition ]
do # do是循環(huán)的開(kāi)始
程序段
done # done是循環(huán)的結(jié)束
3.1.2 until do done
直到條件成立, 終止循環(huán), 否則循環(huán)執(zhí)行程序段.
until [ condition ]
do # do是循環(huán)的開(kāi)始
程序段
done # done是循環(huán)的結(jié)束
3.2 固定循環(huán)
3.2.1 for do done
for var in con1 con2 con3 ... # 注: 用空格隔開(kāi), 中間不需要加逗號(hào)!!!
do
程序段
done
3.2.2 for do done的數(shù)值處理
for (( 初始值; 限制值; 執(zhí)行步長(zhǎng) ))
do
程序段
done
# 實(shí)例
# 計(jì)算1加到100的值
sum=0
for ((i=1; i<=100; i=i+1))
do
sum=$(( sum+i )) # shell腳本中計(jì)算時(shí)要用$(( ))
done
4. shell script的追蹤與調(diào)試
# 用法
sh [-nvx] script.sh
# -n 不執(zhí)行腳本, 僅查詢語(yǔ)法問(wèn)題
# -v 在執(zhí)行腳本前, 先將script的內(nèi)容輸出到屏幕上
# -x 將命令的執(zhí)行過(guò)程顯示在屏幕上, 如此用戶便可以判斷程序代碼執(zhí)行到哪一段出了問(wèn)題, 很有用!