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

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

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

ssh <remote_server> "bash -s" < ./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などは各行の最初の単語です。ローカルファイル.txt:

FOO     FOO_PARAM1
BAR     BAR_PARAM1
BAZ     BAZ_PARAM2
...

"bash -s"つまり、リモートサーバーが解釈しているようですローカルファイル.txt入力ファイルの代わりにスクリプトファイルとしてローカルスクリプトこれを修正する方法はありますか (ラッパー スクリプトを作成する以外)?

答え1

sshは 2 つの別々の出力ストリーム (stdout と stderr) を提供しますが、入力ストリーム (stdin) は 1 つしか提供しません。そのため、スクリプトの内容と入力ファイルを異なるメカニズムで渡す必要があります。

たとえば、1 つは変数経由、もう 1 つは stdin 経由です。

LC_CODE=$(cat local_script.sh) ssh host 'eval "$LC_CODE"' < input

(クライアントが変数をssh渡しLC_*( )、サーバーがそれを受け入れる ( )と仮定)SendEnvssh_configsshdAcceptEnvsshd_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'

ここで、bashbecauseを使用すると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")"'

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

答え2

ここでは、BASH の「here-strings」演算子 ('<<<') を使用したよりエレガントな解決策を示します。

ssh -t host "/bin/bash <(base64 --decode <<<'$(base64 < script)' )"

IT はスクリプトを取得し、それを base64 文字列に変換し、SSH コマンドでそれを元に戻して、パイプ ファイル名として bash に渡します。

対話型シェルを起動するスクリプトの場合は、「パイプファイル名」の前に「--rcfile」を付けます。

ssh -t host "/bin/bash --rcfile <(base64 --decode <<<'$(base64 < script)' )"

さらに詳しく... https://antofthy.gitlab.io/info/apps/ssh_remote_commands.txt

答え3

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

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

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

関連情報