修正する:

修正する:

zshスクリプトには長いコマンドパイプラインがあります。

pv /dev/sda > sda.raw | sha256sum > sda.raw.sha256 | cut -c61-64 | read SHASUM

ifすべてのコマンドが正常に終了したかどうか、ステートメント内でどのように確認できますか?

わかりました${pipestatus[@]}。しかし、配列です。したがって、各要素を個別に確認する必要があります。

${pipestatus[@]}含まれている内容だけを確認するショートカットはありますか0

修正する:

いくつかの奇妙な動作を発見しました。

テスト用にすばやく埋めるように小さなファイルシステム(10 MB)を設定しました。

#!/bin/zsh

set -o pipefail

if pv /dev/zero > loop/file ; then
echo OK
else
echo FAIL
fi

期待どおりに「FAIL」を印刷すると、次のエラーが発生します。

pv: write failed: No space left on device

しかし、pvコマンドを少し変更すると、突然エラーが表示されず、pvコマンドが無限に実行されるように見えます(デバイスに余分なスペースがないにもかかわらず)。

#!/bin/zsh

set -o pipefail

if pv /dev/zero > loop/file | sha256sum ; then
echo OK
else
echo FAIL
fi

ベストアンサー1

2つのオプション:

  1. pipefailこのオプションがksh()で設定されている場合、set -o pipefailパイプラインの終了状態は最も右側に失敗したパイプラインコンポーネントの終了状態になります。

    set -o pipefail
    if ! A | B | C; then
      echo at least one of the commands failed.
    fi
    
  2. 検索でゼロ以外の値を見つけます$pipestatus。このextendedglobオプションを有効にすると、左端の失敗したパイプラインコンポーネントと最も右側の失敗したパイプラインコンポーネントの終了ステータスが返されるため$pipestatus[(r)^0](または$pipestatus[(r)<1->]必須ではない)、次のことができます。extendedglob$pipestatus[(R)^0]

    set -o extendedglob
    A | B | C
    if (( $pipestatus[(r)^0] )); then
      echo at least one of the commands failed.
    fi
    

    または

    A | B | C
    if (( $pipestatus[(r)<1->] )); then
      echo at least one of the commands failed.
    fi
    

    /I代わりに下付き文字フラグを使用すると、一番右に一致する要素のインデックスを取得できるため、次のことができます。rRI

    A | B | C
    if (( failed = $pipestatus[(I)<1->] )); then
      echo component $failed failed.
    fi
    

    ${pipestatus:#0}0以外のコンポーネントに拡張されるため、次のことも$pipestatusできます。

    A | B | C
    failed_statuses=( ${pipestatus:#0} )
    if (( $#failed_statuses )); then
      echo "${#failed_statuses} command(s) failed. Statuses: $failed_statuses"
    fi
    

おすすめ記事