特定のコマンドのエラーを無視するbash


444

次のオプションを使用しています

set -o pipefail
set -e

エラー時に実行を停止するbashスクリプト。実行中のスクリプトが100行まであり、スクリプトのすべての行の戻りコードを確認したくありません。

しかし、ある特定のコマンドについては、エラーを無視したいと思います。どうやってやるの?

回答:


757

ソリューション:

particular_script || true

例:

$ cat /tmp/1.sh
particular_script()
{
    false
}

set -e

echo one
particular_script || true
echo two
particular_script
echo three

$ bash /tmp/1.sh
one
two

three 印刷されることはありません。

また、pipefailオンにすると、パイプ内のコマンドの1つがゼロ以外の終了コードを持っているときに、シェルがパイプ全体がゼロ以外の終了コードを持っているとシェルが考えるのに十分であることを追加したいと思います(pipefailオフでは最後のコードでなければなりません) 。

$ set -o pipefail
$ false | true ; echo $?
1
$ set +o pipefail
$ false | true ; echo $?
0

15
+1。Bashリファレンスマニュアルで説明-eされているように、属性が設定されている場合、「シェルは終了しません。失敗したコマンドが、whileまたはuntilキーワードの直後のコマンドリストの一部、ifステートメントのテストの一部、実行されたコマンドの一部である場合中&&または||最後の次のコマンドを除いて、リスト&&||、任意のコマンドパイプラインではなく、最後の、またはコマンドのリターンステータスが反転されているかどうかを!。」
ruakh

