第11章 結構化命令
if-then
testuser=rich if grep $testuser /etc/passwd ;then echo The bash file for user $testuser are: ls -a /home/$testuser/.b* fi
if-then-else
if comA; then comB else comC fi if com1;then com2 elfi com3;then com4 fi
test 測試判斷
if test condition <==> if [condition] then commands fi 數值比較 A -eq B = [ $var1 -gt 5 ] -ge >= [ $var1 -eq $var2 ] -gt > -le <= -lt < -ne != test無法處理變量中的浮點值 字符串比較 相等 [ "$USER" = "$testuser" ] 轉義大小於號 [ $var1 \> $var2 ],否則會重定向 test中 用ASCII順序 T < t sort中 用系統本地化設置 t < T 大小: 應在進行字符串運算時判斷是否爲空 if [ -n "$var1" ] 是否非空 if [ -z "$var1" ] 是否爲空 未被定義過的字符串長度爲0 文件比較 -e file 文件存在? -s 存在&非空? -d.-f 目錄,文件 -r. -w.-x可讀可寫可執行 -O 屬當前用戶所有? -G文件默認組與當前用戶same? A -nt B A 比 B 新 -ot 舊 雙方括號 模式匹配 if [[ $USER == r* ]] 複合條件測試 [cond1] && [cond2] <==> -a [cond1] || [cond2] <==> -o 雙尖括號 if (( $var1 ** 2 > 90 ));then (( var2 = $var1 ** 2)) <==> var2=$[$var1 ** 2] fi case case $USER in rich|bar) echo ;; testing) echo ;; *) echo ;; esac
第12章 循環
for var in list
do
commands
done
讀取列表中的複雜值
for test in I don\'t know if "this'll" work
do
echo $test
done
當包含空格時,雙引號括起來
./test.sh
I
don't
know
if
this'll
work
從變量讀取列表
list="AB CD EF"
list1=$list"GH JK"
for i in $list1
do
echo $i
done
從命令讀取
file="/etc/passwd"
for i in cat $file
do echo "$i" done 分隔符 IFS.old=$IFS IFS=$'\n' IFS=$IFS.old 通配符讀取目錄 for file in $HOME/.b* do if [ -f "$file" ] done 雙引號防止文件名或目錄名中有空格 c 風格 for((a=1;a<10;a++)) do commA done while [ $var1 -gt 0 ] do var1=$[ $var1 - 1 ] <==> ((var1 = $var1 - 1)) done 在while中若定義多個測試命令,則取最後一個測試命令的退出狀態碼爲執行條件 until 與while相反, 當$? != 0時,執行 在循環處理文件數據時 可在外部循環中,設置IFS=$'\n'獲取一行 在內部循環中,eg:/etc/passwd IFS=:獲取單個信息 break n跳出n層循環 處理輸出 for(()) do done > test.log 也可以對輸出排序 done | sort
第13章 獲取輸入
echo -n "Enter your name" read name echo "hello name" 或者 read -p "Enter your name:" first last 多餘的變量分配給最後一個變量 -n移除了字符串末尾的換行符 若read 行不指定變量,則read將收到的數據放到環境變量REPLY中 超時: -t指定計時器 超時後返回非零退出狀態 if read -t 5 -p "Please enter your name:" name then commA else commB fi 輸入字符計數 -n1 按下單字符無需換行 read -n1 -p " Do you want to continue [Y/N]?" answer case $answer in Y/y) echo ; N/n) echo ; 隱藏輸入: read -s -p "Enter your password" passwd 從文件中讀取: cat test | while read line do done 腳本獲取外部參數 獲取外部輸入參數時,使得 $1,$2 shell會自動識別,num或string 當有輸入含空格的參數時,需引號圈起來 當參數個數大於9時,${10}, ${11} 讀取程序名,不是完整的路徑名 name=` basename $0 ` 可實現基於不同的腳本來執行不同的命令腳本。 需測試參數個數: if [ -n "$1" ] $1 存在或者不存在 參數計數: $# if [ $# -ne 2 ] 最後一個參數: ${$#}錯誤的方式,因爲在{}內不能使用$ ${!#} 對 抓取參數: $* 會將所有參數當成單個參數 $@ 會單獨處理每個參數 移動變量 shift將所有參數左移 當參數被移除後,值會被丟失且無法恢復。 while [ -n "$1"] do commA shift done 處理選項:將 while+shift+case 混合使用 -- 一般分隔選項和參數
第14章 重定向錯誤
只重定向錯誤: ls -sail badfile 2>test4 將錯誤重定向到 test4,標準輸出定向到終端顯示器
ls -al test test2 2>test3 1>test4
若重定向到同一個文件:&> shell 會給予錯誤消息更高的優先級,所以顯示在開頭。
在腳本中重定向到輸出 (臨時和永久)
臨時重定向 腳本中 echo "This is an error" >&2 運行時 ./test 2>test9 永久重定向 腳本內部 exec 1> testout exec 2> testerror 一旦重定STDOUT或STDERR,將無法輕易回覆 腳本中重定向輸入: exec 0<testfile while read line do done 創建輸出文件描述符 exec 3>test echo " " >&3 正確的重定向輸出文件描述符: exec 3>&1 exec 1>testout exec 1>&3 恢復文件描述符1 理解: a3=a1 a1=t a1=a3 正確的重定向輸入文件描述符 exec 6<&0 exec 0<testfile exec 0<&6 理解: a3=a1 a1=t a1=a3 創建讀寫文件描述符 exec 3<> testfile read line <&3 echo " " >&3 回因爲覆蓋而產生混亂 關閉文件描述符 exec 3>&- 若關閉後在之後shell腳本命令中打開,則會產生一個新文件來替換已有文件, 所以新的輸出會覆蓋已有文件 列出打開的文件描述符 #lsof -a -p $$ bash 27677 sholck 0u CHR 136,1 0t0 4 /dev/pts/1 bash 27677 sholck 1u CHR 136,1 0t0 4 /dev/pts/1 bash 27677 sholck 2u CHR 136,1 0t0 4 /dev/pts/1 bash 27677 sholck 255u CHR 136,1 0t0 4 /dev/pts/1 阻止命令輸出: /dev/null 任何重定向到該位置的數據都會丟掉 將/dev/null作爲輸入文件來清空文件內容 cat /dev/null > testfile 用來清除日誌。 記錄消息tee stdout----->STDOUT | |------> file date | tee testfile date | tee -a testfile 追加 創建臨時文件 系統會在啓動時自動刪除/tmp目錄下的文件 任何用戶都有在/tmp 讀寫的權限 創建本地當前目錄臨時文件: #mktemp testing.XXXXXX testing.hOIz4y 在/tmp下創建臨時文件 #mktemp -t testing.XXXXXX /tmp/testing.H
謙讓度
VU3BI 創建臨時目錄: #mktemp -d dir.XXXXXXX dir.ljpG8IU
第15章 定時處理與信號
定時
at -f test 6:25 > /dev/tty2 列出等待中的at作業:atq at -l at -d 刪除at作業 at -c 1查看at作業內容 定期執行腳本 cron 時間表 min hour dayofmonth month dayofweek command 15 16 * * 1 command crontab -l 列出已有時間表 cron 列表 /etc/cron.daily /etc/cron.monthly 若需每天運行一次,將腳本複製到daily目錄 anacron 運行錯過的作業 根據時間戳來決定作業是否被運行過。/var/spool/anacron.monthly anacron時間表 period 多久運行一次 delay 開機後延遲多少分鐘運行錯過的腳本 identifer command 啓動運行時 開機腳本 /etc/rc#.d /etc/init.d /etc/init.d/rc.d $HOME/.bash_profile -->登錄shell $HOME/.bashrc -->啓動shell /etc/bashrc --->所有用戶
處理信號
1.SIGHUP 掛起 2.SIGINT 3.SIGQUIT 9.SIGKILL 15.SIGTERM 終止進程 17. SIGSTOP 停止進程 18. SIGTSTP shell默認忽略SIGUIT SIGTERM Ctrl+c SIGINT Ctrl+z SIGTSTP 暫停 ps au 查看已停止的作業 捕捉信號
謙讓度
trap "echo 'Sorry! I have trapped Ctrl+c'" SIGINT SIGTERM 捕捉腳本退出 trap "echo byebye" EXIT 移除捕捉 trap -EXIT 當後臺進程在運行時,仍會使用終端來顯示STDOUT與STDERR的消息 如果進程會話退出,後臺進程也會退出
脫離終端+作業控制+謙讓度
在非控制檯下運行腳本 nohup ./test1 & 阻斷髮送給該進程的SIGHUP信號 因爲已解除終端和進程的關聯,故將STDOUT與STDERR重定向到名爲nohup.out的文件中。 作業控制 $$表示該腳本的PID jobs 查看作業 [1]+ 默認作業 [2] - 下一個默認作業 只能有一個+和一個-作業 重啓停止作業 後臺 bg 2->作業號 前臺 fg 1 謙讓度 nice -n 10 ./test4 > testout & -n 指定優先級 renice 改變已運行進程的優先級 renice 10 -p 29504 29504 is process-id