溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

shell腳本中如何進(jìn)行信號(hào)的捕捉

發(fā)布時(shí)間:2022-01-24 10:21:03 來源:億速云 閱讀:672 作者:柒染 欄目:開發(fā)技術(shù)

本篇文章給大家分享的是有關(guān)shell腳本中如何進(jìn)行信號(hào)的捕捉,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

trap從字面意思看就是就是陷阱的意思但是在shell腳本中trap時(shí)專門捕捉kill -9,kill -15,CTRL+C等信號(hào)的。

shell腳本中如何進(jìn)行信號(hào)的捕捉

1、查看所有可用的信號(hào)

trap -l或kill -l即可

[root@linux1 ~]# kill -l63) SIGRTMAX-1  64) SIGRTMAX    
[root@linux1 ~]# trap -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
......

2、常見的信號(hào)如下:

Signal     Value     Comment
─────────────────────────────
SIGHUP        1      終止進(jìn)程,特別是終端退出時(shí),此終端內(nèi)的進(jìn)程都將被終止
SIGINT        2      中斷進(jìn)程,幾乎等同于sigterm,會(huì)盡可能的釋放執(zhí)行clean-up,釋放資源,保存狀態(tài)等(CTRL+C)
SIGQUIT       3      從鍵盤發(fā)出殺死(終止)進(jìn)程的信號(hào)

SIGKILL       9      強(qiáng)制殺死進(jìn)程,該信號(hào)不可被捕捉和忽略,進(jìn)程收到該信號(hào)后不會(huì)執(zhí)行任何clean-up行為,所以資源不會(huì)釋放,狀態(tài)不會(huì)保存
SIGTERM      15      殺死(終止)進(jìn)程,幾乎等同于sigint信號(hào),會(huì)盡可能的釋放執(zhí)行clean-up,釋放資源,保存狀態(tài)等

SIGSTOP      19      該信號(hào)是不可被捕捉和忽略的進(jìn)程停止信息,收到信號(hào)后會(huì)進(jìn)入stopped狀態(tài)
SIGTSTP      20      該信號(hào)是可被忽略的進(jìn)程停止信號(hào)(CTRL+Z)

真正的信號(hào)名字不是SIGXXX,而是去除SIG后的單詞,每個(gè)信號(hào)還有對(duì)應(yīng)的代號(hào)

比如向PID為12345的進(jìn)程發(fā)起1信號(hào)

kill -1 12345kill -HUB 12345kill -SIGHUB 12345

3、trap的選項(xiàng)

trap -l列出當(dāng)前系統(tǒng)支持的信號(hào)列表,上面已經(jīng)使用過,根kill -l一樣

trap -p等價(jià)于trap,查看shell已經(jīng)布置好的陷阱

可以看到shell默認(rèn)有三個(gè)陷阱,表示忽略20,21,22信號(hào)

[root@linux1 ~]# traptrap -- '' SIGTSTPtrap -- '' SIGTTINtrap -- '' SIGTTOU

4、陷阱捕捉到信號(hào)后干嘛

  • 忽略信號(hào)

  • 捕捉到信號(hào)后做相應(yīng)的處理。主要是清理一些腳本創(chuàng)建的臨時(shí)文件,然后退出。

5、設(shè)置一個(gè)可以忽略CTRL+C和15信號(hào)的陷阱

CTRL信號(hào)對(duì)應(yīng)的是SIGINT 15信號(hào)對(duì)應(yīng)的是SIGTERM

[root@linux1 ~]# trap '' SIGINT SIGTERM[root@linux1 ~]# traptrap -- '' SIGINTtrap -- '' SIGTERMtrap -- '' SIGTSTPtrap -- '' SIGTTINtrap -- '' SIGTTOU

這樣,當(dāng)前shell就不能被kill -15殺死

6、設(shè)置一個(gè)陷阱,捕捉到-15信號(hào)時(shí),就打印“我抓到你啦~”

[root@linux1 ~]# trap 'echo "我抓到你啦~"' TERM[root@linux1 ~]# traptrap -- '' SIGINTtrap -- 'echo "我抓到你啦~"' SIGTERMtrap -- '' SIGTSTPtrap -- '' SIGTTINtrap -- '' SIGTTOU

效果,當(dāng)我對(duì)當(dāng)前bash發(fā)起kill -15信號(hào)時(shí)就打印出來了

[root@linux1 ~]# echo $$8827
[root@linux1 ~]# kill -15 8827我抓到你啦~
[root@linux1 ~]# kill -15 8827我抓到你啦~
[root@linux1 ~]# kill -15 8827我抓到你啦~

7、在腳本中設(shè)置一個(gè)能忽略CTRL+C和CTRL+Z信號(hào)的腳本

CTRL+C是2信號(hào),即SIGINT

CTRL+Z是20信號(hào),即SIGTSTP

腳本:

腳本沉睡10s,然后打印success,腳本忽略INT和TSTP信號(hào)

[root@linux1 ~]# cat trap.sh#!/bin/bashtrap '' SIGINT SIGTSTP
sleep 10echo success

效果:

CTRL+C也不能阻止我睡覺