@IgorChubin理由はわかりませんが、これは機能しません。output= (ldd $2/bin/* || true) | grep "not found" | wc -lスクリプトは、lddが失敗すると、この行の後で終了します
Vivek Goel

1
(ldd $2/bin/* || true) | grep "not found" | wc -l || true
Igor Chubin

1
のせいでset -o pipefailgrep何も見つからなかった場合は、ゼロ以外の終了コードが返され、パイプ全体がゼロ以外の終了コードを持っているとシェルが考えるのに十分です。
Igor Chubin

3
(終了せずに)戻り値を保持するオプションが必要な場合は、mycommand && trueを試してください。これにより、後続のステップで戻りコードを確認し、プログラムで処理できます。
エド・オスト

178

|| trueエラーを無視する場所にコマンドの後に追加するだけです。


11
これを追加することが重要だと思います。このメソッドを使用すると、応答コードとエラーメッセージを保持できますが、「!」以下で説明する方法では、応答コードが変更されるため、エラーは生成されません。使用している場合、このことは重要であるset -eとのエラーメッセージをキャプチャしようとしている:例えばset -e; TEST=$(foo 2>&1 || true); echo $TEST
Spanky

87

停止せず、終了ステータスも保存する

特定のコマンドが失敗してもスクリプトが停止しないようにして、失敗したコマンドのエラーコードも保存したい場合に備えて:

set -e
EXIT_CODE=0
command || EXIT_CODE=$?
echo $EXIT_CODE

2
これがまさに私が必要としていたことです
。–

なんらかの理由で私にはうまくいきません...まあ
Jeef

コマンドが0を返す場合、EXIT_CODEはゼロに設定されません。ただし、ゼロ以外の終了コードがキャプチャされます。なぜか?
Ankita13

@ Ankita13なぜならそれがゼロだった場合、最初commandは成功し、その後何を実行する必要があるから||です。それを次のように読んでcommandくださいEXIT_CODE=$?。失敗した場合は、実行してください。command || echo "$?"より詳細なデバッグを行うには、おそらく「トラップ」を実行するか使用するだけです。これを参照してください-> stackoverflow.com/a/6110446/10737630
tinnick

63

より簡潔に:

! particular_script

(強調鉱山)に関するPOSIX仕様からset -e

このオプションがオンの場合、「シェルエラーの結果」にリストされているいずれかの理由で単純なコマンドが失敗するか、終了ステータス値> 0を返し、while、until、またはifキーワードに続く複合リストの一部ではない場合、およびANDまたはORリストの一部ではなく、!に続くパイプラインではありません予約語、シェルはすぐに終了します。


16
これはコマンドの終了コードを反転するだけなので、正常に終了したコマンドは0ではなく1を返し、でスクリプトを失敗させます-e
Marboni

17
私の理解では!、シェルは何があってもシェルが終了するのを防ぎます。このスクリプトStill alive!を実行すると、スクリプトが最後まで実行されたことを示すメッセージが表示されます。異なる動作を見ていますか?
リリーフィンリー2015年

7
正解です。終了ステータスが反転しますが、コマンドが0または1の両方で終了してもスクリプトはクラッシュしません。とにかく、ドキュメントを引用してくれてありがとう、私は私の表現をif節に入れて問題を解決しました。
Marboni

42

「trueを返す」代わりに、「noop」またはnullユーティリティー(POSIX仕様で参照):を使用して、「何もしない」こともできます。いくつかの手紙を保存します。:)

#!/usr/bin/env bash
set -e
man nonexistentghing || :
echo "It's ok.."

3
||:はそれほど明確ではありませんが|| 真実(エキスパート以外のユーザーを混乱させる可能性があります)、簡潔さを気に入っています
David

このバリアントは、CIで重要になる可能性があるテキストを返しません。
kivagant

5

スクリプトが失敗するのを防ぎ、戻りコード収集したい場合:

command () {
    return 1  # or 0 for success
}

set -e

command && returncode=$? || returncode=$?
echo $returncode

returncode コマンドが成功したか失敗したかに関係なく収集されます。


2

CLIツールを使用する際に以下のスニペットを使用していて、リソースが存在するかどうかを知りたいのですが、出力については気にしません。

if [ -z "$(cat no_exist 2>&1 >/dev/null)" ]; then
    echo "none exist actually exist!"
fi

1
これは本当に回り道であり、適度に高額な言い方になるようですif [ -r not_exist ]
tripleee

1

私はこのソリューションが好きです:

: `particular_script`

バックティックの間のコマンド/スクリプトが実行され、その出力がコマンド ":"( "true"と同等)に送られます。

$ false
$ echo $?
1
$ : `false`
$ echo $?
0

編集:醜い誤植を修正


0

しばらくは|| true好ましいものですが、あなたも行うことができます

var=$(echo $(exit 1)) # it shouldn't fail

0

ここからは解決策が機能しなかったため、別の解決策を見つけました:

set +e
find "./csharp/Platform.$REPOSITORY_NAME/obj" -type f -iname "*.cs" -delete
find "./csharp/Platform.$REPOSITORY_NAME.Tests/obj" -type f -iname "*.cs" -delete
set -e

これはCIとCDに役立ちます。このようにして、エラーメッセージが出力されますが、スクリプト全体は引き続き実行されます。


0
output=$(*command* 2>&1) && exit_status=$? || exit_status=$?
echo $output
echo $exit_status

これを使用してログファイルを作成する例

log_event(){
timestamp=$(date '+%D %T') #mm/dd/yy HH:MM:SS
echo -e "($timestamp) $event" >> "$log_file"
}

output=$(*command* 2>&1) && exit_status=$? || exit_status=$?

if [ "$exit_status" = 0 ]
    then
        event="$output"
        log_event
    else
        event="ERROR $output"
        log_event
fi

0

上記の簡単な解決策をありがとうございます:

<particular_script/command> || true

次の構成は、スクリプトステップの追加のアクション/トラブルシューティングと追加のフロー制御オプションに使用できます。

if <particular_script/command>
then
   echo "<particular_script/command> is fine!"
else
   echo "<particular_script/command> failed!"
   #exit 1
fi

exit 1必要に応じて、さらにアクションを停止できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.