無限ループに陥ってしまったプロセスを強制終了させるためにはCtrl-Cやkillコマンドを利用しますね。このとき、プロセスにはシグナルというものが送られています。プロセスはシグナルの種類に応じて既定された処理を実行します。trapコマンドを用いると、各シグナル番号に対応する既定の処理を書き換えることができます。
シグナルN1, N2, N3, ...を受けたときに実行するコマンドを指定することで、trapコマンド実行後からのシグナル受信時の挙動を書き換えます。
trap 'シグナルを受けたときに実行するコマンド' シグナル番号N1, N2, N3, ...
Ctrl-Cを押したときに送られるシグナルです。SIGINT (SIGnal INTerruput) とも。
sample.sh (実行注意!!!)
#!/bin/sh
trap '' 2 # ''は何もしない、つまりシグナルを無視するということ。
while :
do
echo 'looping... (CAN NOT BE STOPPED BY Ctrl-C!!)'
sleep 1
done
実行例 (killコマンドか何かでシグナル2以外を送って終了させてください)
$ sh sample.sh
looping... (CAN NOT BE STOPPED BY Ctrl-C!!)
looping... (CAN NOT BE STOPPED BY Ctrl-C!!)
....
killコマンドを実行したときに送られるシグナルです。シグナル受信時のコマンドリストにexitを含めていることに注意してください。含めないとシグナル受信後、コマンドリストを実行した後、プロセスは終了せずに残りの処理を継続実行します。
sample.sh
#!/bin/sh
trap "echo 'killed'; exit" 15
while :
do
echo 'looping...'
sleep 1
done
実行例 (他のターミナルでkillコマンドを実行します)
$ sh sample.sh
looping...
looping...
...
looping...
killed
別のターミナルでのコマンド例
$ ps | grep sample.sh | awk '{print $1}' | xargs kill
なお、killコマンドはデフォルトではシグナル15を送りますが、kill -n pidとするとシグナルnを送れます。
シェルスクリプト内でexitが実行されたり、すべての処理が完了して終了した際に自分自身に送るシグナルです。
sample.sh
#!/bin/sh
trap "echo 'end'" 0
echo 128
実行例
$ sh sample.sh
128
end
ターミナル終了時にログインシェルによって送信されるシグナルです。こちらに記載した nohup という関連コマンドがあります。