複数のリモートサーバーで実行したいローカルスクリプトがあります。私が使用するコマンド構文は次のとおりです。
ssh <remote_server> "bash -s" < ./local_script.sh
これはうまく機能し、引数を渡すこともできます。ローカルscript.sh。しかし、私は次のように入力ファイルを渡したいと思います。
local_script.sh < local_file.txt
これら2つの文を組み合わせると、次のような結果が得られます。
ssh <remote_server> "bash -s" < ./local_script.sh < local_file.txt
私がこれを実行すると、私は得ます。
bash: line 1: FOO: command not found
bash: line 2: BAR: command not found
bash: line 3: BAZ: command not found
...
ここで、FOO、BAR、BAZなどは各行の最初の単語です。ローカルファイル.txt:
FOO FOO_PARAM1
BAR BAR_PARAM1
BAZ BAZ_PARAM2
...
だから"bash -s"
リモートサーバーが解釈しているようです。ローカルファイル.txt入力ファイルではなくスクリプトファイルとしてローカルscript.sh。この問題を解決する方法はありますか(ラッパースクリプトを作成することに加えて)?
ベストアンサー1
2つの独立した出力ストリーム(stdoutとstderr用)が提供されますが、ssh
入力ストリーム(stdin)は1つのみを提供します。したがって、他のメカニズムを介してスクリプトコンテンツと入力ファイルを渡す必要があります。
たとえば、1つは変数を介して、もう1つはstdinを介して:
LC_CODE=$(cat local_script.sh) ssh host 'eval "$LC_CODE"' < input
(ssh
クライアントが変数を渡しLC_*
(SendEnv
in ssh_config
)sshd
、サーバーがそれを受け入れるとします(AcceptEnv
in sshd_config
))
または、local_script.sh
リモートユーザーのログインシェルがこのスクリプト構文の正しい選択であると仮定し、その内容をリモートシェルコードに渡すだけです。
ssh host "$(cat local_script.sh)" < input
または、次のようにコードと入力をssh
stdinに接続します。
{
echo '{'; cat local_script.sh; echo '}; exit'
cat input
} | ssh host 'bash -s some arguments'
ここで使用するbash
と、入力は一度に1バイトずつ読み取られ、他のすべてのシェルはそうでない行bash
よりも読みにくくなります。}; exit
または、sed
リモートホストがGNUの場合sed
:
echo '#END-OF-SCRIPT' | cat local_script.sh - input |
ssh host 'set some arguments; eval "$(sed -u "/^#END-OF-SCRIPT/q")"'
(ここでコードはリモートユーザーのログインシェルによって評価され、Bourneに似ていると仮定されます。)