咱們ping一個主機,而後按下ctrl+c
那麼就會終止這個ping動做,以下圖:shell
但是若是使用一個循環來逐個ping不一樣主機,你再按下ctrl+c
就會發現停不下來,直到循環完成,以下圖:bash
#!/bin/bash NETWORK=172.16.42. # -W 表示超時時長 -c 是發送幾個ping包 for IP in {1..20}; do ping -W 1 -c 10 ${NETWORK}${IP} done
腳本沒有中止而是依然繼續執行,可是你發現172.16.42.1是通的,並且咱們經過-c參數應該是ping 10次,當完成第5次ping的時候,咱們按下ctrl+c
它就再也不ping這個地址,而是開始ping 172.16.42.2這個地址。這就是ctrl+c
的真正含義,它的做用是終止當前正在執行的操做,腳本中循環20次,每次執行一個ping操做,因此ctrl+c
僅僅終止的是其中一個ping操做而不是整個腳本。函數
不過這麼解釋並不徹底正確,由於你要知道ctrl+c
是發送中斷信號,究竟是應該終止ping操做仍是這個腳本,取決於捕捉到這個中斷信號的程序,若是是ping捕捉到了,那麼就終止ping操做;若是是執行這個腳本的進程捕捉到就終止這個腳本的執行。那麼咱們如何設置捕捉一個信號呢?就使用trap
這個內置的shell命令。ui
trap -l
顯示系統信號1,kill -l
也是能夠顯示的。3d
trap命令不能捕捉SIGKILL和SIGTERM這兩個信號。捕捉信號的目的是一旦信號到達咱們針對信號作什麼處理,若是捕捉SIGKILL而且你修改了行爲,這就意味着這個進程刀槍不入了,這顯然不行。通常咱們捕捉SIGHUP、SIGINT等。code
針對上面的例子如何修改呢?blog
#!/bin/bash # 捕捉INT,而後執行exit 1,該命令一般寫在腳本第一行 trap 'exit 1' INT NETWORK=172.16.42. # -W 表示超時時長 -c 是發送幾個ping包 for IP in {1..20}; do ping -W 1 -c 10 ${NETWORK}${IP} done
再次運行這個腳本那麼依然會執行循環,可是trap並不執行而是一直等着信號發生,咱們使用的ctrl+c
其實就是SIGINT信號。這個腳本的含義就是shell捕捉信號,因此shell捕捉到之後就會執行響應動做,咱們這裏是trap 'exit 1' INT
捕捉SIGINT而後執行exit 1
,當shell執行這個命令時也就意味着退出了,因此不管for循環是否執行完畢它都隨着腳本的退出而終止。進程
若是你想讓捕捉信號時作更多操做,你可使用函數的方式,以下代碼:it
#!/bin/bash trap 'sig_handler' INT sig_handler(){ echo "Quit" exit 1 } NETWORK=172.16.42. # -W 表示超時時長 -c 是發送幾個ping包 for IP in {1..20}; do ping -W 1 -c 10 ${NETWORK}${IP} done
也就是忽然終止後須要作一些收尾的清理操做,你就能夠經過上面自定義一個函數來執行。io
信號是進程間通訊的一種方式↩