web-dev-qa-db-ja.com

"curl | bash"フィードバックを使用してリモートでスクリプトを実行する

私はそのようなコマンドを多く使用するプラットフォームで作業しています:ssh [email protected] 'curl http://some_server/script.sh | bash'

これはスクリプトをリモートで実行するのに非常にクリーンで便利ですが、スクリプトの出力/終了コードを取得する方法がわかりません。だれでも、スクリプトが適切に実行されたことを確認するために何かを理解できます(ホストがsshの観点から起動した場合)。

4
rmonjo

@Zoredacheが指摘するように、sshはリモートコマンドのステータスを独自の終了ステータスとして中継するため、エラー検出はSSH経由で透過的に機能します。ただし、例では2つの重要な点について特別な考慮が必要です。

まず、curlは非常に寛大で、多くの異常な状態を成功として扱います。例えば、 curl http://serverfault.com/some-non-existent-url-that-returns-404の実際の終了ステータスは0です。この動作は直観に反するものです。これらの条件をエラーとして扱うために、私は-fsSフラグ:

  • --failフラグは、障害が発生したときに出力を抑制し、bashがWebサーバーの404エラーページをコードのように実行する機会を与えないようにします。
  • --silent --show-errorフラグを一緒に使用すると、妥当な量のエラー報告が提供されます。 --silentは、curlからのすべての注釈を抑制します。 --show-error STDERRに送信されるエラーメッセージを再度有効にします。

次に、パイプがあります。つまり、最初のコマンドまたは2番目のコマンドのいずれかで障害が発生する可能性があります。 bash(1) のパイプラインに関するセクションから:

pipefailオプションが有効になっていない限り、パイプラインの戻りステータスは、最後のコマンドの終了ステータスです( Set Builtin を参照)。 pipefailが有効になっている場合、パイプラインの戻りステータスは、ゼロ以外のステータスで終了する最後の(右端の)コマンドの値、またはすべてのコマンドが正常に終了した場合はゼロです。

注意事項:bashのドキュメントは、パイプを使用してbashに関係するのではなく、(私は)リモートユーザーのログインシェルであり、したがって、リモートコマンドラインを解釈し、パイプラインの実行を処理するプログラムになります。ユーザーが別のログインシェルを使用している場合は、そのシェルのドキュメントを参照してください。

具体的な例として、

( echo whoami ; false ) | bash
echo $?

出力を生成します

login
0

パイプラインの最後のbashfalseによって返されるエラーステータスをマスクすることを示しています。 whoamiが正常に実行される限り、0を返します。

対照的に、

set -o pipefail
( echo whoami ; false ) | bash
echo $?

収量

login
1

パイプラインの前半での障害が報告されるようにします。


それをすべてまとめると、ソリューションは

ssh [email protected] 'set -s pipefail ; curl -fsS http://some_server/script.sh | bash'

これにより、次のいずれかがゼロ以外の値を返した場合に、ゼロ以外の終了ステータスが取得されます。

  • ssh
  • リモートログインシェル
  • curl
  • パイプラインの最後のbash

さらに、curl -fsSは異常なHTTPステータスコードを検出し、次のことを行います。

  • sTDOUTを抑制して、何も実行されるbashにパイプされないようにします。
  • 正しく伝播されるゼロ以外の値を返す
  • 1行の診断メッセージをSTDERRに出力します。STDERRも伝搬されます。
7
200_success

それはすべて、script.shがその仕事について何をするか/行うかによって異なります。冗長である(出力があるものを実行する)場合は、sshストリームのSTDOUT/STDERRで確認できます。もしそうなら、そうするようにそれを修正しません。

0
tink

SSHが戻ると、スクリプトから終了コードが発行されます。

ssh user@Host 'echo "exit 2" | bash' ; echo $?をお試しください。 2の値が返されます。

スクリプトに適切なエラーチェックをたくさん書いて、スクリプトが有用なエラーと終了コードで終了することを確認してください。エラーがない場合は、スクリプトがゼロ以外の終了コードを返すことを確認してください。

0
Zoredache

ここにあなたが試すことができるいくつかのオプションがあります。

別の方法は、エコー$を使用することでしょうか?スクリプトが実行された直後に実行し、

# ssh [email protected] 'curl http://some_server/script.sh | bash; echo $?' 

これにより、スクリプトの終了ステータスがわかります。または終了ステータスが0の場合にのみテキストを入力します

# ssh [email protected] 'curl http://some_server/script.sh | bash && echo "Script Completed!"'

「スクリプトが完了しました!」と表示されます。成功した実行時。または終了ステータスが0でない場合にのみエラーコードを表示する

# ssh [email protected] 'curl http://some_server/script.sh | bash || echo "Script Failed: $?"'

これにより、「スクリプトが失敗しました:」と表示されます。@ Zoredacheによって提案されているように、スクリプトに複数の終了ステータスを追加すると、問題の原因を特定するのに役立ちます。

0
Danie