web-dev-qa-db-ja.com

関数またはサブシェルで使用されない限り、コマンド出口のトラップが機能しない

サンプルコードを使用して、無効なコマンドリターンコードでtrapを少し実験しています

#!/bin/bash

# Exit on error
trap 'echo 'exiting..';exit' ERR
set -e

h=1
b=$((h+)) # <----- command causing the error
echo $?
echo $b
echo "end"

問題のある指示があっても、トラップを発生させることはできません。しかし、サブシェルで実行した場合も同じです

function junk() {
h=1
b=$((h+))
echo "Exit code:$?"
echo $b
echo "end"
echo "Hello"
}

junk

(または)サブシェルで命令全体を実行する

(h=1
b=$((h+))
echo "Exit code:$?"
echo $b
echo "end"
echo "Hello"
)

コマンドの失敗をキャッチでき、EXITはトラップをキャッチし、それに応じてメッセージを出力します。

set -eの使用法を認識しています

-e  errexit When set, the Shell exits when a simple command in a command list exits
    non-zero (FALSE). This is not done in situations, where the exit code is already checked 
    (if, while, until, ||, &&)

しかし、サブシェルや関数などでのみ発生すると書かれている適切なリファレンスを見つけることができません。

ここで基本的なものが不足している場合はお知らせください。

3
Inian

不足しているのは、_set -e_とsigspec ERRの両方がコマンド実行(ゼロ以外の値で終了するコマンド)に適用されることです。ここにb=$((h+))があるのは、解析エラーです。コマンドは理解されていないため、not実行されます。

関数またはサブシェルで機能するのはなぜですか?この解析エラーにより、含まれているスクリプト(関数またはサブシェル)が全体として失敗するためです。言い換えると、これはトラップをトリガーするb=$((h+))ではなく(サブシェルにトラップが設定されていない)、これはjunkまたはサブシェルの呼び出しの失敗です。

6
xhienne