如何確認 process 有在 listen 哪些 Signals
可能有用小知識之 Linux Signals: SigCgt
Signal 是 Linux 中用來「通知」process 的一種方式,當 processes 接收到 signal 時,可以有三種處理方式:執行預設行為、忽略掉這個 signal 及把這個 signal 捕捉起來後處理。
在 Linux 中,透過 kill -l
可以看到有哪些 signals:
這個我們常用(?)的 kill
指令,其實也只是向 process 傳送 signal 而已,預設是傳送 SIGTERM,我們很愛用(?)的 kill -9 [PID]
呢?透過圖 1 可以發現,9 是 SIGKILL 這個 signal。
那要怎麼知道我們的 process 有註冊了哪些 signal 的處理(handler)呢?原來可以透過 SigCgt 來查看,現在就來實驗看看:
實驗 1:捕捉 SIGTERM
步驟 1:準備範例程式
先準備一支小程式,這是一個 shell script,會透過 trap
來捕捉 SIGTERM 這個 signal,並且用 cleanup
這個函式來處理,平常沒事的時候就是一直睡覺。
#!/bin/bash
cleanup() {
echo "Hello SIGTERM"
echo "Do something for graceful stop..."
exit
}
trap cleanup SIGTERM
while true;
do
echo "running for sleep"
sleep 1
done
將這個程式碼存成 test.sh,並且 chmod +x test.sh
使其可執行。執行起來後會如圖 2:
步驟 2:查看 SigCgt
先透過 ps aux
找到這個 process 的 PID,例如 9847,再透過以下指令去找出 SigCgt:
# 找出 PID 為 9847 的 process 的 SigCgt
# 記得要把 PID 換成你的 PID
$ cat /proc/9847/status | grep -i sigcgt
SigCgt: 0000000000014002
# 轉成 2 進位:
$ echo "obase=2;ibase=16;0000000000014002" | bc
10100000000000010
由於 SigCgt 是 16 進位,記得轉成 2 進位,轉出來後是 10100000000000010
步驟 3:查找對應的位置
由圖 3 可以看到,由右到左第 15 個位置是 1,而我們程式中是有去捕捉 SIGTERM 的。
實驗 2:不捕捉 SIGTERM
步驟 1:準備範例程式
跟實驗 1 一樣的範例程式,只需要把 trap 這行註解起來、不要去捕捉即可。修改完後一樣執行起來。
#!/bin/bash
cleanup() {
echo "Hello SIGTERM"
echo "Do something for graceful stop..."
exit
}
# 把這行註解起來,也就是不再去捕捉 SIGTERM
#trap cleanup SIGTERM
while true;
do
echo "running for sleep"
sleep 1
done
步驟 2:查看 SigCgt
先透過 ps aux
找到這個 process 的 PID,例如 9847,再透過以下指令去找出 SigCgt:
# 找出 PID 為 9847 的 process 的 SigCgt
# 記得要把 PID 換成你的 PID
$ cat /proc/10644/status | grep -i sigcgt
SigCgt: 0000000000010002
# 轉成 2 進位:
$ echo "obase=2;ibase=16;0000000000010002" | bc
10000000000000010
SigCgt 轉成 2 進位後是 10000000000000010。
步驟 3:查找對應的位置
也可以試試看修改範例程式中 trap signal 後,重複進行實驗看看,SigCgt 都會有對應的變化。
後話
現在才學會這件事,很想要重寫《Docker 實戰 6堂課:56個實驗動手做,掌握 Linux 容器核心技術》這本書的相關章節(會被編輯殺掉的吧?)
雖然不知道「知道了這件事」可以做什麼,但就是覺得很開心又多知道了一件事,本來想稱呼這是「無用小知識」,但也許只是我站得還不夠高,所以才覺得無用,因此決定改叫做「可能有用」。
如果大家對上述動手做的實驗有興趣,認真推薦《Docker 實戰 6堂課:56個實驗動手做,掌握 Linux 容器核心技術》這本書,裡面提供了 56 個大大小小的實驗,讓你親手驗證自己讀到的東西!