web-dev-qa-db-ja.com

スクリプトがSIGKILLシグナルを受信したときに別のコマンドを実行する

スクリプトを実行するとします

$ Nohup ./myscript </dev/null >/dev/null 2>&1 & 

そしてそれを殺します

$ pkill myscript

SIGKILL信号を受信したときに別のコマンドが実行されるように、スクリプトをどのように設計できますか?

1
user123456

SIGKILL(およびSIGSTOP)をキャッチできないため、SIGKILLのカスタムハンドラーを有効にすると意味がありません。

他のすべての信号をキャッチできるので、おそらくそれらを中心に設計してみてください。

また、実行中:

pkill myscript

デフォルトのpkillは、SIGTERMではなく、SIGKILLを送信します。これは明らかにキャッチできます。

たとえば、スクリプト内の上部に次を追加します。

trap 'echo foobar' TERM

trap Shellビルトインは、シグナルをトラップし、カスタムハンドラーをディスパッチするか、シグナルを完全に無視するために使用されます。

ここでは、シェルがTERMを受信すると、コマンドecho foobarが実行されます。

他の信号にも同じことができ、必要に応じてコマンドを変更することもできます。たとえば、echo foobarとカスタムハンドラスクリプトの両方の実行:

trap 'echo foobar; /my/custom/handler.sh' TERM

その後exitを計画している場合:

trap 'echo foobar; /my/custom/handler.sh; exit' TERM
3
heemayl

SIGKILLをキャッチできないという回答を受け入れました。ところで、スクリプトのPIDを監視して、スクリプトがまだ実行中かどうかを確認できます。これは、現在のスクリプトのサブプロセスでこのウォッチャーを起動することでも実行できます。

#!/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"

https://stackoverflow.com/a/39128574/1324228からのオリジナルトラップスクリプト

1
JBreton