
我非常努力地去理解我做錯了什麼以及為什麼?
我有一個launch.sh
啟動的腳本process.sh
。
啟動.sh
#!/bin/bash
while true; do
./process.sh
done
進程.sh
#!/bin/bash
function signalHandler() {
for i in {1..2}; do
sleep 0.1s
echo "process.sh: cleanup $i"
done
exit 130
}
trap "signalHandler" "SIGINT"
while true; do
sleep 1s
done
當我跑步時
./launch.sh &
然後用
kill -s SIGINT -$!
其中$!
取得最後一個命令 (launch.sh) 的 PID,減號將訊號傳送給所有子進程,然後launch.sh
繼續。為什麼?
我期望以下行為(根據此博客信號與猛擊):
後台運行腳本的 shell Alaunch.sh
被中斷,Bash 等待process.sh
完成。由於process.sh
中的訊號處理程序導致異常回傳(退出 130)process.sh
,shell A 應該退出。為什麼不呢?
如果該子進程的狀態表明它由於該訊號而異常退出,則 shell 會進行清理,刪除其訊號處理程序,並再次終止自身以觸發作業系統預設操作(異常退出)。或者,它會按照 trap 設定運行腳本的信號處理程序,然後繼續。
答案1
首先,exit 130
是不是異常退出。是正常退出,退出狀態為130。man 3 wait
(POSIX):
If the information pointed to by stat_loc was stored by a call to
waitpid() that specified the WUNTRACED and WCONTINUED flags,
exactly one of the macros WIFEXITED(*stat_loc), WIFSIGNALED(*stat_loc),
WIFSTOPPED(*stat_loc), and WIFCONTINUED(*stat_loc) shall evaluate to
a non-zero value.
WIFEXITED
檢查正常退出,並WIFSIGNALLED
因未捕獲訊號而終止。由於它們是互斥的,所以 anexit 130
是正常的。
當進程因 SIGINT 死亡時,退出狀態為 130 是因為 bash 在進程外部將其設為 130,因為它偵測到由於 SIGINT 導致的退出:為什麼 bash 設定 $? (退出狀態)在 Ctrl-C 或 Ctrl-Z 上變成非零?
其次,處理 SIGINT 然後死亡的進程應該用 SIGINT 殺死自己。 Greg 的 wiki(有關 shell 的優秀資源)有關於此的註釋:
如果您選擇為 SIGINT 設定處理程序(而不是使用 EXIT 陷阱),您應該意識到響應 SIGINT 而退出的進程應該用 SIGINT 殺死自己而不是簡單地退出,以避免給呼叫者帶來問題。因此:
trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT
現在,如果您將其更改exit 130
為:
trap - INT
kill -INT $$
您會看到預期的行為。