-9 KILL (non-catchable, non-ignorable kill)
kill -9 is SIGKILL and Unix system by design doesn’t allow any script/program to trap SIGKILL due to security reasons. Otherwise any script can trap & ignore SIGKILL which will make impossible to terminate that script by OS.
kill -9會發送SIGKILL信號,程序一般來說不能捕捉,但是有時候我們我們希望程序被kill時,執行某些操作保存log等等
- 啓動主進程
sh run.sh
時,同時啓動一個不依附於主進程的守護進程 - 該守護進程監控
sh run.sh
是否結束了,如果結束則被觸發,然後可以寫一些“善後代碼”,gracely exit - **切記: **直接執行
sh run.sh
纔有效,如果sh run.sh
在另一個shelltmp.sh
中然後執行了sh tmp.sh
,這樣的話,run.sh
中的守護進程會依附於tmp.sh
,當tmp被kill時它直接被kill了,根本無法守護run.sh
原始代碼鏈接:
https://askubuntu.com/questions/832767/run-another-command-when-my-script-receives-sigkill-signal
#!/bin/bash
# Launch a sleeping child process that will be "waited" next
sleep infinity & PID=$!
# Trap "graceful" kills and use them to kill the sleeping child
trap "kill $PID" TERM
# Launch a subprocess not attached to this script that will trigger
# commands after its end
( sh -c "
# Watch main script PID. Sleep duration can be ajusted
# depending on reaction speed you want
while [ -e /proc/$$ ]; do sleep 3; done
# Kill the infinite sleep if it's still running
[ -e /proc/$PID ] && kill $PID
# Commands to launch after any stop
echo "Terminating"
" & )
# Commands to launch before waiting
echo "Starting"
# Waiting for infinite sleep to end...
wait
# Commands to launch after graceful stop
echo "Graceful ending"
如果你有更特殊的需求,比如主進程sh run.sh
中還有其他子進程不在主進程中,當主進程被kill -9時也想收到通知,同理可在守護進程中,發送信號給子進程,如果子進程需要接收SIGINT
時,需要在run.sh
中加set -m
,因爲默認情況下後臺進程會忽略SIGINT
run.sh
#!/bin/bash
# Job control is enabled
# Send SIGINT to background tasks (if not, SIGINT will be ignored)
set -m
# Launch a child process of target task
sh A.sh & PID=$!
# Launch a subprocess not attached to this script that will trigger commands after its end
( sh -c "
# Watch main script PID. Sleep duration can be ajusted
# depending on reaction speed you want
while [ -e /proc/$$ ]; do sleep 1; done
# Kill A if it's still running
# kill -2: send SIGINT
[ -e /proc/$PID ] && kill -2 $PID
" & )
# Waiting for A to end...
wait $PID