通过 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/配置/权限(您尚未提供)可以允许更智能的解决方案。

相关内容