- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
!!!技術的雑談-ctrl-cをscript内で捕捉する
!!環境
GNU bash 2.05b(1)-release
!!目的
*スクリプト実行中にctrl+cを検出したい
*どんな終わり方をしても必ず実行する処理を加えたい
!!手段
'''trap'''コマンドを使います。
trapコマンドはshell script内でトラップが発生したときに実行したいscriptを設定するコマンドです。
!書式
trap [-lp] [arg] [sigspec ...]
::-l
:::signalの一覧を表示する
::-p
:::指定したsignalに関連付けられているscriptを表示する
::arg
:::sigspecに関連付けるscriptを文字列で記述する。空文字列を指定するとそのsignalの補足を解除できる。何も指定しないとそのsignalに現在関連付けられているscriptを表示する。
::sigspec
:::スペース区切りでsignalを列挙する。
!signal
ちなみに、よく使うsignalはこんな感じ。
文字列で指定しても数字で指定しても良い。
::HUP (1)
:::kill -HUPなどで呼ばれる。普通は「設定ファイルの読み直し」を実装するのがお約束。
::INT (2)
:::インタラプト。ctrl+cで発生する。
::KILL (9)
:::プロセスの強制終了。INTよりも強い。kill -KILLで発行できる。これが来たらプログラムは直ちに終了するのがお約束。trapコマンドで何を書いても無視される。
::TERM (15)
:::終了要求。trapで指定しても無視される。
!使用例
#!/bin/sh
trap 'echo "HUP"' HUP
trap 'echo "INT"' INT
trap 'echo "KILL"' KILL
trap 'echo "TERM"' TERM
trap 'echo "zero"' 0
while [ $EEE -eq 0 ]
do
echo '.'
sleep 10
done
exit 0
10秒ごとに「.」を1つ表示します。
ctrl+cでもkill xxxxでも死にません。(ある意味危険ですな。)
ctrl+c押したりkill -HUPやったりkill -KILLすると「INT」「HUP」「KILL」なんて表示して、そのシグナルが来たことを教えてくれます。
止めたいときは、ctrl+zで一時中断してから、
ps
でこのscriptのPIDを調べて、
kill -TERM <PID>
で殺しましょう。
[1]+ Killed ./test.sh
とか出てきます。ちと怖い。
!応用
manなんかをよく読むと、実行中のddにkill -ALRMとかやると今までに転送終わったデータ量とか表示してくれた気がするんだけど……linuxのmanには見当たらないなぁ…。
USR1とかUSR2などのユーザシグナルがあり、ユーザが独自のシグナルを定義するためにリザーブしてある。
ちなみに、Unixなどの「マルチプロセスOS」で一番手軽にプロセス空間を越えてメッセージを伝えるのが「シグナル」だったりする。
(いや、これを聞いて「おお〜」とか感心するのは、「メモリー空間」とか分かっていないと無理だよね(汗))
!注意
trapでINTやKILLを捕捉するscriptを書いた場合、trap処理が不要になった時点で、
tarp '' INT
などと書いておかないとctrl+cで殺せないscriptになってしまう。
止められて困る場所を過ぎたらtrap解除するようにしましょう。
(ま、kill -TERMはユーザプロセスで補足不可能なsignalなので最終的にはそれで殺せるけど危ないでしょ?^^;)
!!履歴
2005/10/06 -- 初版
[[技術的雑談]]へ戻る
!!突っ込み
{{comment}}
[[技術的雑談]]へ戻る
{{trackback}}
[[技術的雑談]]へ戻る