回答のまとめ(2020年1月2日)

回答のまとめ(2020年1月2日)

command_1ほとんどのLinuxガイドでは、「実行してから実行してからcommand_2実行する必要がありますcommand_3。」のようなページが含まれています。これらすべてのタスクを手動で実行するのに時間を無駄にしたくないので、スクリプトを作成することをお勧めします。

command_1
command_2
command_3

そして一度実行してみてください。しかし、多くの場合、いくつかのコマンドが失敗し、どのコマンドが失敗したのかわかりません。また、以前にエラーが発生した場合、通常、残りのコマンドはすべて意味がありません。したがって、より良いスクリプトは次のようになります。

   (command_1 && echo OK command_1 || (echo FAILED command_1; false) )
&& (command_2 && echo OK command_2 || (echo FAILED command_2; false) )
&& (command_3 && echo OK command_3 || (echo FAILED command_3; false) )
&& echo DONE 
|| echo FAILED

しかし、あまりにも多くの定型句コードを書く必要があり、各コマンドを3回繰り返す必要があり、いくつかの中括弧を誤って入力する可能性があります。最後のスクリプトが行った操作を実行するより便利な方法はありますか?特に:

  • コマンドを順番に実行
  • コマンドが失敗した場合
  • どのコマンドが失敗したかを記録してください(存在する場合)。
  • コマンドとの正常な対話を可能にします。すべての出力が印刷され、キーボード入力が許可されます(コマンドが何でも必要な場合)。

回答のまとめ(2020年1月2日)

ソリューションには2つのタイプがあります。

  • 修正なしでガイドのコピー/貼り付けコマンドを許可しますが、失敗したコマンドを印刷しません。したがって、失敗したコマンドが長い出力を生成する場合、どのコマンドが失敗したかを確認するには、多くの行を上にスクロールする必要があります。 (すべて人気のある回答)
  • 最後の行を印刷することは失敗しますが、コピーして貼り付けた後に引用符を追加するか(Johnの答え)、ステートメントを追加してリンクされたコマンドを別のコマンドにtry分割(Jasenの答え)してコマンドを変更する必要があります。

お前らは本当にすごいですが、私はこの話をしばらくしておきます。おそらく、誰かが両方の要件を満たすソリューション(最後の行に失敗したコマンドを印刷し、変更なしでコマンドをコピーして貼り付けることができる)を知っている可能性があります。

ベストアンサー1

1つのオプションは、コマンドをbashスクリプトに入れますset -e

ゼロ以外の終了状態でコマンドが終了すると、スクリプトは早期に終了します。

Stack Overflowに関するこの質問も参照してください。https://stackoverflow.com/q/19622198/828193

エラーを印刷するには、次のものを使用できます。

trap 'do_something' ERR

do_somethingエラーを表示するために生成するコマンドはどこにありますか?

以下は、どのように動作するかを確認できるサンプルスクリプトです。

#!/bin/bash

set -e
trap 'echo "******* FAILED *******" 1>&2' ERR

echo 'Command that succeeds'   # this command works
ls non_existent_file           # this should fail
echo 'Unreachable command'     # and this is never called
                               # due to set -e

出力は次のとおりです。

$ ./test.sh 
Command that succeeds
ls: cannot access 'non_existent_file': No such file or directory
******* FAILED *******

さらに、前述のように@ジケ、パイプの終了状態は基本的にパイプの終了状態に設定されていることに注意してください。決定的なコマンドはその中にあります。これは、パイプラインの最後ではないコマンドが失敗してもブロックされないことを意味しますset -e。この問題を解決するには(心配されている場合)、次のものを使用できます。set -o pipefail


私が提案したようにこんにちはそして@モンティハード関数をハンドラとして使用すると、ネストされた参照を防ぐため、スクリプトを読みやすくします。とにかく、関数を使用しているので、set -e関数を完全に削除してハンドラexit 1で使用しました。これにより、一部の人が読みやすくなります。

#!/bin/bash

error_handler() {
  echo "******* FAILED *******" 1>&2
  exit 1
}

trap error_handler ERR

echo 'Command that succeeds'   # this command works
ls non_existent_file           # this should fail
echo 'Unreachable command'     # and this is never called
                               # due to the exit in the handler

スクリプトの終了状態は異なりますが、出力は上記と同じです。

おすすめ記事