說明:本文部分內(nèi)容均摘取自書籍《Linux命令行與shell腳本編程大全》,版權(quán)歸原作者所有?!禠inux命令行與shell腳本編程大全》(第三版)第十六章學(xué)習(xí)總結(jié)
第十六章:控制腳本
本章內(nèi)容
處理信號
以后臺模式運行腳本
禁止掛起
作業(yè)控制
修改腳本優(yōu)先級
腳本執(zhí)行自動化
16.1 處理信號
16.1.1 重溫Linux信號
Linux系統(tǒng)信號
Linux利用信號與運行在系統(tǒng)中的進(jìn)程進(jìn)行通信
可以使用信號來停止/啟動/終止進(jìn)程
可以通過對腳本進(jìn)行編程,使其在收到特定信號時執(zhí)行某些命令,從而控制shell腳本
默認(rèn)情況下,bash shell會忽略收到的任何3和15信號
但是bash shell會處理1和2信號
常見的Linux系統(tǒng)信號
信號:值:描述
1:SIGHUP:掛起進(jìn)程
2:SIGINT:終止進(jìn)程
3:SIGQUIT:停止進(jìn)程
9:SIGKILL:無條件終止進(jìn)程
15:SIGTERM:盡可能終止進(jìn)程
17:SIGSTOP:無條件停止進(jìn)程,但不是終止進(jìn)程
18:SIGTSTP:停止或暫停進(jìn)程,但不終止進(jìn)程
19:SIGCONT:繼續(xù)運行停止的進(jìn)程
16.1.2 生成信號
1.中斷進(jìn)程
使用Ctrl+C組合鍵會生成2(SIGINT)信號,并將其發(fā)送給當(dāng)前在shell中運行的所有進(jìn)程
執(zhí)行命令
sleep 100
^C
注:^代指Ctrl鍵
2.暫停進(jìn)程
使用Ctrl+Z組合鍵會生成18(SIGTSTP)信號,停止shell中運行的任何進(jìn)程
執(zhí)行命令
sleep 100
^Z
當(dāng)按鍵Ctrl+Z組合鍵時,bash shell會給出如下提示
[1]+ Stopped sleep 100
方括號中的數(shù)字時shell分配的作業(yè)號(job number)
shell將shell中運行的每個進(jìn)程稱為作業(yè),并為每個作業(yè)分配唯一的作業(yè)號
如果shell回話中有已停止的作業(yè),在退出shell時,bash會提醒你
常用操作
ps -l
查看已停止的作業(yè),在S列中(進(jìn)程狀態(tài))顯示T的為已停止的作業(yè)
kill -9 PID
終止指定PID的作業(yè),終止已停止作業(yè)的PID
通俗來講,就是殺掉進(jìn)程
16.1.3 捕獲信號
命令格式:trap commands signals
命令說明:使用trap命令來指定shell腳本要監(jiān)看并從shell中攔截的Linux信號
使用trap命令來忽略SIGINT信號
編寫test1.sh腳本
#!/bin/bash
trap "echo 'Sorry!I have trappend Ctrl-C'" SIGINT
echo This is a test script
count=1
while [ $count -le 10 ]
do
echo "Loop #$count"
sleep 1
count=$[ $count+1 ]
done
echo "This is the end of the test script"
16.1.4 捕獲腳本退出
捕獲shell腳本的退出EXIT信號
編寫test2.sh腳本
#!/bin/bash
trap "echo Goodbye..." EXIT
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 1
count=$[ $count+1 ]
done
16.1.5 修改或移除捕獲
修改信號捕獲,腳本仍然會根據(jù)最初的trap命令進(jìn)行處理
編寫test3.sh腳本
#!/bin/bash
#
trap "echo 'Sorry.. Ctrl+C is trapped.'" SIGINT
#
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 1
count=$[ $count+1 ]
done
#
trap "echo 'I modified the trap!'" SIGINT
#
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 1
count=$[ $count+1 ]
done
在trap和信號列表之間加上兩個破折號刪除已設(shè)置好的捕獲并恢復(fù)默認(rèn)行為
編寫test3b.sh腳本
#!/bin/bash
#
trap "echo 'Sorry.. Ctrl+C is trapped.'" SIGINT
#
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 1
count=$[ $count+1 ]
done
#
# Remove the trap
trap -- SIGINT
echo "I just removed the trap"
#
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 1
count=$[ $count+1 ]
done
敲門:也可以在trap命令后使用單破折號來恢復(fù)信號的默認(rèn)行為。單破折號和雙破折號都可以正常發(fā)揮作用
16.2 以后臺模式運行腳本
16.2.1 后臺運行腳本
在命令后加個&符以后臺模式運行shell腳本
編寫test4.sh腳本
#!/bin/bash
count=1
while [ $count -le 10 ]
do
sleep 1
count=$[ $count+1 ]
done
執(zhí)行命令
./test4.sh &
然后顯示[1] 3231
方括號中的表示后臺進(jìn)程的作業(yè)號,后面的數(shù)字為進(jìn)程的進(jìn)程ID(PID)
當(dāng)后臺進(jìn)程運行時,它仍然會使用終端顯示器來顯示STDOUT和STDERR消息
編寫test5.sh腳本
#!/bin/bash
#
echo "Start the test script"
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 5
count=$[ $count+1 ]
done
#
echo "Test script is complete"
當(dāng)腳本在后臺模式運行時,腳本的輸出和輸入的命令以及命令輸出全都混在了一起,最好是將后臺運行的腳本的STDOUT和STDERR進(jìn)行重定向,避免雜亂的輸出
16.2.2 運行多個后臺作業(yè)
可以使用&符號的方法在命令行提示符下同時啟動多個后臺作業(yè)
使用ps命令查看所有腳本的運行狀態(tài)
在終端會話中使用后臺進(jìn)程時一定要小心,當(dāng)退出終端時,后臺進(jìn)程也會退出
16.2.3 在非控制臺下運行腳本
命令格式:nohup ./test1.sh &
命令說明:使用nohup命令在終端會話中啟動shell腳本,并讓腳本一直以后臺模式運行到結(jié)束,即使退出了終端會話,shell腳本也會一直運行
執(zhí)行命令
nohup ./test1.sh &
cat nohup.out
說明
使用nohup啟動shell腳本時,腳本會忽略終端會話發(fā)過來的SIGHUP信號
由于nohup命令會解除終端與進(jìn)程的關(guān)聯(lián),進(jìn)程也就不在同STDOUT和STDERR關(guān)聯(lián)
nohup命令會自動將STDOUT和STDERR的消息重定向到當(dāng)前目錄下名為nohup.out的文件中
如果使用nohup命令運行了另一個腳本,則該腳本的輸出會被追加到已有的nohup.out文件中
16.4 作業(yè)控制
啟動/停止/終止以及恢復(fù)作業(yè)的這些功能統(tǒng)稱為作業(yè)控制
16.4.1 查看作業(yè)
使用jobs命令查看shell當(dāng)前正在處理的作業(yè),腳本$$變量顯示Linux系統(tǒng)分配給該腳本的PID
編寫test10.sh腳本
#!/bin/bash
#
echo "Script Process ID: $$"
#
count=1
while [ $count -le 10 ]
do
echo "Loop #$count"
sleep 10
count=$[ $count + 1 ]
done
#
echo "End of script..."
#
執(zhí)行命令
./test10.sh > test10.out &
查看作業(yè)
jobs
查看作業(yè)的PID
jobs -l
jobs命令參數(shù)
參數(shù):描述
-l:列出進(jìn)程的PID以及作業(yè)號
-n:只列出上次shell發(fā)出的通知后改變了狀態(tài)的作業(yè)
-p:只列出作業(yè)的PID
-r:只列出運行中的作業(yè)
-s:只列出已停止的作業(yè)
jobs命令輸出中的加號和減號
帶加號的作業(yè)會被當(dāng)做默認(rèn)作業(yè)
在使用作業(yè)控制命令時,如果未在命令行指定任何作業(yè)號,
該作業(yè)會被當(dāng)做作業(yè)控制命令的操作對象
當(dāng)前的默認(rèn)作業(yè)完成處理后,帶減號的作業(yè)成為下一個默認(rèn)作業(yè)
任何時候都只有一個帶加號的作業(yè)和一個帶減號的作業(yè),
不管shell中有多少個正在運行的作業(yè)
16.4.2 重啟停止的作業(yè)
命令格式:bg 作業(yè)號
命令說明:以后臺模式重啟指定作業(yè)
命令格式:fg 作業(yè)號
命令說明:以前臺模式重啟指定作業(yè)
16.6 定時運行作業(yè)
16.6.1 用at命令來計劃執(zhí)行作業(yè)
1.at命令的格式
命令格式:at [-f filename] time
命令說明:使用-f參數(shù)指定需要執(zhí)行的腳本文件的文件名,time參數(shù)制定了什么時候運行
多種不同的時間格式
標(biāo)準(zhǔn)的小時和分鐘格式,比如10:15
AP/PM指示符,比如10:15PM
特定可命名時間,比如now,noon,midnight或teatime(4PM)
標(biāo)準(zhǔn)日期格式,比如MMDDYY,MM/DD/YY或DD.MM.YY
文本日期,比如Junl4或Dec25,加不加年份均可
也可以指定時間增量
當(dāng)前時間+25min
明天10:15PM
10:15+7天
2.獲取作業(yè)的輸出
在Linux系統(tǒng)上運行時,顯示器并不會關(guān)聯(lián)到該作業(yè)。Linux系統(tǒng)會將STDOUT或STDERR的輸出通過郵件系統(tǒng)發(fā)送給用戶
編寫test13.sh腳本
#!/bin/bash
echo "This script ran at $(date +%B%d,%T)"
echo
sleep 5
echo "This is the script end..."
執(zhí)行命令
at -f test13.sh now
使用-M選項來屏蔽作業(yè)產(chǎn)生的輸出信息
編寫test13b.sh
#!/bin/bash
echo "This script ran at $(date +%B%d,%T)" > test13b.out
echo >> test13b.out
sleep 5
echo "This is the script end..." >> test13b.out
執(zhí)行命令
at -M -f test13b.sh now
cat test13b.out
3.列出等待的作業(yè)
atq命令查看系統(tǒng)中有哪些作業(yè)在等待,顯示作業(yè)列表
作業(yè)列表中顯示了作業(yè)號,系統(tǒng)運行該作業(yè)的日期和時間及其所在的作業(yè)隊列
4.刪除作業(yè)
命令格式:atrm 作業(yè)號
命令說明:使用atrm刪除指定作業(yè)
16.6.2 安排需要定期執(zhí)行的腳本
1.cron時間表
命令格式:min hour dayofmonth month dayofweek command
命令說明:cron時間表采用一種特別的格式來指定作業(yè)何時運行
格式說明
dayofweek:文本(mon,tue,wed,thu,fri,sat,sun)或數(shù)值(0為周日,6為周六)
dayofmonth:表示月份中的日期值(1~31)
cron實例
在每天的10:15運行一個命令
15 10 * * * command
在每周一4:15PM運行的命令
15 16 * * 1 command
在每個月的第一天中午12點執(zhí)行命令
00 12 1 * * command
在每個月的最后一天執(zhí)行命令
00 12 * * * if [‘date +%d -d tomorrow’ = 01]; then;command
說明:在每天中午12點檢查是不是當(dāng)月的最后一天,如果是,cron將會運行該命令
執(zhí)行命令
15 10 * * * /home/zc/test/unit16/test4.sh > test4.out
2.構(gòu)建cron時間表
Linux提供了 crontab來處理cron時間表,使用cron時間表來運行安排好的任務(wù)
命令格式:crontab -l
命令說明:使用crontab -l列出已有的cron時間表
3.瀏覽cron目錄
如果創(chuàng)建的腳本對精確的執(zhí)行時間要求不高,則可以使用預(yù)配置的cron腳本目錄
四個基本目錄
hourly:每小時執(zhí)行
daily:每天執(zhí)行
monthly:每月執(zhí)行
weekly:每周執(zhí)行
執(zhí)行命令
ls /etc/cron.*ly
16.6.3 使用新shell啟動腳本
每次啟動一個新shell時,bash shell都會運行$HOME/.bashrc文件
驗證
在$HOME/.bashrc文件的最后加入:echo "I'm in a new shell"
然后保存,關(guān)閉shell終端
重新打開shell終端時,可以看見該提示語
16.7 小結(jié)
本章主要講解了linux中的信號控制,以后臺模式執(zhí)行腳本,指定時間執(zhí)行腳本,修改腳本的優(yōu)先級等。
謝謝