シェルスクリプトの基礎 - シグナルとtrapコマンド
概要
シグナルとは、プロセス間で通信を行うための仕組みであり、Linuxカーネルに実装されている。
実行中のプロセスの処理を一時的に止めて、別のプロセスを処理する場合等に使用される。
シグナルは、キーボードからの割り込み(SIGINT)や浮動小数点例外(SIGFPE)、プロセスの終了(SIGTERM)等、30種類以上ある。
これらのシグナルは、プログラム(プロセス)自身の動作によって発生する同期シグナル、外的な要因で発生する非同期シグナルの2種類ある。
シグナルの動作を以下に示す。
- あるプロセスの実行中において、処理を割り込ませたい場合、カーネルがシグナルを発生させる。
- シグナルが発生すると実行中のプロセスが中断され,特定の処理が実行される。
この特定の処理のことを、シグナルハンドラと呼ぶ。
シグナルは突然発生するため、発生するシグナルごとに実行する処理を、予めシグナルハンドラとして登録する。
使用可能なシグナルの一覧は、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 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 35) SIGRTMIN 36) SIGRTMIN+1 ...略
シグナルを送出する
プロセスにシグナルを送出するには、killコマンドを使用する。
以下のように、killコマンドのオプションとして、送出先プロセスのプロセスIDと送出するシグナルを指定して実行する。
kill [シグナル番号|シグナル名] PID
シグナルを送出するには、killコマンドに送出先プロセスのプロセスIDと送出するシグナルを指定して実行する。
シグナルの指定には、各シグナルに定義されているシグナル番号またはシグナル名のいずれかを使用する。
送出先プロセスのプロセスID(PID)は、psコマンドやpgrepコマンドで確認することができる。
シグナル番号またはシグナル名を省略する場合、標準で15番シグナル(TERM)が送出される。
sleep 100000 & # sleepコマンドに&を付加してバックグラウンドで実行する [1] 5355
pgrep -lf sleep # pgrepコマンドでプロセスIDを検索する 5355 sleep 100000
kill -15 5355 # TERMシグナルを送出する
pgrep -lf sleep # 再検索すると終了していることを確認できる [1]+ 終了しました sleep 100000
下表に、各シグナルが持っている意味を示す。
表. 一般的なシグナル番号一覧
シグナル番号 | シグナルが持つ意味 |
---|---|
0 | プロセス終了時に、プロセスが自分自身に対して送出するEXITシグナル。 |
1 | XWindowのクローズやデーモンのリセットに使用されるハングアップシグナル。 |
2 | [Ctrl]+[C]キーや[Delete]キーを押下した時に発生する割り込みシグナル。 |
3 | [Ctrl]+[\]キーを押下した時に発生するクイットシグナル。 |
9 | プロセスを強制終了するためのキルシグナル。 強制終了であるため、trapできない。 |
15 | プロセスを終了させるための終了シグナル。 killコマンドは標準でこのシグナルを使用する。 ( kill <PID> は、kill -15 <PID> と同じ意味)
|
表. 一般的なシグナル名一覧
シグナル番号 | シグナル名 | 通知内容 |
---|---|---|
1 | HUP | プロセスに再起動を通知する。 |
2 | INT | プロセスに割り込みを通知する。 [Ctrl]+[C]キー |
3 | QUIT | プロセスに終了を通知する。 (coreを作成する) |
9 | KILL | プロセスに強制終了を通知する。 |
15 | TERM | プロセスに終了を通知する。 (デフォルト) |
18 | CONT | プロセスに再開を通知する。 |
19 | STOP | プロセスに中断を通知する。 |
20 | TSTP | プロセスにサスペンドを通知する。 [Ctrl]+[Z]キー |
trap コマンド
trapコマンドの使用方法
trapコマンドは、送出されたシグナルを捕捉して、予め指定された処理を実行するコマンドである。
trap "<コマンド>" <シグナルリスト>
実行中のシェルスクリプトに対して送出されたシグナルは、trapコマンドを使用することで捕捉することができる。
killコマンド等により、シグナルリストに指定されたシグナルが送出されると、trapコマンドはそれを捕捉して、指定したコマンドを実行する。 trapコマンドを使用することにより、各シグナルの規定の動作を置き換えることができる。 ただし、強制終了のシグナルである9番はtrapすることはできないため、注意すること。
trap "echo trapped." 2 # ここで、[Ctrl]+[C]キーを押下する trapped.
trap処理のリセット
trap コマンドでシグナル捕捉時に実行するように指定した動作は、リセットを行うことで解除することができる。
trap シグナルリスト → trap コマンドにシグナルリストのみを指定し、指定されたシグナルの捕捉処理をリセットする。
trap コマンドで指定した処理をリセットしたい場合、つまり trap 'rm -f *.tmp; exit 1' 1 2 3 15 などと指定していた動作を、各シグナルのデフォルトの動作に戻したい場合は、trap 1 2 3 15 のように trap コマンドにリセットしたいシグナルのみを指定し実行する。
trap コマンドの処理を指定していた部分に何も書かないことにより、シグナル受信時にデフォルトの動作をするようになる。ただし、処理部分に何も書かないと言っても**「trap '’ 1 2 3 15」とはまったく意味が違う**ので注意が必要だ。
trap 1 2 3 15 と書くと、シグナルを捕捉した場合は を実行する、つまり何もしない処理を実行するという意味になり、結果として該当するシグナルを無視するという設定になってしまう。
$ trap 'echo trapped.' 2 ※ ここで Ctrl+c を押す。 $ trapped.
- ↑trap に指定した処理が実行されている。
$ trap 2
- ↑trap をリセットする。
※ ここで Ctrl+c を押す。 $
- ↑指定した処理が解除されているのが確認できる。