SSHを介してさまざまなコンピュータでスクリプトを実行するプロセスを自動化しようとしています。出力コードと戻りコード(エラー検出用)をキャプチャすることが重要です。
終了コードの設定は期待どおりに明示的に機能します。
~$ ssh host exit 5 && echo OK || echo FAIL
FAIL
ただし、異常終了を通知するシェルスクリプトがある場合、sshは常に0を返します(文字列を介してシミュレートされたスクリプトを実行します)。
~$ ssh host sh -c 'exit 5' && echo OK || echo FAIL
OK
対話型シェルのホストシステムでまったく同じスクリプトを実行すると、正常に動作します。
~$ sh -c 'exit 5' && echo OK || echo FAIL
FAIL
なぜこのようなことが起こるのか混乱しています。 bashの戻りコードを伝播するようにsshにどのように指示しますか?おそらくリモートスクリプトを変更しないでしょう。
公開鍵認証を使用しており、秘密鍵がロック解除されました。ユーザーの対話は必要ありません。すべてのシステムはUbuntu 18.04です。アプリケーションのバージョンは次のとおりです。
OpenSSH_7.6p1 Ubuntu-4ubuntu0.1, OpenSSL 1.0.2n 7 Dec 2017
GNU bash, Version 4.4.19(1)-release (x86_64-pc-linux-gnu)
注: この質問は、類似している次の質問とは異なります。
ベストアンサー1
で述べたように回答そこにリモコンがsh
起動しませんexit 5
。のみexit
:
$ ssh test sh -x -c 'exit 5'; echo $?
+ exit
0
たとえば、ここで何が起こっているのかを説明します。この回答:
ssh
リモートシェルを実行して通過ひもそれに、いいえパラメータリスト。
私たちが実行するときssh host sh -c 'exit 5'
:
- ローカルシェルは一重引用符(見積もりの削除);
- クライアントは
ssh
パラメータhost
、sh
および-c
を取得しますexit 5
。これを文字列で接続してリモートホストに送信します。 - リモートホストで
ssh
シェルを呼び出し、文字列を渡しますsh -c exit 5
。 - 以下のようにリモートシェルが呼び出され、オプションが渡され
sh
ます。-c
exit
コマンド文字列と5
コマンド名。
最後に単語を追加すると、追加のexit 5
引数としてのみ渡されますsh
。シェルで認識されないことに関連するエラーはありません。
$ ssh test sh -x -c 'exit 5' a b c; echo $?
+ exit
0
strace
確認は、5
ここに提供されているコマンド文字列の一部ではありませんsh
。これは引数です。
$ ssh test strace -e execve sh -c 'exit 5'; echo $?
execve("/usr/bin/sh", ["sh", "-c", "exit", "5"], 0x7ffc0d744c38 /* 14 vars */) = 0
+++ exited with 0 +++
0
リモートホストで期待どおりに実行するには、sh -c 'command'
引用符を正しく送信していることも確認する必要があります。
$ ssh test "sh -x -c 'exit 5'"; echo $?
+ exit 5
5
現在の問題に関連しない完全なリモートコマンドを明示的に参照するには、次のように書くことができます。
$ ssh test sh -x -c "'exit 5'"; echo $?
+ exit 5
5
内部引用符を2回引用するのではなく、バックスラッシュでエスケープすることも可能です。
命令に対する意見ssh host sh -c ':; exit 5'
(質問に対する意見)それがすることは:
$ ssh test sh -x -c ':; exit 5'; echo $?
+ :
5
つまりexit 5
、ではなくシェルによって実行されますsh
。もう一度sh
目的のコードで終了します。
$ ssh test sh -x -c "':; exit 5'"; echo $?
+ :
+ exit 5
5