Lから始まるLinux

3章25話
一時ファイル作成
3章26話 シグナル処理
もくじ
3章27話
ジョブ管理
シグナル処理
若木 みどり
お兄ちゃん! 一時ファイルを作るスクリプトを Ctrl + C で止めると 一時ファイルが残っちゃうよ!
若木 みどり
スクリプトの最後の後処理で 一時ファイルを削除しているので 途中で止めたら残るのは 仕方ないとは思うけど… なんとかならないかな?
若木 しげる
「Ctrl + C」 「SIGINT(2)」 送信だったね 今回はシグナルを 処理する方法を学ぼう!
trap コマンド
若木 しげる
trap シグナルの処理を定義するよ
trap ['コマンド'] シグナル番号...
若木 しげる
シェルが指定されたシグナル番号 を受け取ったらコマンド を実行してくれるんだ
若木 みどり
trapシグナル番号2 を指定すればCtrl + C で止められたときの処理を指定できるんだね!
若木 しげる
trap では特別なシグナル番号 0 を指定できるんだこれは「スクリプトが終了したとき」に発せられるよスクリプトの後処理などに使われるんだ
若木 みどり
0 番はよく使いそうだね他に気をつけるシグナルはあるかな?
若木 しげる
強制終了を表す「SIGKILL(9)」処理できないんだtrap9 番を指定してもコマンド は実行されず実行されているスクリプトは即時終了になるよ
シグナルのリセット
若木 みどり
一度 trap を設定すると解除できないのかな?
若木 しげる
コマンドを省略するとtrap をの設定を解除するよ以下はシグナル番号 2tarp の設定を解除するんだ
trap 2
シグナルの無視
若木 しげる
指定するコマンドを空文字にするとそのシグナルに対して「何もしない」という指定ができるよつまり指定されたシグナルを無視する動作になるんだ
若木 しげる
以下は SIGHUP(1) を無視する設定だよ
trap '' 1
若木 みどり
nohup と同じ挙動になるんだね!シグナルの「リセット」「無視」指定が似ているから気をつけなきゃ…
実践
若木 しげる
ではシグナルが送信されても一時ファイルが後片付けされるようなスクリプトを書いてみよう!
#!/bin/bash

# シグナル処理定義
function cleanup() {
  [ -e "$TEMP_FILE" ] && rm -rf "$TEMP_FILE"
  exit "$1"
}

# シグナル処理設定
trap 'cleanup 0' 0
trap 'cleanup 1' 1 2 3 15

# 一時ファイル作成
TEMP_FILE="$(mktemp "/tmp/${0##*/}.XXXXXXXX")"

# 一時ファイルを使う処理
...
若木 しげる
このスクリプトではシグナルを以下のように処理しているよ
シグナル名シグナル番号意味終了ステータス
-0シェルスクリプト終了0
SIGHUP1端末の接続切れを通知1
SIGINT2キーボード割り込み(Ctrl + C)1
SIGQUIT3キーボード中止(Ctrl + /)1
SIGTERM15終了1
若木 みどり
これまで一番最後にあった一時ファイルの後処理は書かなくてもいいんだね!
若木 しげる
シェルスクリプト終了時に0 番のシグナルが送られるからねtrap0 番を処理すると決めておくと書かなくても良くなるんだ
若木 みどり
cleanup 関数を定義しているみたいだけど?
若木 しげる
trap で指定する コマンド1行である必要があるんだこの コマンド関数にしてあげることで複数行の処理を書けるようになるんだtrap でよく使われる書き方だよ!
まとめ
若木 みどり
今回はシェルスクリプトでシグナルを扱う方法を学んだよ!trap を使って定義してあげるんだね!
若木 しげる
trap が実行されてからシグナルを扱えるようになるんだなのでなるべくスクリプトの冒頭で実行してあげるようにしよう!