web-dev-qa-db-ja.com

リモートホスト上のローカル入力ファイルを使用してローカルスクリプトを実行する

複数のリモートサーバーで実行するローカルスクリプトがあります。私が使用しているコマンド構文は次のとおりです。

ssh <remote_server> "bash -s" < ./local_script.sh

これは正常に動作し、パラメーターをlocal_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などはlocal_file.txtの各行の最初のWordです。

FOO     FOO_PARAM1
BAR     BAR_PARAM1
BAZ     BAZ_PARAM2
...

したがって、"bash -s"リモートサーバー上のlocal_script.shへの入力ファイルではなく、スクリプトファイルとしてlocal_file.txtを解釈しています。これを修正する方法はありますか(ラッパースクリプトを作成する以外)?

5
Nester

sshは2つの個別の出力ストリーム(stdoutとstderr)を提供しますが、1つの入力ストリーム(stdin)のみを供給します。したがって、さまざまなメカニズムを介してスクリプトのコンテンツと入力ファイルを渡す必要があります。

たとえば、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の標準入力に供給される入力を連結します。

{
  echo '{'; cat local_script.sh; echo '}; exit'
  cat input
} | ssh Host 'bash -s some arguments'

ここではbashを使用しています。これは、bashが一度に1バイトずつ入力を読み取って、それを超えて読み取らないようにするためです}; 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")"'

(ここでは、リモートユーザーのログインシェルによってコードが評価され、ボーンに似ていると想定しています)

5

これはうまく機能し、複数のファイルの内容をスクリプトに渡すこともできます。

ssh Host "bash -s -- '$(cat local_file_1.txt)'  '$(cat local_file_2.txt)'" < local_script.sh

説明は、sshはログイン時にbash -sを実行し、スクリプトの引数は--の後に続くすべてになるということです。したがって、$1local_file_1.txtのコンテンツになり、$2local_file_2.txtのコンテンツになります。 bash -sは、< local_script.shから取得したstdinからコマンドを読み取ります。

1
Jonathan Potter