シェルスクリプトでシグナルをトラップするにはtrapを使います。
最初の引数が実行コマンドで、その後ろにトラップするシグナルを並べます。
#!/bin/sh trap 'echo exit...' EXIT trap 'echo trap INT or TERM' INT TERM echo start sleep 5 echo end
出力
start end exit...
start (^C押す) trap INT or TERM end exit...
EXITはプロセス終了時に投げられる番号0のシグナルです。
シグナル指定は名前でも番号でもよくて、他のシグナルはtrap -lやkill -lで見れます。
$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT ...
それでは応用例を3つほど。
HUPシグナルで設定ファイルのリロード
hup_handle.sh
#!/bin/sh startup () { . ./env.sh } trap startup HUP startup while :;do echo $STR sleep 2 done
env.sh
STR=AAA
実行
$ ./hup_handle.sh AAA AAA ...
別ターミナルで設定ファイルを書き換えてHUPシグナルを飛ばしてやれば、
$ echo STR=BBB > env.sh $ pkill -HUP hup_handle.sh
設定ファイルがリロードされて出力が変わります。
... AAA AAA BBB BBB ...
終了処理
例えば終了処理としてテンポラリファイルの削除とメッセージの表示を行うには。
#!/bin/sh end () { rm -f *tmp.$$ echo bye... } trap end EXIT #trap 'exit 255' 1 2 3 15 date > date.tmp.$$ echo start cat date.tmp.$$ sleep 10 echo end
テンポラリファイルに$$(PID)をつけてるのは複数同時に起動されたときにごっちゃにならないようにするためです。
2重起動防止
同じスクリプトを複数同時に起動できないようにするにロックファイルで制御するには。
#!/bin/sh lockfile=lockfile if [ -f $lockfile ];then echo $0 is locked exit 100 fi touch $lockfile trap 'rm -f $lockfile' EXIT #trap 'exit 255' 1 2 3 15 echo start sleep 10 echo end
既に他で起動されてると怒られます。
$ ./lock.sh ./lock.sh is locked