Bash

當 SIGINT 或 SIGTERM 發送到父腳本本身而不是子程序時執行命令或函式

  • October 1, 2016

假設我有這個script.sh

#!/bin/bash
exit_script() {
   echo "Printing something special!"
   echo "Maybe executing other commands!"
   kill -- -$$ # Sends SIGTERM to child/sub processes
}

echo "Some other text"
#other commands here
sleep infinity

我想在收到時script.sh執行該函式, 例如:exit_script``SIGINT``SIGTERM

killall script.sh # it will send SIGTERM to my script

我希望我的腳本執行這個

exit_script() {
   echo "Printing something special!"
   echo "Maybe executing other commands!"
   kill -- -$$ # Sends SIGTERM to child/sub processes
}

我嘗試使用trap

trap exit_script SIGINT SIGTERM

回答我問題的人證明我錯了。

但它不起作用,因為trap似乎只對發送給子/子程序的信號做出反應。作為初學者,我無法解讀trap’s 手冊頁,因此我可能錯過了解決方案。

我想這就是像 Chromium 這樣的“真實”程序在你發送它們時所做的事情SIGTERM

來自https://major.io/2010/03/18/sigterm-vs-sigkill/

一旦收到 SIGTERM,應用程序就可以確定它想要做什麼。雖然大多數應用程序會清理它們的資源並停止,但有些可能不會。

trap對呼叫程序信號本身做出反應。但是你必須在收到信號之前呼叫它。我的意思是,在腳本的開頭。

此外,如果您想使用kill -- -$$,它也將信號發送到您的腳本,您需要在執行 kill 之前清除陷阱,否則您將以無限的kill && 陷阱循環結束。

例如:

#!/bin/bash
exit_script() {
   echo "Printing something special!"
   echo "Maybe executing other commands!"
   trap - SIGINT SIGTERM # clear the trap
   kill -- -$$ # Sends SIGTERM to child/sub processes
}

trap exit_script SIGINT SIGTERM

echo "Some other text"
#other commands here
sleep infinity

正如評論中所解釋的,問題在於腳本接收到信號但在處理接收到的信號之前正在等待睡眠程序結束。因此,您應該殺死子程序(在這種情況下為睡眠程序)以執行陷阱操作。您可以通過以下方式做到這一點:

kill -- -$(pgrep script.sh)

或如評論中所述:

killall -g script.sh

引用自:https://unix.stackexchange.com/questions/313644