単一のパイプコマンドに対するpipefailの設定


18

これらのような非BASHスクリプト(つまり、PHPスクリプト)からパイプされたシェルコマンドをいくつか実行する必要があります。

command1 | command2 | command3

そのため、command1ゼロ以外の終了コードで失敗した場合、他の各コマンドも失敗します。これまでのところ、私が思いついたのは:

set -o pipefail && command1 | command2 | command3

ただし、ターミナルからは正常に実行されますが、スクリプトから実行されると、次のようになります。

sh:1:set:無効なオプション-o pipefail


それが表示されます/bin/sh好きではありませんset -o pipefail。それは実際bashに変装していますか、それとも別のシェルですか?bashとして実行される場合/bin/sh、受け入れられset -o pipefailますか?
ジョナサンレフラー

@JonathanLeffler実行/bin/sh set -o pipefailすると、/bin/sh: 0: Can't open set(と同じことsudo)と表示されます。私が正しくテストしたことを願っています。システムはUbuntu 12です
デスモンドヒューム

試してみる必要があり/bin/sh -c "set -o pipefail"ます。現状では、シェルは呼び出された現在のディレクトリでスクリプトを実行しようとしましたが、set見つかりませんでした。
ジョナサンレフラー

@JonathanLeffler /bin/sh -c "set -o pipefail"は動作しませんが、動作bash -c "set -o pipefail"します。
デズモンドヒューム

だから、あなたの問題は、/bin/sh認識されないスクリプトが実行されることset -o pipefailです。したがって、スクリプトがの/bin/bash代わりに実行されることを確認する必要があります/bin/sh。または、自信がある場合は、勇気があり、おそらく愚かであっ/bin/shても、/bin/bash現在リンクしているシェルまたはコピーの代わりに、リンクまたはコピーに変更します。そうだと確信している場合/bin/shbash、次のbashように実行したときに公開されない動作を使用してい/bin/shます。bashとして使用しbashます。
ジョナサンレフラー

回答:


18

Bashコマンドラインからサブシェルを呼び出して、pipefail後で設定されないようにする必要があります。

$ (set -o pipefail && command1 | command2 | command3)

これにより、pipefailオプションの効果が括弧で作成されたサブシェルに制限されます(...)

実際の例:

$ (set -o pipefail && false | true) && echo pipefail inactive || echo pipefail active
pipefail active

あなたが持つ明示的なシェルの呼び出しを使用する場合-cのオプションをあなたがどちらか、サブシェルを必要としないbashか、とshの別名bash

$ bash -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
$ sh -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active

あなたshpipefailオプションを受け入れないので、私はそれが古いか修正されたバージョンのいずれかであるか、bash実際には完全に他のシェルであると仮定しなければなりません。


1
ある$コマンドの一部は、それだけでシェルプロンプト最初の作品には?両方の方法を試しましたが、実際には機能しませんでした。bash -c道はいつもあまりにもエレガントカントー..ない作品
デズモンド・ヒューム

5

上記の理由がわからない理由はわかりませんがpipefail、を使用して明示的に設定解除することができset +o pipefailます。

set -o pipefail
command1 | command2 | command3
set +o pipefail

フラグメントを実行してpipefailいて、すでに設定されているかどうかがわからない場合は、前述のサブシェルでこれを使用できます。

# explicitly execute with pipefail set
(set -o pipefail ; command1 | command2 | command3 )
# explicitly execute with pipefail unset
(set +o pipefail ; command1 | command2 | command3 )

0

$(command1)と$?を組み合わせて使用​​できます。:

a=$(echo "a")
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

「abc」を印刷します

a=$(ls unexitingDir)
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

「」を印刷します。

「[$?-eq 0] &&」は、前のコマンドが成功した場合にのみ、次のコマンドが実行されることを意味します。

それはあなたの質問には答えませんが、それはあなたの問題の解決策です。


各コマンドの出力を常に変数に保存する必要があるということですか?
デズモンドヒューム

いつもわからないが、私のソリューションではそうだろう(次のコマンドで必要な場合)。あなたが書くことができない限りcommand1 && command2 && command3
cglacet
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.