リモートホストにプログラムがあり、その実行を自動化する必要があります。コマンドはそのプログラムを同じマシンで実行し、次のようになります。
/path/to/program -a file1.txt -b file2.txt
この場合、file1.txt
とfile2.txt
はプログラム内でまったく異なるものに使用されるため、これらを一緒にcat
することはできません。ただし、私の場合、プログラムに渡したいfile1.txt
とfile2.txt
は、プログラムを実行する必要のあるホストではなく、デバイスにのみ存在します。 stdin
を介して渡すことで、SSH経由で少なくとも1つのファイルをフィードできることを知っています。
cat file1.txt | ssh Host.name /path/to/program -a /dev/stdin -b file2.txt
ただし、ホストにファイルを保存することは許可されていないため、file2.txt
をそこに取得する方法も必要です。環境変数の悪用とcat
とsed
のクリエイティブな併用によって可能になると思いますが、それらをどのように使用するかを理解するのに十分なツールを知りませんこれを達成します。それは可能ですか?
プログラムの引数として指定されたファイルがテキストファイルであり、その内容を制御できる場合(その中にはない行がわかっている場合)、複数のヒアドキュメントを使用できます。
{
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
を、それぞれのファイルで発生しないものに置き換えます。
たぶん、あなたが望んでいるものではないかもしれません...しかし、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
'
これにはファイルパスの追加の注意が必要な場合があり、考慮すべきいくつかのケースがあります(それらをテストする)が、一般的なアプローチは機能するはずです。
書き込み可能なディレクトリが利用できない場合、可能な方法はprogram
を変更してtarballを単一の入力として受け取り、その内容をメモリに解凍することです。たとえば、program
がPythonスクリプトである場合、組み込みのtarfile
モジュールを使用すると、そのようなことを簡単に実現できます。
TCPリスナー(より高いポートにすることもできます))を設定できる場合、2番目のSSHセッションを使用して、nc
で2番目の入力ソースを確立できます。
例:
サーバー上にこのスクリプトがあります(~/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
コメント で/tmp
が書き込み可能であることが確立されているため、事前にファイルの1つをコピーするだけです。
scp -p file2.txt Host.name:/tmp/
ssh Host.name "/path/to/program -a /dev/stdin -b /tmp/file2.txt && rm /tmp/file2.txt" < file1.txt
これにより、正常に実行された後、コピーされたファイルもクリーンアップされます(成功に関係なく削除する場合は&&
を;
に変更しますが、終了値が失われることに注意してください)。
それが許容できない場合は、/path/to/program
または次のような単一の入力ストリームから2つのファイルを分離できるラッパーをいじることをお勧めします。
awk 'FNR == 1 && NR > 1 { printf "%c%c%c", 28, 28, 28 } 1' file1.txt file2.txt \
| ssh Host.name /path/to/tweaked_program
これは ASCII情報セパレーター4 (ファイルセパレーター、FS)を使用して3倍にし、バイナリファイルが偶然その文字列を含む可能性を最小限に抑えます。次に、tweaked_program
は、セパレータを指定して入力を分割し、保存された2つのファイルを変数として操作します。
もちろん、tarballを処理するためのライブラリーがある言語を使用している場合、より安全で明確なアプローチは、次のようにtar
をssh
全体でそのようなコードにパイプすることです。
tar -zpc file1.txt file2.txt |ssh Host.name /path/to/tweaked_program
そして、あなたのtweaked_program
は、アーカイブを解凍して開き、各ファイルを異なる変数に保存してから、変数に対して元のprogram
のロジックを実行します。
ssh
を介してポートを転送することが許可されていて、リモートマシンのwget
とローカルマシンのbusybox
にアクセスできる場合は、次のようにします。
_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 $!
_
(2つのファイル引数を取るサンプルプログラムとしてcat
を使用)。
_-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に似ていない場合は、<(...)
プロセスの置換を置き換える方法がある場合があります。
全体として、これはそれほどすばらしいことではありません。正確なsystem/shells/config/permissions(ユーザーが提供していない)についてのより良い知識は、よりスマートなソリューションを可能にする可能性があります。