Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
99
Help us understand the problem. What is going on with this article?

More than 5 years have passed since last update.

@kobake@github

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

今回実現すること

シェルスクリプトの途中でエラーが発生した(コマンドの終了ステータスが 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

99
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
99
Help us understand the problem. What is going on with this article?