例えば、gpioに出力するscriptを実行中にCtrl-Cを押下すると、タイミングによってはgpioに出力しっ放しになり、後からpinを調べてgpio write $PIN 0などと手作業で始末しなければならない。これはいかにも面倒なので、Ctrl-Cによる中断 (SIGINT)が発生した際に終了処理を行わせたくなる。
この目的を達成するために、shell builtin commandであるtrapが使える。ただし、trapの仕様 (受け付けるoptionの種類や数)がshellによって異なるので注意が必要。以下、bashにおける利用例を挙げる。
使い方
singalに対する処理を指定する
trap <commands> <signals>
<commands>にはdouble quotation (")で括ってcommandの羅列が指定できる。
<signals>にはSIGINTやSIGTERMなどが指定できる。bashのtrapでは、trap -pで指定できるsignalsのlistが表示される。1つの処理に対して複数のsignalsを指定できる。
例: SIGINT (Ctrl-C)とSIGTERMが発生した時にgpio 25番 (WiringPi)に0を出力して終了する
$ trap "gpio out 25 0; exit" SIGINT SIGTERM
signalを単に無視する
<commands>に"" (空文字列)を渡す。
trap "" <signals>
例: SIGINTを無視する
$ trap "" SIGINT
signal handlingをdefaultに戻す
<commands>に"-" (hyphen)を指定する。
trap - <signals>
例: SIGINTのsiginal handlingをdefaultに戻す
$ trap - SIGINT
※bashの場合は<commands>を省略しても同じ効果。
$ trap SIGINT
注意
* shebang (shell scriptの1行目)を/bin/bashにしておくこと
* trapはshell scriptで使う場合が殆どだが、その際、なるべく早い段階で設定しておくこと → trapによるsignal handlingが設定されていない状態で主たる処理が始まってしまう。
少し考えれば当たり前なのだが、なぜか最後にtrapを指定していたscriptがあったので敢えて注意を。
補遺
shellによるtrapの動作やoptionsの違いについて。
options
* bashのtrapのみ、-lや-pといったoptionを受け付ける
* zshのtrapは何もしない
* dash (Debian defaultの/bin/sh)のtrapではerror
書式
* bashやzshのtrapは、<signals>として例えば"SIGINT"もしくはSIG抜きの省略形"INT"のような名前、或いは対応する番号 (SIGINTは2)で指定する
* dashでは、"INT" (SIG抜き)或いは番号 (2)で指定する
出典
* man bash-builtins
* man zshbuiltins
* man dash
0 件のコメント:
コメントを投稿