透過 stdin 傳遞多個檔案(透過 ssh)

透過 stdin 傳遞多個檔案(透過 ssh)

我在遠端主機上有一個程序,我需要自動化其執行。在同一台機器上執行該程式的命令如下所示:

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

在這種情況下,file1.txtfile2.txt分別用於程序中完全不同的事物,所以我不能將cat它們放在一起。但是,就我而言,我想要傳遞到程式中的file1.txt和只存在於我的裝置上,而不存在於我需要執行程式的主機上。file2.txt我知道我可以透過 SSH 傳遞至少一個檔案stdin

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

但是,由於我不允許在主機上儲存文件,所以我file2.txt也需要一種方法來到達那裡。我認為透過濫用環境變數和創造性地使用catsed在一起可能是可能的,但我對這些工具還不夠了解,無法理解如何使用它們來實現這一點。可行嗎?

答案1

如果作為程式參數給出的文件是文字文件,並且您能夠控制它們的內容(您知道其中沒有出現的行),則可以使用多個此處文件:

{
    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
  '

這可能需要額外注意檔案路徑,並且需要考慮一些極端情況(對其進行測試),但一般方法應該可行。

如果沒有可用的可寫入目錄,可能的方法是修改program為將 tarball 作為單一輸入並將其內容解壓縮到記憶體中。例如,如果program是Python腳本,那麼使用內建tarfile模組可以輕鬆完成類似的事情。

答案3

如果您可以設定 TCP 監聽器(可以是更高的連接埠),那麼您可以使用第二個 SSH 會話來建立第二個輸入來源nc

例子:

伺服器上有這個腳本(~/script.bash):

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

且本地有這兩個檔案:

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

現在先啟動第二個來源($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,並且您可以訪問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 $!

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)

<(...)如果遠端電腦上的登入 shell 不是類似 ksh 或 bash 的,則可能有一些方法可以替換進程替換。

總而言之,這並不是太好——更好地了解確切的系統/shell/配置/權限(您尚未提供)可以允許更聰明的解決方案。

相關內容