このスクリプトを実行しようとしています。
#!/bin/bash -e
{
echo "Doing something";
will_fail # like `false`
echo "Worked";
} || echo "Failed"
驚いたことにwill_fail
失敗しましたが、コマンドラインに「失敗」が表示されずに「動作」しました。
失敗後に複合コマンドがエラーなしで終了するのはなぜですかwill_fail
?
答え1
Failed
複合コマンドの終了ステータスは、で実行された最後のコマンドの終了ステータスであるため、印刷されません{ ...; }
。echo
Successecho
なので、複合コマンドは終了状態 0 で終了します。
次は3つの文字列を出力します。
{ echo "Do something"; echo "Worked"; false; } || echo "Failed"
~からPOSIX規格:
特に明記しない限り、コマンドの終了ステータスは、そのコマンドによって実行された最後の単純コマンドの終了ステータスです。
ここではさまざまなことが起こっています(要約)。
あなたは
set -e
積極的に走っています。コマンドがゼロ以外の終了状態を返す場合(代替として)、シェルは終了します。ただし、コマンドは(リストの一部であるwill_fail
複合コマンド)の一部であるため(そしてリストの最後のコマンドではないため)、これには適用されません。||
また、POSIX規格(私のハイライト):
予約語の後に、、、、または複合リストを実行するとき
-e
、予約語で始まるパイプ、またはwhile
until
if
elif
!
どんな命令でも最後の項目を除くAND-ORのリスト。リストの最後の簡単なコマンド
||
はですecho "Failed"
。これは、複合コマンドの完全終了状態を決定します。正常に実行されたため(そしてwill_fail
シェルが終了していないため)、状態はゼロになり、これは反対側の端が||
実行されないことを意味します。
答え2
私の考えでは紹介する許可された回答(+1
徹底のために編集したにもかかわらず)は誤解を招く可能性があり、存在する場合は正確な問題を説明しませんset -e
。下の行の残りの部分に答えが含まれています。私は直接ここに来て、もともと間違った情報を受け取ったので、書くことにしました。
複合コマンドの終了状態は{...;内で実行された最後のコマンドの終了状態であるため、失敗は印刷されません。 }、これはエコーです。 echo が成功したため、複合コマンドは終了状態 0 で終了します。
最初に渡す必要があるのはここset -e
から場所{ ... }
リストのAND-ORです。部品が取り外されると、部品が故障した直後に|| echo "Failed"
複合コマンドが{ ... }
中断されます。最終注文もできませんでした。{ ... }
比較する
#!/bin/bash -e
{
echo "Doing something";
false
echo "Worked";
}
その後、何も印刷せずにエラーDoing something
で終了します。しかし、(これが答えが間違っている理由です)内部の最後の複合{ ... }
コマンドですecho
。
しかし、
#!/bin/bash -e
{
echo "Doing something";
false
echo "Worked";
} || echo "Failed"
Worked
印刷後、Doing something
呼び出しは行われず、終了echo "Failed"
ステータス0が返されます。
理由引用符で埋められている(許可された回答でより詳細に提供されています):set -e
はい障害のあるAND-ORコマンドの一部であるすべて。
末尾の場合はAND-ORコマンドの一部になるので従順を中断|| echo "Failed"
します。途中はフローに影響を与えずに進み、AND-ORに0を返して呼び出しスクリプトに戻ります。{...}
set -e
false
echo "Worked"
後続のコマンドがない場合、それ自体は|| echo "Failed"
一般{ ... }
的な複合コマンドのセットであり、POSIXで述べられている例外に該当せずに準拠していますset -e
。その部分に達すると実行が停止false
し、実行フローがその部分に達していなくてもecho "Worked"
呼び出しスクリプトにエラーが返されます。