トップ 一覧 検索 ヘルプ RSS ログイン

技術的雑談-ctrl-cをscript内で捕捉するの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!!技術的雑談-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}}

[[技術的雑談]]へ戻る