111
101

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Shell ScriptAdvent Calendar 2015

Day 23

エラー監視時(set -e)の汎用トラップコード(trap)

Last updated at Posted at 2015-12-22

今回実現すること

シェルスクリプトの途中でエラーが発生した(コマンドの終了ステータスが 0 以外だった)とき、スクリプトを中断し、エラー発生時の環境情報を出力する。実行例は以下。

$ ./sample1.sh aa "bb" "cc dd"
hello
mondai hassei ← ここで問題発生

------------------------------------------------------------
Error occured on ./sample1.sh [Line 8]: Status 1

PID: 3888
User: kobake
Current directory: /test/shell
Command line: ./sample1.sh "aa" "bb" "cc dd" 
------------------------------------------------------------

手段概要

シェルスクリプトの実行において set -e しておくと、それ以降のコマンド実行結果が正常でなかった(終了ステータスが 0 以外だった)場合にスクリプトが中断するわけだが、ただ何もせずに終了してしまうと問題解析がめんどくさい。

そんなわけで set -e する際には trap を利用して何かしらのメッセージを表示するのが一般的かと思う。

ただ、シェルスクリプト毎に trap 処理を書くのは非生産的なので、共通の trap 処理があるとなかなか捗る。

汎用トラップコード

エラーを検出したときに onerror が呼ばれるようにしているのだが、この中で問題解析時によく参照するであろう諸々の情報を出力しておく、というもの。

error_trap.sh
#!/bin/bash

onerror()
{
    status=$?
    script=$0
    line=$1
    shift

    args=
    for i in "$@"; do 
        args+="\"$i\" "
    done

    echo ""
    echo "------------------------------------------------------------"
    echo "Error occured on $script [Line $line]: Status $status"
    echo ""
    echo "PID: $$"
    echo "User: $USER"
    echo "Current directory: $PWD"
    echo "Command line: $script $args"
    echo "------------------------------------------------------------"
    echo ""
}

begintrap()
{
    set -e
    trap 'onerror $LINENO "$@"' ERR
}

begintrap

トラップコードの利用

./error_trap.sh を「.」により実行することで、エラー監視が始まる。

sample1.sh
#!/bin/bash

# エラートラップ開始
. ./error_trap.sh

# 処理
echo hello
./e.sh
echo world
e.sh
#!/bin/bash

>&2 echo "mondai hassei"
exit 1

e.sh はエラーを返すだけのダミースクリプト。

echo hello
./e.sh ← ここでエラーが発生
echo world

実行結果

こんな感じ。
hello 出力の後の e.sh でエラーが発生し、そこで処理は中断される。それ以降の world 出力は実行されない。

$ ./sample1.sh aa "bb" "cc dd"
hello
mondai hassei

------------------------------------------------------------
Error occured on ./sample1.sh [Line 8]: Status 1

PID: 3888
User: kobake
Current directory: /test/shell
Command line: ./sample1.sh "aa" "bb" "cc dd" 
------------------------------------------------------------

必要に応じて onerror には $PATH 出力等を加えたり等、諸々情報を増やしていくと良い(邪魔にならない範囲で)。

スクリプトの出力内容が多いとパっと見でエラー情報が埋もれがちなので、こうやって罫線で囲って目立つようにしてあげるのもけっこう大事だと思っている。

今回のサンプル

以下に設置。
https://github.com/kobake/bash-error-trap-sample

111
101
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
111
101

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?