[root@linux1 ~]# bash trap.sh ^C^C^Z^Z^C^C^Z^Zccc^Z^Z^Z^C^C^C

success

8、布置一個(gè)當(dāng)腳本被終端時(shí)能清理垃圾并立即退出腳本的陷阱

腳本如下:

[root@linux1 ~]# cat trap1.sh#!/bin/bashtrap 'echo trap handing...;rm -rf /tmp/$BASHPID;echo TEMP files cleaned;exit' SIGINT SIGTERM SIGQUIT SIGHUP
mkdir -p /tmp/$$/
touch /tmp/$$/{a..c}.txt
sleep 10echo first sleep success
sleep 10echo second sleep success

這樣,腳本除了SIGKILL信號(hào)(kill -9),總能清理掉臨時(shí)垃圾

效果

剛開始一直不能終止,后來執(zhí)行了下trap發(fā)現(xiàn)前面shell自己設(shè)置了一個(gè)忽略CTRL+C的陷阱,退出shell重進(jìn)即可

[root@linux1 ~]# bash trap1.sh ^Ctrap handing...
TEMP files cleaned

9、陷阱的守護(hù)對(duì)象

陷阱的守護(hù)對(duì)象是shell進(jìn)程本身,不會(huì)守護(hù)shell環(huán)境內(nèi)的子進(jìn)程。但如果是信號(hào)忽略型陷阱,則會(huì)守護(hù)整個(gè)shell進(jìn)程組使其忽略給定信號(hào)。

[root@linux1 ~]# cat trap2.sh #!/bin/bashtrap 'echo trap_handle_time: $(date +"%F %T")' SIGINT SIGTERMecho time_start: $(date +"%F %T")
sleep 10echo time_end1: $(date +"%F %T")
sleep 10echo time_end2: $(date +"%F %T")#執(zhí)行腳本后,新開終端使用kill -15殺死它[root@linux1 ~]# killall -s SIGTERM trap2.sh#查看輸出情況[root@linux1 ~]# ./trap2.sh time_start: 2019-08-27 10:43:48
trap_handle_time: 2019-08-27 10:43:58
time_end1: 2019-08-27 10:43:58
time_end2: 2019-08-27 10:44:08

可以發(fā)現(xiàn),kill執(zhí)行完后,屏幕沒有立即打印trap_handle,而是等sleep 10運(yùn)行完后才打印的。sleep進(jìn)程都被忽略型trap守護(hù)了

只要是向shell進(jìn)程發(fā)送的信號(hào),都會(huì)等待當(dāng)前正在運(yùn)行的命令結(jié)束后才處理信號(hào),然后繼續(xù)腳本向下運(yùn)行。(實(shí)際上,只有當(dāng)shell腳本中正在執(zhí)行的操作是信號(hào)安全的系統(tǒng)調(diào)用時(shí),才會(huì)出現(xiàn)信號(hào)無法中斷進(jìn)程的情況,而在shell下的各種命令,我們是沒法直接知道哪些命令中正在執(zhí)行的系統(tǒng)調(diào)用是系統(tǒng)調(diào)用的)。

但sleep命令發(fā)起的sleep()調(diào)用,是一個(gè)信號(hào)安全的,所以上面腳本中執(zhí)行sleep的過程中,信號(hào)不會(huì)直接中斷它們的運(yùn)行,而是等待它運(yùn)行完之后再執(zhí)行信號(hào)處理命令。

10、如果shell中針對(duì)某信號(hào)設(shè)置了陷阱,則該shell進(jìn)程接收到該信號(hào)時(shí),會(huì)等待其內(nèi)正在運(yùn)行的命令結(jié)束才開始處理陷阱

11、CTRL+C和SIGINT不是等價(jià)的。當(dāng)某一時(shí)刻按下CTRL+C,它是在向整個(gè)當(dāng)前運(yùn)行的進(jìn)程組發(fā)送SIGINT信號(hào)。對(duì)shell腳本來說,SIGINT不僅發(fā)送給shell腳本進(jìn)程,還發(fā)送給腳本中當(dāng)前正在運(yùn)行的進(jìn)程

[root@linux1 ~]# cat trap2.sh #!/bin/bashtrap 'echo trap_handle_time: $(date +"%F %T")' SIGINT SIGTERMecho time_start: $(date +"%F %T")
sleep 10echo time_end1: $(date +"%F %T")
sleep 10echo time_end2: $(date +"%F %T")#執(zhí)行腳本后,立馬CTRL+C[root@linux1 ~]# bash trap2.sh time_start: 2019-08-27 10:20:53
^Ctrap_handle_time: 2019-08-27 10:20:54
time_end1: 2019-08-27 10:20:54
time_end2: 2019-08-27 10:21:04

可以發(fā)現(xiàn),CTRL+C后,不僅trap進(jìn)行處理了,sleep也立馬結(jié)束了;說明CTRL+C不僅讓腳本進(jìn)程收到了SIGINT信號(hào),也讓當(dāng)前進(jìn)程收到了SIGINT信號(hào)

以上就是shell腳本中如何進(jìn)行信號(hào)的捕捉,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI