bash入門:trapについて -スクリプト終了時に処理をする-

スポンサーリンク
bash入門:trapについて -スクリプト終了時に処理をする- ノウハウ
bash入門:trapについて -スクリプト終了時に処理をする-
この記事は約7分で読めます。
よっしー
よっしー

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

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

スポンサーリンク

背景

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

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

実行環境について

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

概要

本記事のtrapは、スクリプト終了時に必ずする処理をします。

作成ファイル一覧

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

        new file:   local/work/10_finally/10_finally.sh

10_finally.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 log_debug() {
    log 'DEBUG' "$*"
}

function log_err() {
    log 'ERROR' "$*"
}

function log() {
    printf "%s\t[%5s]\t%s\n" "$(date '+%Y/%m/%d %H:%M:%S.%3N')" "$1" "$2"
}

function trap_err() {
    error_status=$?
    msg=$(printf "エラー発生 \$?=%d %s %s:%d" ${error_status} "${BASH_SOURCE[0]}" "${FUNCNAME[1]}" ${BASH_LINENO[0]})
    log_err "${msg}"
}

function trap_exit() {
    msg=$(printf "終了時の処理 %s %s:%d" "${BASH_SOURCE[0]}" "${FUNCNAME[1]}" ${BASH_LINENO[0]})
    log_debug "${msg}"
}

trap trap_err ERR

trap trap_exit EXIT

log_debug "$(which bash)"

log_debug "$(bash --version)"

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

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

動作確認

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

make build

make up

make login

cd 10_finally

chmod +x 10_finally.sh

./10_finally.sh

strout.logに下記の文言が出力されている想定です。

2023/12/10 14:45:59.721	[DEBUG]	/usr/bin/bash
2023/12/10 14:45:59.726	[DEBUG]	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
2023/12/10 14:45:59.742	[ERROR]	エラー発生 $?=2 ./10_finally.sh main:43
2023/12/10 14:45:59.745	[DEBUG]	終了時の処理 ./10_finally.sh main:1

解説

10_finally.sh

このスクリプトは、trapコマンドを使用してエラーハンドリングとスクリプト終了時の処理を行う 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 log_debug() { ... }: log_debugというデバッグ用のログを記録する関数を定義しています。log関数を呼び出して、ログの種類を “DEBUG” としています。
  6. function log_err() { ... }: log_errというエラーログを記録する関数を定義しています。log関数を呼び出して、ログの種類を “ERROR” としています。
  7. function log() { ... }: logという共通のログを記録する関数を定義しています。日付、ログの種類、メッセージを整形して表示します。
  8. function trap_err() { ... }: trap_errというエラーが発生した際に呼び出される関数を定義しています。エラーのステータスや発生箇所の情報を取得し、log_err関数を呼び出してエラーログを記録します。
  9. function trap_exit() { ... }: trap_exitというスクリプトが終了する際に呼び出される関数を定義しています。終了時の処理を行い、log_debug関数を呼び出してデバッグログを記録します。
  10. trap trap_err ERR: ERR シグナルに対して、trap_err関数が呼び出されるように設定します。
  11. trap trap_exit EXIT: EXIT シグナルに対して、trap_exit関数が呼び出されるように設定します。
  12. log_debug "$(which bash)": インストールされている Bash の実行ファイルのパスをデバッグログに記録します。
  13. log_debug "$(bash --version)": Bash のバージョン情報をデバッグログに記録します。
  14. ls dummy.txt: 標準エラーへの出力確認用に、存在しないファイル dummy.txtls コマンドでリストします。この部分でエラーが発生し、trap_err関数が呼び出されてエラーログが記録されます。
  15. echo "ここは表示されない": 上記の ls dummy.txt でエラーが発生した場合、この行は実行されません。スクリプトはエラーが発生した時点で終了するため、この行は実行されません。
  16. スクリプト終了時に trap_exit関数が呼び出され、終了時の処理が実行されます。

おわりに

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

よっしー
よっしー

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

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

コメント

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