1. 程式人生 > 實用技巧 >Bash指令碼程式設計學習筆記09:訊號捕捉

Bash指令碼程式設計學習筆記09:訊號捕捉

簡介

首先我們先來看一段程式碼。

#!/bin/bash

declare -i uphosts=0
declare -i downhosts=0

for i in 192.168.152.{98..102}; do
    if ping -W 2 -c 1 $i &>/dev/null; then
        echo "$i is up."
        let uphosts++
    else
        echo "$i is down."
        let downhosts++
    fi
done

echo "Up hosts is $uphosts, down hosts is $downhosts.
"

該程式碼針對一個IP地址段進行ping測試,輸出IP地址線上與否並做統計。為了便於觀察效果,我們選擇的IP地址段較短,從192.168.152.98~102,其中只有主機地址為100(即本機)的主機線上。我們執行一遍看結果。

[root@c7-server ~]# bash trap1.sh
192.168.152.98 is down.
192.168.152.99 is down.
192.168.152.100 is up.
192.168.152.101 is down.
192.168.152.102 is down.
Up hosts is 1, down hosts is 4.

接下來我們執行第二遍,在執行的過程中,我們使用Ctrl+c嘗試終止指令碼的執行。

[root@c7-server ~]# bash trap1.sh
192.168.152.98 is down.
^C192.168.152.99 is down.
192.168.152.100 is up.
192.168.152.101 is down.
^C192.168.152.102 is down.
Up hosts is 1, down hosts is 4.

當98和101主機地址結果顯示出來以後我們立即鍵入Ctrl+c(在上面的輸出結果上我對其進行了加粗標紅),鍵入後99和102的輸出結果立即顯示出來了(由於這是程式碼塊展示,因此無法顯示出動態效果,大家看我描述腦補或者自行實驗)。

我們可以發現Ctrl+c並沒有終止指令碼的執行,而僅僅只是終止了當前迴圈中的ping命令的執行。

如果我們想讓指令碼本身停止,就需要使用bash內建命令trap來捕獲我們對指令碼發出的Ctrl+c命令。

在我之前的一篇部落格中《CentOS 7上的程序管理》已經有談到通過Ctrl+c命令結束正在執行中的指令碼實際上是向指令碼程序發出了SIGINT訊號。

因此我們需要使用trap捕獲SIGINT訊號並對其作出反應(在這裡是嘗試結束指令碼的執行)。

trap語法如下。

trap [-lp] [[arg] signal_spec ...]

arg:當接受到指定的訊號以後將要執行的命令;

signal_spec:具體的訊號;

-l:列出所有的訊號,類似於“kill -l”;

-p:打印出目前已經設定的陷阱,僅鍵入trap命令也有該效果。

[root@c7-server ~]# trap
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
[root@c7-server ~]# trap -p
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU

因此我們只需要在原本的指令碼的頂部(shebang下面)寫入這樣的陷阱即可。

[root@c7-server ~]# cat trap1.sh 
#!/bin/bash

trap "exit" SIGINT
declare -i uphosts=0
declare -i downhosts=0
... ...

結果如下,當指令碼一收到SIGINT訊號,立即結束指令碼,即便迴圈還未停止。

[root@c7-server ~]# bash trap1.sh 
192.168.152.98 is down.
^C[root@c7-server ~]# 
[root@c7-server ~]#

對於訊號捕捉(陷阱)trap的簡單介紹到此為止。