システムの運用を行ってくうちに、ディスク容量の枯渇やネットワークの瞬断などが原因で、思わぬ障害に出くわすようになってきます。
そこで、実行シェルに問題が発生した場合などに備え、予め中断ロジックを作成してみます。
「trap」コマンドを使用して、シェルを中断する
シェルには、予め組み込みコマンドとして「trap」コマンドが用意されています。
拾えるシグナルは下記になります。
シグナル | シグナル名 | 意味 |
---|---|---|
0 | - | プロセス終了時に送出する EXIT シグナル |
1 | HUP | ハングアップシグナル |
2 | INT | 割り込みシグナル(Ctrl+C や Del キー) |
3 | QUIT | プログラム実行中止のクイットシグナル |
9 | KILL | プロセスの強制終了 ※ 故意による強制終了なのでtrapでは拾えない |
15 | TERM | プロセスを終了させるための終了シグナル |
コマンドの書式
trap [アクション] シグナル
シェルスクリプトが、シグナルに指定した(複数書けます)シグナルを受け取ったとき、どういう処理をするかをアクションのところに指定します。
アクションには、関数名を指定して、シグナル取得時に関数を実行させることが可能です。
Abortメッセージの作成
メッセージ設定ファイルへ、トラップを拾った際に出力するメッセージを追加しておきます。
[ <BASE_DIR>/scripts/etc/message.conf ]
message.conf
W-00001 user.warn "The shell script aborted the process. Check the log for the cause."
E-00001 user.err " The number of arguments is incorrect. args_count: ["$#"]"
実行シェルスクリプトの作成
簡単な流れ
- 実行シェルへ「sleep」コマンドを実行させて15秒間待機状態にします。
- キーボードから「Ctr + C(INT)」を入力して割り込みします。
- シェルスクリプトは、「abort」関数を呼び出しシェルを中断します。
今回は、「abort」関数へ、外部ファイルから取得したアボートメッセージをログへ出力させてみます。
[ <BASE_DIR>/scripts/bin/func.sh ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
#!/bin/sh #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # # ver.1.0.0 yyyy.mm.dd # # Usage: # # sh /root/scripts/bin/func.sh # # Description: # 例題(トラップ)コマンド実行スクリプト # # 設計書 # なし # #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ . `dirname $0`/../com/comFunc.shrc # ---------------------------------------------------------- # variables (変数の宣言領域) # ---------------------------------------------------------- scope="var" rc=${JOB_ER} # ---------------------------------------------------------- # functions (関数を記述する領域) # ---------------------------------------------------------- scope="func" # -------------------------------------------------- # devider. # -------------------------------------------------- # return N/A # -------------------------------------------------- line (){ echo -e "\\n ------------" echo -e " ▼ ${1}" } # -------------------------------------------------- 👈 「abort」関数追記 # abort shell. # -------------------------------------------------- # return N/A # -------------------------------------------------- abort () { logOut $(getMsg W-00001) exitLog ${JOB_WR} } # ---------------------------------------------------------- # pre-process (事前処理ロジックを記述する領域) # ---------------------------------------------------------- scope="pre" startLog # Set a trap. 👈 トラップを設定します。 trap abort 1 2 3 15 # ---------------------------------------------------------- # main-process (メインロジックを記述する領域) # ---------------------------------------------------------- scope="main" sleep 15 👈 15秒間スリープ状態にします。 if [ $? -eq ${JOB_OK} ]; then rc=${JOB_OK} fi # ---------------------------------------------------------- # post-process (事後処理ロジックを記述する領域) # ---------------------------------------------------------- scope="post" exitLog ${rc} |
実行結果を見てみます。
1 2 3 4 5 6 7 |
[root@CentOS7 bin]# sh func.sh ^C[root@CentOS7 bin]# ^C 👈 「Ctr + C」実行 [root@CentOS7 bin]# cd ../log [root@CentOS7 log]# cat func.log 2020-05-09 16:28:55 [ pre ] SCRIPT:[ func.sh ] PID:[ 9029 ] STARTED LOG. 2020-05-09 16:28:57 [ main ] "The shell script aborted the process. Check the log for the cause." 2020-05-09 16:28:57 [ post ] SCRIPT:[ func.sh ] PID:[ 9029 ] ENDED LOG with WARNING. |
1行目:シェル実行(sleep待機中)
2行目:「Ctr + C」で割り込み実行
5-6行目:ログを確認します。
アボート処理を行った旨のメッセージがログに出力されていることが分かります。
今回は、ログ出力で「trap」コマンドの確認を行いましたが、実際には、シェル実行中に作成した中間ファイルの削除や、マウントポイントをアンマウントしておく等、後処理を記述しておくことが一般的な使い方となります。
※ 本スクリプト利用により発生した利用者の損害全てに対し、いかなる責任をも負わないものとし、損害賠償をする一切の義務はないものとします。