パーzancoの答え、あなたは、リモートコマンドを提供していないssh
シェルはコマンドラインを解析する方法与えられ、。この問題を解決するには、ssh
コマンド呼び出しの構文を変更して、リモートコマンドが構文的に正しい複数行の文字列で構成されるようにします。
使用できるさまざまな構文があります。コマンドはにパイプすることができますので、例えば、bash
そしてsh
あまりにも、そしておそらく他のシェル、最も簡単な解決策は、単に組み合わせることであるssh
ヒアドキュメントとシェル呼び出しを:
ssh user@server /bin/bash <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
上記を実行せず /bin/bash
に警告が発生することに注意してくださいPseudo-terminal will not be allocated because stdin is not a terminal
。また、EOT
は単一引用符で囲まれているためbash
、ヒアドキュメントをnowdocとして認識し、ローカル変数の補間をオフにして、コマンドテキストがそのまま渡されるようにします。ssh
ます。
パイプのファンなら、上記を次のように書き換えることができます。
cat <<'EOT' | ssh user@server /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
上記と同じ警告が/bin/bash
適用されます。
別の有効なアプローチはbash
、次のように変数補間の複数のレイヤーを使用して、複数行のリモートコマンドを単一の文字列として渡すことです。
ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"
上記のソリューションは、この問題を次のように修正します。
ssh user@server
バッシュによって解析され、そしてあると解釈されるssh
コマンド、引数が続くuser@server
に渡されるssh
コマンド
"
補間された文字列を開始します。これは、完了すると、ssh
コマンドに渡される引数を構成します。この場合、引数は、によってssh
実行されるリモートコマンドであると解釈されます。user@server
$(
実行されるコマンドを開始し、出力は周囲の補間された文字列によってキャプチャされます
cat
後に続くファイルの内容を出力するコマンドです。の出力はcat
、キャプチャされた補間文字列に戻されます。
<<
bashのヒアドキュメントを始める
'EOT'
ヒアドキュメントの名前がEOTであることを指定します。'
EOTを囲む単一引用符は、ヒアドキュメントをnowdocとして解析する必要があることを指定します。これは、内容がbashによって補間されず、リテラル形式で渡される、ヒアドキュメントの特別な形式です。
間<<'EOT'
で遭遇<newline>EOT<newline>
し、nowdoc出力に追加されるコンテンツ
EOT
nowdocを終了します。その結果、nowdoc一時ファイルが作成され、呼び出しcat
コマンドに渡されます。cat
nowdocを出力し、出力をキャプチャーされた補間文字列に渡します
)
実行するコマンドを終了します
"
キャプチャされた補間文字列を終了します。補間された文字列の内容は、ssh
単一のコマンドライン引数として渡されます。これssh
は、次のように実行されるリモートコマンドとして解釈されます。user@server
のような外部ツールの使用を回避する必要がありcat
、1つではなく2つのステートメントを使用してもかまわない場合は、read
組み込みのheredocを使用してSSHコマンドを生成します。
IFS='' read -r -d '' SSH_COMMAND <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
ssh user@server "${SSH_COMMAND}"
ssh user@server /bin/bash <<EOT…