bash入門:trapについて

スポンサーリンク
bash入門:trapについて ノウハウ
bash入門:trapについて
この記事は約7分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、bashにおけるtrapについてご紹介します。

スポンサーリンク

背景

bashにおけるtrapについて調査する機会があったので、そのときの内容を備忘として残しました。

この記事のソースは下記のサイトにアップしています。

実行環境について

実行環境は下記の記事を参考にお願いします。

概要

本記事のtrapは、エラーが発生した箇所を標準出力します。

作成ファイル一覧

下記のファイルを作成しました。

        new file:   local/work/08_trap/08_trap.sh

08_trap.sh

#!/usr/bin/env bash

set -euCo pipefail

readonly LOG_OUT=./stdout.log
readonly LOG_ERR=./stderr.log

exec 1> >(tee -a "$LOG_OUT")
exec 2> >(tee -a "$LOG_ERR")

function trap_err() {
    error_status=$?
    echo "エラー発生 \$?=${error_status} ${BASH_SOURCE[0]} ${FUNCNAME[1]}:${BASH_LINENO[0]}"
}

trap trap_err ERR

function log() {
    echo "[$(date '+%Y/%m/%d %H:%M:%S.%3N')] $*"
}

log "$(which bash)"

log "$(bash --version)"

# 標準エラーへの出力確認用
ls dummy.txt

echo "ここは表示されない"

動作確認

下記のコマンドを実行します。

make build

make up

make login

cd 08_trap

chmod +x 08_trap.sh

./08_trap.sh

strout.logにも同様のエラー文言が出力されている想定です。

[2023/12/10 07:46:17.340] /usr/bin/bash
[2023/12/10 07:46:17.347] GNU bash, version 5.2.15(1)-release (aarch64-unknown-linux-gnu)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
ls: cannot access 'dummy.txt': No such file or directory
エラー発生 $?=2 ./08_trap.sh main:27

解説

08_trap.sh

このスクリプトは、エラーが発生した際にエラーハンドリングを行う Bash スクリプトです。以下に各部分の解説を示します。

  1. #!/usr/bin/env bash: スクリプトが Bash シェルで実行されることを指定しています。
  2. set -euCo pipefail: スクリプトの設定を変更しています。
  • -e: エラーが発生したら即座にスクリプトを終了します。
  • -u: 未定義の変数を使用しようとするとエラーを発生させます。
  • -C: コマンドの返り値が0以外の場合、そのコマンドが非零であることを示します。
  • -o pipefail: パイプの途中でエラーが発生した場合、パイプ全体をエラーとして扱います。
  1. readonly LOG_OUT=./stdout.log: 標準出力を記録するログファイルのパスを指定します。
  2. readonly LOG_ERR=./stderr.log: 標準エラーを記録するログファイルのパスを指定します。
  3. exec 1> >(tee -a "$LOG_OUT"): 標準出力をファイルにリダイレクトし、同時にその内容を標準出力にも表示します。リダイレクト先は $LOG_OUT となります。
  4. exec 2> >(tee -a "$LOG_ERR"): 標準エラーをファイルにリダイレクトし、同時にその内容を標準エラーにも表示します。リダイレクト先は $LOG_ERR となります。
  5. function trap_err() { ... }: trap_errという関数を定義しています。この関数は、trapコマンドを使用してエラーが発生した際に呼び出されるように設定されます。エラーが発生した場合、エラーの発生箇所とエラーのステータスを表示します。
  6. trap trap_err ERR: trapコマンドを使用して、ERR(エラーが発生した際)に対してtrap_err関数が呼び出されるように設定しています。
  7. function log() { ... }: logという関数を定義しています。この関数は、指定されたメッセージを日付とともにログとして表示します。
  8. log "$(which bash)": インストールされている Bash の実行ファイルのパスをログに記録します。
  9. log "$(bash --version)": Bash のバージョン情報をログに記録します。
  10. ls dummy.txt: 標準エラーへの出力確認用に、存在しないファイル dummy.txtls コマンドでリストします。この部分でエラーが発生し、trap_err関数が呼び出され、エラーの発生箇所とエラーのステータスが表示されます。
  11. echo "ここは表示されない": 上記の ls dummy.txt でエラーが発生した場合、この行は実行されません。スクリプトはエラーが発生した時点で終了するため、この行は実行されません。

このスクリプトはエラーハンドリングの例であり、エラーが発生した場合にそれを適切に処理する仕組みが組み込まれています。

trapコマンドについて

trapは、シェルスクリプト内でシグナル(信号)やイベントを捕捉し、それに対して特定の処理を実行するためのコマンドです。主にエラーハンドリングやシグナルの処理に使用されます。trapの基本構文は以下の通りです:

trap 'コマンド' シグナル
  • 'コマンド': シグナルが発生したときに実行するコマンドやシェルスクリプトを指定します。シグナルが発生すると、このコマンドが実行されます。
  • シグナル: trapが設定されるシグナルを指定します。例えば、ERRはエラーが発生したとき、EXITはスクリプトが終了するときなどです。

以下によく使用されるtrapの用途をいくつか紹介します:

  1. エラーハンドリング: trap 'echo "エラーが発生しました"' ERR この例では、スクリプト内でエラーが発生した際に、”エラーが発生しました”と表示するようになります。
  2. スクリプト終了時の処理: trap 'echo "スクリプトが終了しました"' EXIT スクリプトが終了するときに、”スクリプトが終了しました”と表示するようになります。
  3. 特定のシグナルの無視: trap '' HUP HUPシグナル(ハングアップシグナル)を無視するように設定します。
  4. トラップを解除: trap - ERR ERRシグナルに設定されたトラップを解除します。

trapはシェルスクリプト内で複数回使用することができ、同じシグナルに対して複数の処理を指定することもできます。また、シグナルには標準のシグナル(ERREXITなど)の他に、カスタムのシグナルも利用することができます。

おわりに

今日は、bashにおけるtrapについてご紹介しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました