質問: シェルスクリプト trap処理の流れにつきまして シェルスクリプト作成しておりますが、 trap処理について質問がありますので、ご教授お願い致します。 以下、テストしたいと思っているスクリプトを記載いたします。 #!/bin/sh trap "echo 'stopped'" 1 2 3 15 echo start > test1.txt sleep 100 echo end > test1.txt 上記スクリプトを実行し、ctrl+cもしくは、 kill -15 でスクリプトを削除した場合、 sleep中にスクリプト中断していると思うのですが、 end文字列がtest1.txtに書き込まれてしまいます。 trapが処理される流れというのは、どのような流れなのでしょうか。 また途中で中断しているのであれば、途中で以下処理を 行なわないようにするにはどうすればよろしいでしょうか。 宜しくお願いいたします。
回答: このあたり、ジョブ制御(バックグラウンドジョブとか)まで含めてきちんと説明するのは実は大変です。 基本的な流れは、man bashに書いてあるのですが、読み取るのが難しいかもしれません。 ctrl-c の sigint(kill -2)は、スクリプトの/bin/shと、稼働中のコマンドこの場合はsleepの両方に伝わります。sleep はsigintで終了し、終了コードは130(=128+2)になります。その後、trapが実行され、echo stoppedしますが、/bin/sh自体は終了しないので、続きのコマンドであるecho end >test1.txt を実行します。 処理の中断をするには2通りあって、 案1) trap "echo 'stopped';exit" 1 2 3 15 # trapの中で/bin/shを終了 echo start > test1.txt sleep 100 echo end > test1.txt 案2) trap "echo 'stopped'" 1 2 3 15 echo start > test1.txt sleep 100 || exit # 終了コードが非ゼロなら/bin/shを終了 echo end > test1.txt 案2の変形) trap "echo 'stopped'" 1 2 3 15 echo start > test1.txt sleep 100 if [ $? -ne 0 ] then exit fi echo end > test1.txt ただし、案2の場合は、時間のかかる処理が複数あれば、その処理毎に終了コードの判断が必要ですね。 また、上記例では、exit とだけ書きましたが、実際は、exit 1 などとゼロ以外の終了コードで終わらせた方が良いでしょうね。