通过标准输入(通过 ssh)传递多个文件

Gre*_*Guy 15 ssh io-redirection

我在远程主机上有一个程序,我需要自动执行该程序。在同一台机器上执行该程序的命令如下所示:

/path/to/program -a file1.txt -b file2.txt
Run Code Online (Sandbox Code Playgroud)

在这种情况下,file1.txtfile2.txt用于程序中完全不同的东西,所以我不能把cat它们放在一起。然而,在我的情况下,file1.txtfile2.txt我想要传递到程序中只有我的设备上存在的,不是我需要执行该程序的主机上。我知道我可以通过以下方式通过 SSH 提供至少一个文件stdin

cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt
Run Code Online (Sandbox Code Playgroud)

但是,由于我不允许在主机上存储文件,因此我也需要一种方法来将文件放在file2.txt那里。我认为通过滥用环境变量和创造性地使用catsed一起使用可能是可能的,但我不太了解这些工具,无法理解我将如何使用它们来实现这一目标。是否可行,以及如何做?

mos*_*svy 19

如果作为参数提供给您的程序的文件是文本文件,并且您能够控制它们的内容(您知道其中没有出现一行),您可以使用多个 here-documents:

{
    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
Run Code Online (Sandbox Code Playgroud)

cat是一个将文件名作为参数的示例命令。可以改为:

echo "/path/to/prog -a /dev/fd/3 3<<'EOT' -b /dev/fd/4 4<<'EOT'
Run Code Online (Sandbox Code Playgroud)

分别EOT用每个文件中没有出现的内容替换每个文件。

  • 请注意,几个(大多数)sh 实现在这里使用临时文件实现文档,因此如果不允许它们在远程主机上存储文件,则它可能不适用于 OP。 (3认同)
  • `dash`(debian、ubuntu 等中的 `/bin/sh`)、`busybox sh`、来自 FreeBSD 的 `/bin/sh` 和 `yash` 不使用临时文件作为 here-documents。我实际上已经用只读 chroot 对其进行了测试。当然,`/dev/fd/` 文件必须是可用的——在库存的 FreeBSD 系统上只有 `/dev/fd/0-2` 是可用的,所以 `fdescfs` 必须被挂载到 `/dev/fd `. (2认同)

fil*_*den 14

也许不完全是你想要的......但也许可以考虑通过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
  '
Run Code Online (Sandbox Code Playgroud)

这可能需要额外注意文件路径,并且需要考虑一些极端情况(测试它们),但一般方法应该有效。

如果没有可用的可写目录,一种可能的方法是修改program以将 tarball 作为单个输入并将其内容解压缩到内存中。例如,如果program是 Python 脚本,那么使用内置tarfile模块可以轻松完成类似的操作。

  • 即使没有经历压缩它的麻烦 - 我或多或少地决定只将文件写入`/tmp/`并直接使用它。 (3认同)
  • @GreenCloakGuy 毕竟,您*可以*在服务器上存储文件就好了。请相应地修改问题。 (3认同)
  • tarball 方法有一些优点,因为您使用单个 ssh 连接(无需测试成功/失败)并且多个并发运行不太可能相互运行(使用和/或删除 /tmp 中用于单独运行的文件) .) 但我认为这是您从 ssh 获得的最好的结果,因为它现在存在。祝你好运! (2认同)

小智 5

如果您可以设置 TCP 侦听器(可以是更高的端口),那么您可以使用第二个 SSH 会话通过nc.

例子:

服务器 ( ~/script.bash)上有这个脚本:

#!/usr/bin/env bash
cat "$1" | tr a 1
nc localhost "$2" | tr '[:lower:]' '[:upper:]'
Run Code Online (Sandbox Code Playgroud)

并且本地有这两个文件:

$ cat a 
aaa
aaa
aaa
$ cat b
bbb
bbb
bbb
Run Code Online (Sandbox Code Playgroud)

现在首先启动第二个源($serv是服务器):

ssh "$serv" nc -l -p 2222 -q1 <b &
Run Code Online (Sandbox Code Playgroud)

并正确运行命令:

$ ssh "$serv" ./script.bash - 2222 <a
111
111
111
BBB
BBB
BBB
[1]+  Done                    ssh "$serv" nc -l -p 2222 -q1 < b
Run Code Online (Sandbox Code Playgroud)