複数のファイルを標準入力経由で渡す(SSH経由)

複数のファイルを標準入力経由で渡す(SSH経由)

リモート ホスト上にプログラムがあり、その実行を自動化する必要があります。同じマシン上でそのプログラムを実行するコマンドは次のようになります。

/path/to/program -a file1.txt -b file2.txt

この場合、file1.txtと はfile2.txtプログラム内でまったく異なる目的で使用されているため、catこれらを一緒に使用することはできません。ただし、私の場合、プログラムに渡したいfile1.txtと はfile2.txtデバイス上にのみ存在し、プログラムを実行する必要があるホスト上には存在しません。 を渡すことで、少なくとも 1 つのファイルを SSH 経由で送ることができることはわかっていますstdin

cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt

しかし、ホストにファイルを保存することは許可されていないため、ホストにファイルを保存する方法も必要です。環境変数を悪用し、とを組み合わせfile2.txtて創造的に使用することで可能になるのではないかと考えていますが、ツールを十分に理解していないため、これをどのように使用すれば良いのか理解できません。実行可能でしょうか。また、どのように実行すればよいでしょうか。catsed

答え1

プログラムに引数として渡されるファイルがテキスト ファイルであり、その内容を制御できる場合 (ファイル内に出現しない行がわかっている場合)、複数の here-document を使用できます。

{
    echo "cat /dev/fd/3 3<<'EOT' /dev/fd/4 4<<'EOT' /dev/fd/5 5<<'EOT'"
    cat file1
    echo EOT
    cat file2
    echo EOT
    cat file3
    echo EOT
} | ssh user@host sh

以下はcatファイル名を引数として受け取るサンプルコマンドです。代わりに次のようになります:

echo "/path/to/prog -a /dev/fd/3 3<<'EOT' -b /dev/fd/4 4<<'EOT'

それぞれEOTを、各ファイルに存在しないものに置き換えます。

答え2

おそらく、まさにあなたが望んでいることではないかもしれません...しかし、ssh によって開かれたパイプを介して tarball を送信することを検討してみてはいかがでしょうか?

あなたが言った:

ホストにファイルを保存することは許可されていません。

書き込み可能なホーム ディレクトリや、ファイルを長期的に保存するための他の便利な場所がない可能性もありますが、tmpfs特定の接続でのみ使用できる一時的な場所であっても、書き込み可能な場所がないということはまずないと思います。

多くのプログラム (さらには libc ルーチン) では書き込み可能な が必要な/tmpので、書き込み可能な が利用できる可能性が非常に高くなります。

次に、tarball を一時ディレクトリに解凍し、プログラムを実行して、ssh 接続を介してクリーンアップするスクリプトを使用できます。

何かのようなもの:

$ tar cf - file1.txt file2.txt |
  ssh host.name '
      set -e
      tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX)
      cleanup () { rm -rf "$tmpdir"; }
      trap cleanup EXIT
      cd "$tmpdir"
      tar xf -
      /path/to/program -a file1.txt -b file2.txt
  '

ファイル パスについては特別な注意が必要になる可能性があり、考慮すべき特殊なケース (テスト) がいくつかありますが、一般的なアプローチは機能するはずです。

書き込み可能なディレクトリが利用できない場合は、tarball を単一の入力として受け取り、その内容をメモリに解凍するように変更するという方法がありますprogram。たとえば、がprogramPython スクリプトである場合、組み込みtarfileモジュールを使用すると、そのようなことが簡単に実現できます。

答え3

TCP リスナー (より高いポートでも可) を設定できる場合は、2 番目の SSH セッションを使用して 2 番目の入力ソースを確立できますnc

例:

サーバー上にこのスクリプトがあります ( ~/script.bash)。

#!/usr/bin/env bash
cat "$1" | tr a 1
nc localhost "$2" | tr '[:lower:]' '[:upper:]'

ローカルには次の 2 つのファイルがあります。

$ cat a 
aaa
aaa
aaa
$ cat b
bbb
bbb
bbb

まず、2 番目のソース ($servサーバー) を起動します。

ssh "$serv" nc -l -p 2222 -q1 <b &

そして、適切なコマンドを実行します:

$ ssh "$serv" ./script.bash - 2222 <a
111
111
111
BBB
BBB
BBB
[1]+  Done                    ssh "$serv" nc -l -p 2222 -q1 < b

答え4

経由でポートを転送する権限があり、リモート マシンの とローカル マシンのsshにアクセスできる場合は、次のように実行できます。wgetbusybox

mkdir /tmp/test; cd /tmp/test
echo 1st_file > 1st_file
echo 2nd_file > 2nd_file

busybox httpd -f -p 127.0.0.1:11080 &
ssh USER@HOST -R 10080:127.0.0.1:11080 '
        cat <(wget -q -O- http://localhost:10080/1st_file) \
            <(wget -q -O- http://localhost:10080/2nd_file)
'
kill $!

( cat2 つのファイル引数を取るサンプル プログラムとして使用します)。

経由でポートを転送する機能のみが-R必須です。http を実行する代わりに、他の方法を使用できます。たとえば、 が およびオプションnetcatをサポートしている場合:-d-N

nc -Nl localhost 11001 < 1st_file &
nc -Nl localhost 11002 < 2nd_file &
ssh USER@HOST -R 10001:localhost:11001 -R 10002:localhost:11002 '
        cat <(nc -d localhost 10001) <(nc -d localhost 10002)

<(...)リモート マシンのログイン シェルが ksh や bash に似ていない場合は、プロセス置換を置き換える方法がある可能性があります。

全体的に見て、これはあまり良いことではありません。正確なシステム/シェル/構成/権限 (提供されていない) に関する知識が深まれば、よりスマートなソリューションが可能になります。

関連情報