技術(shù)交流QQ群:1027579432工扎,歡迎你的加入徘钥!
歡迎關(guān)注我的微信公眾號:CurryCoder的程序人生
1.引言
- 目前為止,運行腳本的唯一方式是以實時模式在命令行界面上直接運行肢娘。但是呈础,這并不是Linux上運行腳本的唯一方式舆驶。
2.處理信號量
- Linux利用信號與運行在系統(tǒng)中的進程進行通信。不同的Linux信號以及Linux如何用這些信號來停止而钞、啟動沙廉、終止進程【式冢可以通過對腳本進行編程撬陵,使其在收到特定信號時執(zhí)行某些命令,從而控制shell腳本的操作网缝。
2.1 重溫Linux信號
- Linux系統(tǒng)和應(yīng)用程序可以生成超過30個信號巨税,下面列出了Linux編程時遇到的最常見Linux系統(tǒng)信號。
信號 值 描述 1 SIGHUP 掛起進程 2 SIGINT 終止進程 3 SIGQUIT 停止進程 9 SIGKILL 無條件終止進程 15 SIGTERM 盡可能終止進程 17 SIGSTOP 無條件停止進程粉臊,但不是終止進程 18 SIGTSTP 停止或暫停進程,但不終止進程 19 SIGCONT 繼續(xù)運行停止的進程
-
默認情況下,bash shell會忽略收到的任何SIGQUIT(3)和SIGTERM(15)信號(正因為如此珊蟀,交互式shell才不會意外停止)途蒋。但是,bash shell會處理收到的SIGHUP(1)和SIGINT(2)信號犀盟。
- 如果bash shell收到了SIGHUP信號而晒,比如你要離開一個交互式shell,它就會退出阅畴。但是在退出之前倡怎,它會將SIGHUP信號傳遞給所有由該shell所啟動的進程。
- 通過SIGINT信息贱枣,可以中斷shell监署。Linux內(nèi)核會停止為shell分配CPU處理時間。這種情況發(fā)生時纽哥,shell會將SIGINT信號傳遞給所有由它所啟動的進程钠乏。
2.2 生成信號
- bash shell允許使用鍵盤上的組合鍵生成兩種基本的Linux信號,這個特性在需要停止或暫停失控程序時非常方便春塌。
-
中斷進程:Ctrl+C組合鍵可以生成SIGINT信號晓避,并將該信號發(fā)送給當前在shell中運行的所有進程,停止shell中當前運行的進程只壳。如下例所示:
$ sleep 100 ^C
-
暫停進程:可以在進程運行期間暫停進程俏拱,無需終止它。它可以在不終止進程的情況下吼句,使你能夠深入腳本內(nèi)部仔細觀察锅必。Ctrl+Z組合鍵會生成一個SIGTSTP信號,暫停shell中運行的任何進程惕艳。暫停進程與中斷進程不同:暫停進程會讓程序繼續(xù)保留在內(nèi)存中搞隐,并能從上次暫停的位置繼續(xù)運行驹愚。如下例所示:
[njust@njust ~]$ sleep 10 ^Z [1]+ 已停止 sleep 10
- 上述示例中,方括號中的數(shù)字是shell分配的作業(yè)號劣纲,shell將shell中運行的每個進程稱為作業(yè)逢捺,并為每個作業(yè)分配唯一的作業(yè)號。它會給第一個作業(yè)分配作業(yè)號1癞季,第二個作業(yè)分配作業(yè)號2蒸甜,依次類推。
- 如果你的shell會話中有一個已暫停的作業(yè)余佛,在退出shell時柠新,只要再輸入一遍exit命令bash會提醒你。如下所示:
[njust@njust ~]$ sleep 10 ^Z [1]+ 已停止 sleep 10 [njust@njust ~]$ exit exit 有停止的任務(wù)辉巡。
- 可以還有ps命令查看已經(jīng)暫停的作業(yè)恨憎,如下所示:
[njust@njust ~]$ sleep 10 ^Z [2]+ 已停止 sleep 10 [njust@njust ~]$ ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 S 1000 3377 3369 0 80 0 - 29140 do_wai pts/0 00:00:00 bash 0 T 1000 3642 3377 0 80 0 - 26989 do_sig pts/0 00:00:00 sleep 0 R 1000 3733 3377 0 80 0 - 38312 - pts/0 00:00:00 ps
- 在S列(進程狀態(tài))中,ps命令將已暫停作業(yè)的狀態(tài)顯示為T郊楣,可以通過已暫停作業(yè)的PID憔恳,就可以用kill命令來發(fā)送一個SIGKILL信號來終止它。如下例所示:
[njust@njust ~]$ kill -9 3642 [1]- 已殺死 sleep 10
2.3 捕捉信號
- trap命令允許你來指定shell腳本要監(jiān)控并從shell中攔截的Linux信號净蚤,如果腳本收到了trap命令中列出的信號钥组,該信號不再由shell處理,而是交由本地處理今瀑。trap命令的格式如下:
trap commands signals
- 從上述trap命令的格式來看程梦,在trap命令行上,只要列出想要shell執(zhí)行的命令橘荠,以及一組用空格分開的待捕獲的信號即可屿附。如下例所示:使用trap命令來忽略SIGINT信號,并控制腳本的行為哥童。
#!/bin/bash trap "echo ' Sorry! I have trapped Ctrl-C'" SIGINT echo "This is a test script" count=1 while [ $count -le 10 ] do echo "Loop #$count" sleep 2 count=$[ $count + 1 ] done echo "This is the end of the test script" # 結(jié)果 [njust@njust tutorials]$ ./control1.sh This is a test script Loop #1 Loop #2 ^C Sorry! I have trapped Ctrl-C Loop #3 Loop #4 ^C Sorry! I have trapped Ctrl-C Loop #5 Loop #6 ^C Sorry! I have trapped Ctrl-C Loop #7 Loop #8 ^C Sorry! I have trapped Ctrl-C Loop #9 Loop #10 This is the end of the test script
- 上述示例程序使用trap命令在每次檢測到SIGINT信號時挺份,會顯示一行簡單的文本消息。捕獲這些信號會阻止用戶用bash shell組合鍵來Ctrl+C來停止程序運行贮懈。
2.4 捕獲腳本退出
- 除了在shell腳本中捕獲信號匀泊,也可以在shell腳本退出的時候進行捕獲。要想捕獲shell腳本的退出朵你,只要在trap命令后加上EXIT信號即可各聘。如下例所示:
#!/bin/bash trap "echo Goodbye..." EXIT count=1 while [ $count -le 5 ] do echo "Loop #$count" sleep 1 count=$[ $count + 1 ] done
- 上述示例程序中,當腳本運行到正常的退出位置時撬呢,捕獲就被觸發(fā)伦吠,shell會執(zhí)行trap命令妆兑。如果提前退出腳本魂拦,同樣能捕獲到EXIT信號毛仪。
2.5 修改或移除捕獲
- 如果一個信號在捕獲被修改前接收到的,那么腳本仍然會根據(jù)最初的trap命令進行處理芯勘。如下例所示:
#!/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 "Second Loop #$count" sleep 1 count=$[ $count + 1 ] done # 結(jié)果 [njust@njust tutorials]$ ./control3.sh Loop #1 Loop #2 Loop #3 Loop #4 ^C Sorry... Ctrl-C is trapped. Loop #5 Second Loop #1 Second Loop #2 Second Loop #3 ^C I modified the trap!
- 可以刪除已經(jīng)設(shè)置好的捕獲:只要在trap命令與希望恢復(fù)默認行為的信號列表之間加上兩個破折號即可,但如果信號是在捕獲被移除前接收到的荷愕,那么腳本會按照原先trap命令中的設(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 -- SIGINT # 此處已經(jīng)刪除已經(jīng)設(shè)置好的捕獲,因此最前面設(shè)置的捕獲SIGINT信號將會失效安疗! echo "I just removed the trap" count=1 while [ $count -le 5 ] do echo "Second Loop #$count" sleep 1 count=$[ $count + 1 ] done # 結(jié)果 [njust@njust tutorials]$ ./control4.sh Loop #1 Loop #2 Loop #3 ^C Sorry... Ctrl-C is trapped. Loop #4 Loop #5 I just removed the trap Second Loop #1 Second Loop #2 ^C
3.以后臺模式運行腳本
- 一些腳本可能要執(zhí)行很長時間抛杨,而我們又不希望在命令行界面一直等待腳本執(zhí)行結(jié)束。于是荐类,可以采用后臺運行的模式怖现。在后臺模式中,進行運行時不會和終端會話上的STDIN玉罐、STDOUT屈嗤、STDERR關(guān)聯(lián)。
3.1 后臺運行腳本
-
以后臺模式運行腳本只需要在命令后加一個&即可吊输。如下例所示:
#!/bin/bash count=1 while [ $count -le 10 ] do sleep 1 count=$[ $count + 1 ] done # 以后臺模式運行腳本H暮拧!季蚂! [njust@njust tutorials]$ ./bg1.sh & [1] 4280
- 當&符號放到命令后時茫船,它會將命令和bash shell分離開,將命令作為系統(tǒng)中的一個獨立的后臺進行運行扭屁,結(jié)果中顯示的第一行解釋:
- [1]:shell分配給后臺進程的作業(yè)號透硝;
- 4280:Linux系統(tǒng)分配給進程的進程ID(PID),Linux系統(tǒng)上運行的每個進程都必須有一個唯一的PID疯搅;
-
當后臺進程結(jié)束時濒生,它會在終端上顯示出下面的一條信息,該消息表示作業(yè)的作業(yè)號及作業(yè)狀態(tài)Done幔欧,還有用于啟動作用的命令罪治。
[1]+ 完成 ./bg1.sh
- 注意:當后臺進程運行時,它仍然會使用終端顯示器來顯示STDOUT和STDERR消息礁蔗,如下例所示:
#!/bin/bash echo "Start the test script" count=1 while [ $count -le 5 ] do echo "Loop #$count" sleep 2 count=$[ $count + 1 ] done echo "Test script is complete" # 結(jié)果 [njust@njust tutorials]$ ./bg2.sh & [1] 4712 Start the test script Loop #1 Loop #2 Loop #3 Loop #4 Loop #5 Test script is complete [1]+ 完成 ./bg2.sh
3.2 運行多個后臺作業(yè)
- 可以在命令行中同時啟動多個后臺作業(yè)觉义,每次啟動新作業(yè)時,Linux系統(tǒng)都會為其分配一個新的作業(yè)號和PID浴井。通過ps命令晒骇,可以看出所有腳本的狀態(tài)。如下例所示:
[njust@njust tutorials]$ ./bg2.sh & ./bg3.sh & ./bg4.sh & ps [1] 5495 [2] 5496 [3] 5497 Start the test script #4 Loop #1 Start the test script #2 Loop #1 Start the test script #3 Loop #1 PID TTY TIME CMD 5306 pts/0 00:00:00 bash 5495 pts/0 00:00:00 bg2.sh 5496 pts/0 00:00:00 bg3.sh 5497 pts/0 00:00:00 bg4.sh 5498 pts/0 00:00:00 ps 5499 pts/0 00:00:00 sleep 5500 pts/0 00:00:00 sleep 5501 pts/0 00:00:00 sleep
- 在ps命令的輸出中,每一個后臺進程都和終端會話聯(lián)系在一起洪囤。如果終端會話退出徒坡,那么后臺進程也會隨之退出。如果希望運行在后臺模式的腳本在登出控制臺后能夠繼續(xù)運行瘤缩,需要借助別的手段喇完。
4.在非控制臺下運行腳本
-
有時候,你會想在終端會話中啟動shell腳本剥啤,然后讓腳本一直以后臺模式運行到結(jié)束锦溪,即使你已經(jīng)退出了終端「樱可以使用nohup命令來實現(xiàn)刻诊。nohup命令運行了另外一個命令來阻斷所有發(fā)送給該進程的SIGHUP信號。這會在退出終端會話時牺丙,阻止進程退出坏逢。如下例所示:
[njust@njust tutorials]$ nohup ./bg2.sh & [1] 5745 nohup: 忽略輸入并把輸出追加到"nohup.out"
- 當使用nohup命令時,如果關(guān)閉該會話赘被,腳本會忽略終端會話發(fā)送過來的SIGHUP信號是整。由于nohup命令會解除終端與進程的關(guān)聯(lián),進程也就不再同STDOUT和STDERR聯(lián)系在一起民假。為了保存該命令產(chǎn)生的輸出浮入,nohup命令會自動將STDOUT和STDERR的消息重定向到一個名為nohup.out的文件中。nohup.out文件包含了通常會發(fā)送到終端顯示器上的所有輸出羊异。如下所示:
[njust@njust tutorials]$ cat nohup.out Start the test script #2 Loop #1 Loop #2 Loop #3 Loop #4 Loop #5 Loop #6 Loop #7 Loop #8 Loop #9 Loop #10 Test script is complete
5.作業(yè)控制
- 作業(yè)控制:啟動事秀、停止、終止及恢復(fù)作業(yè)的功能野舶。通過作業(yè)控制易迹,就能完全控制shell環(huán)境中所有進程的運行方式了。
5.1 查看作業(yè)
- 作業(yè)控制中的關(guān)鍵命令是jobs命令平道,jobs命令允許查看shell當前正在處理的作業(yè)睹欲。如下例所示:
#!/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 ..." # 結(jié)果 [njust@njust tutorials]$ ./work1.sh Script process ID: 6157 Loop #1 Loop #2 ^Z [1]+ 已停止 ./work1.sh
- $$變量:顯示Linux系統(tǒng)分配給該腳本的PID∫晃荩可以從命令行啟動該腳本窘疮,使用Ctrl-Z鍵來暫停腳本。利用&將另一個作業(yè)作為后臺進程啟動冀墨,然后將腳本的結(jié)果重定向到文件中闸衫。如下所示:
[njust@njust tutorials]$ ./work1.sh > work1.out & [2] 6264
-
jobs命令可以查看分配給shell的作業(yè),jobs命令會顯示上面兩個已停止/運行中的作業(yè)诽嘉,以及它們的作業(yè)號和作業(yè)中使用的命令蔚出。如下所示:
[njust@njust tutorials]$ jobs [1]+ 已停止 ./work1.sh [2]- 運行中 ./work1.sh > work1.out &
-
要想查看作業(yè)的PID弟翘,可以在jobs命令中加入-l選項。如下所示:
[njust@njust tutorials]$ jobs -l [1]+ 6157 停止 ./work1.sh [2]- 6264 運行中 ./work1.sh > work1.out &
-
jobs命令參數(shù)如下所示:
參數(shù) 描述 -l 列出進程的PID和作業(yè)號 -n 只列出上次shell發(fā)出的通知后改變的作業(yè) -p 只列出作業(yè)的PID -r 只列出運行中的作業(yè) -s 只列出已停止的作業(yè)
-
jobs命令輸出中的加號和減號骄酗,帶加號的作業(yè)會被當做默認作業(yè)稀余。在使用作業(yè)控制命令時,如果未在命令行中指定任何作業(yè)號酥筝,該作業(yè)會被當成作業(yè)控制命令的操作對象。當前的默認作業(yè)完成處理后雏门,帶減號的作業(yè)成為下一個默認作業(yè)嘿歌。任何時候都只有一個帶加號的作業(yè)和一個帶減號的作業(yè),不管shell中有多少個正在運行的作業(yè)茁影。下例表示了下一個作業(yè)在默認作業(yè)移除時是如何成為默認作業(yè)的宙帝。如下例所示:
[njust@njust tutorials]$ ./work1.sh > work1.out & [1] 6721 [njust@njust tutorials]$ ./work1.sh > work2.out & [2] 6729 [njust@njust tutorials]$ ./work1.sh > work3.out & [3] 6738 [njust@njust tutorials]$ jobs -l [1] 6721 運行中 ./work1.sh > work1.out & [2]- 6729 運行中 ./work1.sh > work2.out & [3]+ 6738 運行中 ./work1.sh > work3.out & [njust@njust tutorials]$ kill 6738 [3]+ 已終止 ./work1.sh > work3.out [njust@njust tutorials]$ jobs -l [1]- 6721 運行中 ./work1.sh > work1.out & [2]+ 6729 運行中 ./work1.sh > work2.out & [njust@njust tutorials]$ kill 6729 [2]+ 已終止 ./work1.sh > work2.out [njust@njust tutorials]$ jobs -l [1]+ 6721 運行中 ./work1.sh > work1.out & [njust@njust tutorials]$ kill 6721 [1]+ 已終止 ./work1.sh > work1.out
5.2 重啟停止的作業(yè)
-
在bash作業(yè)控制中,可以將已停止的作業(yè)作為后臺進程或前臺進程重啟募闲。前臺進程會接管你當前工作的終端步脓,所以在使用該功能時要小心。要以后臺模式重啟一個作業(yè)浩螺,可以使用bg命令加上作業(yè)號靴患。如下例所示:
[njust@njust tutorials]$ ./work1.sh Script process ID: 6956 Loop #1 ^Z [1]+ 已停止 ./work1.sh [njust@njust tutorials]$ bg [1]+ ./work1.sh & [njust@njust tutorials]$ jobs [1]+ 運行中 ./work1.sh &
- 注意:當作業(yè)被轉(zhuǎn)入后臺模式時,并不會列出其PID要出。如果有多個作業(yè)鸳君,需要在bg命令后加上作業(yè)號患蹂。如下所示:
[njust@njust tutorials]$ ./work1.sh Script process ID: 7299 Loop #1 ^Z [1]+ 已停止 ./work1.sh [njust@njust tutorials]$ ./work2.sh Script process ID: 7307 Loop #1 ^Z [2]+ 已停止 ./work2.sh [njust@njust tutorials]$ ./work3.sh Script process ID: 7315 Loop #1 ^Z [3]+ 已停止 ./work3.sh [njust@njust tutorials]$ bg 2 # bg 2用于將第二個作業(yè)置于后臺模式;蚣铡!传于! [2]- ./work2.sh & Loop #2 [njust@njust tutorials]$ jobs [1]- 已停止 ./work1.sh [2] 運行中 ./work2.sh & [3]+ 已停止 ./work3.sh
- 注意:當使用jobs命令時囱挑,它列出了作業(yè)及其狀態(tài),即使是默認作業(yè)當前并沒有處于后臺模式沼溜。要以前臺模式重啟已暫停作業(yè)平挑,可使用帶有作用號的fg命令。由于作業(yè)是以前臺模式運行的系草,直到該作業(yè)完成后弹惦,命令行界面才會出現(xiàn)提示符。如下所示:
[njust@njust tutorials]$ ./work1.sh Script process ID: 7451 Loop #1 ^Z [2]+ 已停止 ./work1.sh [njust@njust tutorials]$ ./work2.sh Script process ID: 7459 Loop #1 ^Z [3]+ 已停止 ./work2.sh [njust@njust tutorials]$ ./work3.sh Script process ID: 7467 Loop #1 ^Z [4]+ 已停止 ./work3.sh [njust@njust tutorials]$ fg 2 ./work1.sh Loop #2 Loop #3 Loop #4 Loop #5 Loop #6 Loop #7 Loop #8 Loop #9 Loop #10 End of script ... [njust@njust tutorials]$
6.調(diào)整謙讓度
- 在多任務(wù)操作系統(tǒng)中悄但,內(nèi)核負責將CPU時間分配給系統(tǒng)上運行的每個進程棠隐。調(diào)度優(yōu)先級是內(nèi)核分配給進程的CPU時間。在Linux系統(tǒng)中檐嚣,由shell啟動的所有進程的調(diào)度優(yōu)先級默認都是相同的助泽。
- 調(diào)度優(yōu)先級是一個整數(shù)值啰扛,從-20(最高優(yōu)先級)~+19(最低優(yōu)先級)。默認情況下嗡贺,bash shell以優(yōu)先級0來啟動所有進程隐解。越低的值即優(yōu)先級越高,獲得CPU時間的機會就越高诫睬。
6.1 nice命令
- nice命令允許你設(shè)置命令啟動時的調(diào)度優(yōu)先級煞茫,要讓命令以更低的優(yōu)先級允許,只要用nice -n命令來指定新的優(yōu)先級級別摄凡。如下例所示:
[njust@njust tutorials]$ nice -n 10 ./work1.sh > work1.out & [1] 3484 [njust@njust tutorials]$ ps -p 3484 -o pid,ppid,ni,cmd PID PPID NI CMD 3484 2985 10 /bin/bash ./work1.sh
- 注意:必須將nice命令和要啟動的命令放在同一行中续徽。上例中,ps命令的輸出驗證了謙讓度值(NI列)已經(jīng)被調(diào)整為10亲澡。
- 但是钦扭,如果想要提高某個命令的優(yōu)先級,nice命令會阻止普通用戶來提高命令的優(yōu)先級床绪。因為nice命令的-n選項并不是必須的客情,只需要在破折號后面跟上優(yōu)先級即可。如下例所示:
# 提升優(yōu)先級失敗的情況 [njust@njust tutorials]$ nice -n -10 ./work1.sh > work1.out & [1] 3570 [njust@njust tutorials]$ nice: 無法設(shè)置優(yōu)先級: 權(quán)限不夠 ^C # 提升優(yōu)先級成功的情況 [njust@njust tutorials]$ nice -10 ./work1.sh > work1.out & [1] 3760 [njust@njust tutorials]$ ps -p 3760 -o pid,ppid,ni,cmd PID PPID NI CMD 3760 2985 10 /bin/bash ./work1.sh
6.2 renice命令
- 有時候需要改變系統(tǒng)上已運行命令的優(yōu)先級癞己,通過renice命令即可實現(xiàn)膀斋。它允許你指定運行進程的PID來改變它的優(yōu)先級。如下例所示:
[root@njust tutorials]# ./work1.sh & [1] 4612 Script process ID: 4612 [root@njust tutorials]# ps -p 4612 -o pid,ppid,ni,cmd PID PPID NI CMD 4612 4263 0 /bin/bash ./work1.sh [root@njust tutorials]# renice -n 10 -p 4612 4612 (進程 ID) 舊優(yōu)先級為 0痹雅,新優(yōu)先級為 10 [root@njust tutorials]# ps -p 4612 -o pid,ppid,ni,cmd PID PPID NI CMD 4612 4263 10 /bin/bash ./work1.sh
- renice命令會自動更新當前運行進程的調(diào)度優(yōu)先級概页,必須以root賬戶登錄后才能使用!renice也有一些限制:
- 只能對屬于你的進程執(zhí)行renice练慕;
- 只能通過renice降低進程的優(yōu)先級惰匙;
- root用戶可以通過renice來任意調(diào)整進程的優(yōu)先級;
7.定時任務(wù)
- 有時候铃将,我們需要在某個預(yù)先設(shè)定的時間開始運行腳本项鬼,Linux系統(tǒng)提供了多個在預(yù)選時間運行腳本的方法:at命令和cron表。
7.1 用at命令來計劃執(zhí)行作業(yè)
- at命令允許指定Linux系統(tǒng)何時運行腳本劲阎,at命令會將作業(yè)提交到隊列中绘盟,指定shell何時運行該作業(yè)。at的守護進程atd會以后臺模式運行悯仙,檢查作業(yè)隊列來運行作業(yè)龄毡。atd守護進程會檢查系統(tǒng)上的一個特殊目錄/var/spool/at來獲取用at命令提交的作業(yè)。默認情況下锡垄,atd守護進程會每60s檢查一下該目錄沦零。
-
1.at命令的格式
at [-f filename] time
- 默認情況下,at命令會將STDIN的輸入放到隊列中货岭。可以使用-f選項來指定用于讀取命令(腳本文件)的文件名路操。time參數(shù)指定了Linux系統(tǒng)何時運行該作業(yè)疾渴。如果你指定的時間已經(jīng)錯過,at命令會在第二天的那個時刻運行指定的作業(yè)屯仗。
- 如何指定時間搞坝?at命令能夠識別多種不同的時間格式。如下所示:
- 標準的小時和分鐘格式魁袜,如21:00桩撮;
- AM/PM指示符,如21:00 PM峰弹;
- 特定可命令時間店量,如now noon midnight等;
- 標準日期格式垮卓,如MMDDYY MM/DD/YY DD.MM.YY
- 文本日期垫桂,如Jul 4或Dec 25师幕;
- 指定時間增量:
- 當前時間+25 min粟按;
- 明天10:15 PM;
- 10:15+7天霹粥;
- 在使用at命令時灭将,該作業(yè)會被提交到作業(yè)隊列中。作業(yè)隊列會保存通過at命令提交的待處理的作業(yè)后控。針對不同的優(yōu)先級庙曙,存在26種不同的作業(yè)隊列,作業(yè)隊列通過用小寫字母az和大寫字母AZ來表示浩淘。作業(yè)隊列的字母排序越高捌朴,作業(yè)運行的優(yōu)先級就越低(更高的nice值)。默認情況下张抄,at的作業(yè)會被提交到a作業(yè)隊列砂蔽。如果想以更高的優(yōu)先級運行作業(yè),可以用-q參數(shù)指定不同的隊列字母署惯。
- 2.獲取作業(yè)的輸出
- 當作業(yè)在Linux系統(tǒng)上運行時左驾,顯示器并不會關(guān)聯(lián)到該作業(yè)。取而代之的是极谊,Linux系統(tǒng)會將提交該作業(yè)的用戶的電子郵箱地址作為STDOUT和STDERR诡右。任何發(fā)到STDOUT或STDERR的輸出都會通過郵件發(fā)送給該用戶。如下例所示:
#!/bin/bash echo "This script run at $(date +%B%d,%T)" sleep 5 echo "This is the script's end" # 結(jié)果 [njust@njust tutorials]$ at -f at.sh now job 1 at Mon May 18 21:15:00 2020 您在 /var/spool/mail/njust 中有新郵件
- 使用e-mail作為at命令的輸出很不方便轻猖,因此在使用at命令時帆吻,最好在腳本中對STDOUT和STDERR進行重定向。如果不想在at命令中使用郵件或重定向咙边,最好加上-M選項來屏蔽作業(yè)產(chǎn)生的輸出信息桅锄。如下所示:
#!/bin/bash echo "This script run at $(date +%B%d,%T)" > at1.out echo >> at1.out sleep 3 echo "This is the script's end" >> at1.out # 結(jié)果 [njust@njust tutorials]$ at -M -f at1.sh now job 4 at Mon May 18 21:20:00 2020 [njust@njust tutorials]$ cat at1.out This script run at 五月18,21:20:29 This is the script's end [njust@njust tutorials]$ cat at1.sh
- 3.列出等待的作業(yè)
- atq命令可以查看系統(tǒng)中有哪些作業(yè)在等待琉雳。如下所示:
[njust@njust tutorials]$ at -M -f at1.sh teatime job 5 at Tue May 19 16:00:00 2020 [njust@njust tutorials]$ at -M -f at1.sh tomorrow job 6 at Tue May 19 21:23:00 2020 [njust@njust tutorials]$ at -M -f at1.sh 23:00 job 7 at Mon May 18 23:00:00 2020 [njust@njust tutorials]$ at -M -f at1.sh now job 8 at Mon May 18 21:24:00 2020 [njust@njust tutorials]$ atq 5 Tue May 19 16:00:00 2020 a njust 6 Tue May 19 21:23:00 2020 a njust 7 Mon May 18 23:00:00 2020 a njust
- 4.刪除作業(yè)
- 一旦知道哪些作業(yè)在作業(yè)隊列中等待,就能使用atrm命令來刪除等待中的命令友瘤。如下所示:
[njust@njust tutorials]$ atq 5 Tue May 19 16:00:00 2020 a njust 6 Tue May 19 21:23:00 2020 a njust 7 Mon May 18 23:00:00 2020 a njust [njust@njust tutorials]$ atrm 5 [njust@njust tutorials]$ atq 6 Tue May 19 21:23:00 2020 a njust 7 Mon May 18 23:00:00 2020 a njust
7.2 安排需要定期執(zhí)行的腳本
- 使用at命令預(yù)設(shè)時間安排腳本執(zhí)行很方便翠肘,但是如果想每天的同一時間都執(zhí)行該腳本,就不再使用at命令不斷提交作業(yè)了辫秧。Linux系統(tǒng)使用cron程序來安排要定期執(zhí)行的作業(yè)束倍。cron程序會在后臺運行并檢查一個特殊的表(cron時間表),以獲得已安排執(zhí)行的作業(yè)盟戏。
-
1.cron時間表:cron時間表采用一種特別的格式來指定作業(yè)何時運行绪妹,格式如下所示:
min hour day month week 具體的命令
-
cron時間表允許你使用特定值、取值范圍(如1~5)或者通配符(*)來指定條目柿究。如下所示:
15 10 * * * command # 每天的10:15執(zhí)行一次命令
- 可以用三字符的文本值(mon邮旷、tue、wed蝇摸、thu婶肩、fri、sat貌夕、sun)或數(shù)值(0為周日律歼,6為周六)來指定week的值。如何設(shè)置一個在每個月的最后一天執(zhí)行的命令啡专?常用的方法是加一條使用date命令的if-then語句來檢查明天的日期是否為01险毁。如下所示:
00 12 * * * if [ `date +%d -d tomorrow` = 01 ]; then ; command
- 具體的命令中必須指定要運行的命令或腳本的全路徑名,如下例所示:
15 10 * * * /home/njust/tutotials/test.sh > test.out
- 2.構(gòu)建cron時間表
- 每個系統(tǒng)用戶都可以用自己的cron時間表來運行安排好的任務(wù)们童,Linux提供了crontab命令來處理cron時間表畔况。要列出已有的cron時間表,可以用-l選項慧库。如下所示:
[njust@njust tutorials]$ crontab -l no crontab for njust
- 默認情況下跷跪,用戶cron時間表文件并不存在。要為cron時間表添加條目完沪,可以用-e選項域庇。在添加條目時,crontab命令會啟動一個文本編輯器覆积,使用已有的cron時間表作為文件內(nèi)容听皿。
- 3.瀏覽cron目錄
- 如果你創(chuàng)建的腳本對精確的執(zhí)行時間要求不高,用預(yù)配置的cron腳本目錄會更方便宽档。有4個基本目錄:hourly尉姨、daily、monthly吗冤、weekly又厉。如果腳本需要每天執(zhí)行一次九府,只要將腳本復(fù)制到daily目錄,cron就會每天執(zhí)行它覆致。如下所示:
[njust@njust ~]$ ls /etc/cron.*ly /etc/cron.daily: logrotate man-db.cron mlocate /etc/cron.hourly: 0anacron mcelog.cron /etc/cron.monthly: /etc/cron.weekly:
4.anacron程序
- cron程序的唯一問題是:它假設(shè)Linux是7*24小時運行的侄旬,除非將Linux系統(tǒng)當成服務(wù)器環(huán)境來運行,否則假設(shè)不會成立煌妈。如果某個作業(yè)在cron時間表中安排運行的時間已到儡羔,但這時Linux系統(tǒng)處于關(guān)機狀態(tài),那么這個作業(yè)就不會執(zhí)行璧诵。當系統(tǒng)開機時汰蜘,cron程序不會再去運行那些錯過的作業(yè)。要解決這個問題之宿,許多Linux發(fā)行版包含了anacron程序族操。
- 如果anacron知道某個作業(yè)錯過了執(zhí)行時間,它會盡快運行該作業(yè)比被。這個功能常用于日志維護的腳本色难。anacron程序只會處理位于cron目錄的程序,如/etc/cron.monthly姐赡。它使用時間戳來決定作業(yè)是否在正確的計劃間隔內(nèi)運行莱预。每個cron目錄都有一個時間戳文件柠掂,該文件位于/var/spool/anacron项滑。如下所示:
[root@njust njust]# cat /var/spool/anacron/cron.monthly 20200517
- anacron程序使用自己的時間表(通常位于/etc/anacrontab)來檢查作業(yè)目錄。如下所示:
[root@njust njust]# cat /etc/anacrontab # /etc/anacrontab: configuration file for anacron # See anacron(8) and anacrontab(5) for details. SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root # the maximal random delay added to the base delay of the jobs RANDOM_DELAY=45 # the jobs will be started during the following hours only START_HOURS_RANGE=3-22 #period in days delay in minutes job-identifier command 1 5 cron.daily nice run-parts /etc/cron.daily 7 25 cron.weekly nice run-parts /etc/cron.weekly @monthly 45 cron.monthly nice run-parts /etc/cron.monthly
- anacron時間表的基本格式如下所示:
- period:定義了作業(yè)多久運行一次涯贞,以天為單位枪狂。anacron程序用此來檢查作業(yè)的時間戳文件;
- delay:指定系統(tǒng)啟動后anacron程序需要等待多少分鐘再開始運行錯過的腳本宋渔;
- command:包含了run-parts程序(負責運行目錄中傳給它的任何腳本)和一個cron腳本目錄名州疾;
- identifier:一種特別的非空字符串,用于唯一標識日志消息和錯誤郵件中的作業(yè)皇拣;
period delay identifier command
- 注意:anacron程序不會運行位于 /etc/cron.hourly的腳本严蓖。因為anacron程序不會處理執(zhí)行時間需求小于一天的腳本。
7.3 使用新shell啟動腳本
- 如果每次運行腳本的時候都能夠啟動一個新的bash shell氧急,將會非常方便颗胡。當用戶登錄bash shell時需要運行相關(guān)的啟動文件,基本上不同發(fā)行版的Linux系統(tǒng)按照下列順序所找到的第一個文件會被運行吩坝,其余的文件將會被忽略:
- $HOME/.bash_profile
- $HOME/.bash_login
- $HOME/.profile
-
因此毒姨,需要將在登錄時運行的腳本放在上面的第一個文件中。每次啟動一個新的shell時钉寝,bash shell都會運行.bashrc文件弧呐≌⒚裕可以如下例所示進行驗證:
# .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # Uncomment the following line if you don't like systemctl's auto-paging feature: # export SYSTEMD_PAGER= # User specific aliases and functions echo "I'm in a new shell!" # 結(jié)果 [njust@njust ~]$ bash I'm in a new shell!
- .bashrc文件通常也是通過某個bash啟動文件來運行的。因為.bashrc文件會運行兩次:一次是當你登入bash shell時俘枫,另一次是當你啟動一個bash shell時腥沽。如果你需要一個腳本在兩個時刻都得以運行,可以把這個腳本放進該文件中鸠蚪。