77338


bashスクリプトで$()をネストしている場合でも`set -e`コマンドでエラー時に終了させるにはどうしたらよいでしょうか。

[code]

    #!/bin/bash 
    
    set -euC
    
    # スクリプトがおかれているディレクトリを取得
    # 実行例
    # ./test.sh
    # 実行結果
    # test.sh: 行 19: cdd: コマンドが見つかりません
    # RESULT
    # /workspace
    
    
    # 正しい例
    SCRIPT_FILE_DIR=$(cd "$(dirname "$0")"; pwd)
    
    # 誤った例
    # cd を cdd とタイポしている
    SCRIPT_FILE_DIR=$(cdd "$(dirname "$0")"; pwd)
    readonly SCRIPT_FILE_DIR
    
    echo "RESULT"
    echo "$SCRIPT_FILE_DIR"
    
    
    
[/code]


CC BY-SA 4.0
2021-05-31T00:13:24.710
76209
2021-08-05T11:52:46.953
2021-05-31T00:25:00.543
19297
19297
question
bash shellscript shell
bashスクリプトでネストした$()でもsetコマンドでエラー時に終了させる方法


-Eオプションをsetし、ERRをトラップして明示的にexitするのはいかがでしょうか？
[code]

    #!/bin/bash
    #set -euC
    set -E
    trap 'exit $?' ERR
    
    # スクリプトがおかれているディレクトリを取得
    # 実行例
    # ./test.sh
    # 実行結果
    # test.sh: 行 19: cdd: コマンドが見つかりません
    # RESULT
    # /workspace
    
    
    # 正しい例
    SCRIPT_FILE_DIR=$(cd "$(dirname "$0")"; pwd)
    
    # 誤った例
    # cd を cdd とタイポしている
    SCRIPT_FILE_DIR=$(cdd "$(dirname "$0")"; pwd)
    readonly SCRIPT_FILE_DIR
    
    echo "RESULT"
    echo "$SCRIPT_FILE_DIR"
    
[/code]

実行するとecho "RESULT"の前にスクリプトが終了します。

[code]

    ./qw.sh: 行 21: cdd: コマンドが見つかりません
    
[/code]

metropolisさんのコメントを受けて`trap 'exit $?' ERR`としました。  
`$?`がtrapで指定したコマンドに引き継げることも確認しました。


CC BY-SA 4.0
2021-06-04T11:07:14.357
77338
2021-06-04T12:37:23.797
2021-06-04T12:37:23.797
35558
35558
76209
answer


これはコマンド置換の中に `set -e` (errexit) の効果が継承されないという問題です。POSIX に準拠した動作ではないので（bash
2.05.0 以上であれば） `set -o posix` もしくは POSIX モード（`sh`）で起動することによって解決します。また bash 4.4
以上であれば `shopt -s inherit_errexit` でこの問題だけを個別に POSIX に準拠させることができます。

[code]

    #!/bin/bash
    set -e
    shopt -s inherit_errexit # または set -o posix
    
    output=$(no-such-a-command; echo ok)
    echo "end: $output" # ここにはこない
    
[/code]

その他の解決策としてはコマンド置換の中で `set -e` を再有効化することでも解決することができます。

[code]

    #!/bin/bash
    set -e
    
    output=$(set -e; no-such-a-command; echo ok)
    echo "end: $output" # ここにはこない
    
[/code]


CC BY-SA 4.0
2021-08-05T11:52:46.953
80620
2021-08-05T11:52:46.953
47538
76209
answer