ssh経由でコマンドを実行できない

ssh経由でコマンドを実行できない

FreeBSDマシン(xxx.yyy.zzz.net)でコマンドを実行し、出力を取得しています。

指示

sudo camcontrol devlist | grep -o 'ada[0-9]' | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done

出力

media RPM             non-rotating
media RPM             non-rotating
media RPM             non-rotating

別のマシンからsshを使用して同じコマンドを実行しようとしています

指示

ssh xxx.yyy.zzz.net sudo camcontrol devlist | grep -o 'ada[0-9]' | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done

エラー

sudo: camcontrol: command not found

答え1

コマンドでは、すべてが|ローカル シェルによって解釈されます。最後の引数sshは ですdevlistsshはローカルで呼び出されます (これは驚くことではありません)。ただし、最初の の後のすべてのものも同様です|

発生したエラーはsudo次のスニペットから発生しました: do sudo camcontrol identify $a。これはローカルで実行され、どうやらcamcontrolローカル マシンでは利用できないようです。

適切なエスケープまたは引用符が必要です。この場合、リモート コマンド全体を一重引用符で囲む必要があります。

ssh xxx.yyy.zzz.net 'sudo camcontrol devlist | grep -o "ada[0-9]" | while read -r a ; do sudo camcontrol identify $a | grep rotating ; done'

すでにある一重引用符を変更したことに注意してください。(追加された)一重引用符は、文字列全体をグループ化してssh取得するだけでなく、 のローカル展開も防止します$a

sudoがパスワードを尋ねる場合、擬似端末が必要になります。-tのオプションを使用して擬似端末の割り当てを強制することができますssh(つまり のようになりますssh -t xxx.yyy.zzz.net …)。ssh -tはリモート側に擬似端末を割り当てることに注意してください。リモートはsudostderr にプロンプ​​トを表示しますが、その後 stdout と stderr がこの擬似端末によって「出力」され (通常コンソールに出力されるのと同じように)、この時点ではこれらを区別できなくなります。マージされたストリームがキャプチャされ、ローカル側に転送されて stdout に送られます。 がない場合、-tリモートの stdout と stderr は別々に転送され、ローカル側の stdout と stderr に移動し、最終的にこれらがマージされて (リダイレクトされている場合はマージされずに) 表示されます。つまり、 では-t(ローカル側で) リモートの stderr とリモートの stdout を区別できません。出力をさらにローカルで処理 (リダイレクト) する必要があり、 を使用する場合、-tからのプロンプトsudoは干渉します。

また、おそらく二重引用符を使用する必要があるでしょう$a( を使用しない最初のコマンドでもssh)。シェル スクリプトが空白文字やその他の特殊文字で動作しなくなるのはなぜですか?

関連情報