yassy's note

なんかかきます

trapコマンドでのシグナル受信

シェルスクリプトは、毎回正常に終了するとは限らない。
例えば実行した誰かが[Ctrl + C]で中断してしまうかもしれないし、オペミス等でkill(TERM)されてしまうかもしれない。

この時、一時ファイル等を作成していたとするとそのファイルがそのまま残ってしまう。
対処として、trapコマンドを使うという方法がある。
(自分が経験した現場ではそういった事象に備え、スクリプト起動時にrm -fで削除しているところもあったが…)

trapコマンドは

trap '実行コマンド' <シグナル名>

のように書くことで、特定のシグナルを受信した際に指定したコマンドを実行できる。

例えば、シェルスクリプト実行中、何らかの原因で異常終了した場合にメッセージを出力したいとする。
その場合、このように書く。

#!/bin/bash

trap 'echo "異常終了しました。"' HUP INT QUIT TERM

<処理内容>

シグナルは数字でも記述できるが、可読性を考えるとちゃんと文字列で書いた方がいいと思う。
各シグナルの説明は以下のmanページに記載されている。

linuxjm.osdn.jp

応用として、シェルスクリプトの中でコマンドが失敗した場合にエラーを出す使い方もできる。

#!/bin/bash

set -e

trap 'echo "コマンドが失敗しました"' ERR

<処理内容>

set -eは、コマンドが失敗した場合に処理を即停止させるオプション。
trapで指定しているERRはコマンドのエラーを検知するためのもの。
エラーといっても、実際にはコマンドの戻り値を見ており、0以外であればエラー判定される。
例えばgrepなどは文字列検知時に0を返すが、非検知時には1を返すため、エラー判定されやすい問題がある。

この辺は「ハマリポイント」して有名であるようで、if文の条件式に含めたり、一時的にset +eする等の対処方法がある。
以下の記事がとても参考になった。

sousaku-memo.net

他のハマリポイントや、もっと細かく知りたければ以下が参考になる。

qiita.com

シェルスクリプトって奥が深いなぁと思いました。

【おまけ】シグナルとは

シグナルとは、発生したイベントをプロセスに通知するために使用するものである。
killコマンドでプロセスを終了させたことがあると思うが、あれもプロセスにシグナル(デフォルトはTERM)を送っている。
ちなみにTERMは終了シグナル。