SSH:除了标准输入、标准输出、标准错误之外,还提供额外的“管道”文件

mic*_*c_e 13 ssh pipe file-descriptors

当连接到SSH与一台主机,通常主机和客户之间提供了三个“管道”,为stdinstdoutstderr

是否有命令行选项可以为其他文件描述符(3及以后)创建转发?

例如,我想做

ssh --forwardfd=10:3 remotehost 'echo test >&3'
Run Code Online (Sandbox Code Playgroud)

它将打印“test”到本地打开的文件描述符 10。

Jak*_*uje 7

您可以使用从 openssh-6.7 开始可用的套接字转发来完成此操作。这是某种管道。例如这里描述了这种技术:http : //www.25thandclement.com/~william/projects/streamlocal.html

您将获得数据的双向路由。有mysql的例子:

将远程服务器上的 MySQL 客户端连接代理到本地实例:

ssh -R/var/run/mysql.sock:/var/run/mysql.sock \
    -R127.0.0.1:3306:/var/run/mysql.sock somehost 
Run Code Online (Sandbox Code Playgroud)


pmh*_*ahn 5

@jakuje 的答案的问题是:它仅适用于sockets,但您不能使用标准 UNIX 工具来期望使用它们

ssh -R/tmp/sock.remote:/tmp/sock.local "$HOST" 'LANG=C cat >/tmp/sock.remote'

bash: /tmp/sock.remote: 没有这样的设备或地址

还有一个问题是本地socket文件在远程主机上没有被删除;当您下次运行相同的命令时,您会收到警告,并且套接字未正确重新创建。您可以选择-o StreamLocalBindUnlink=yes取消ssh旧套接字的链接,但在我的测试中这还不够;您还必须编辑您sshd_config以包含StreamLocalBindUnlink=yes该选项才能起作用。

但是您可以使用socatnetcat或任何其他支持UNIX 本地套接字的类似工具(netcat-traditional不够!)来使用本地套接字转发进行文件传输:

# start local process listening on local socket, which receives the data when ssh opens the connections and saves it to a local file
nc -l -N -U /tmp/sock.local >/tmp/file.local &
# connect to remote $HOST and pipe the remote file into the remote socket end
ssh \
 -o ExitOnForwardFailure=yes \
 -o StreamLocalBindUnlink=yes \
 -R /tmp/sock.remote:/tmp/sock.local \
 "$HOST" \
 'nc -N -U /tmp/sock.remote </tmp/file.remote'
Run Code Online (Sandbox Code Playgroud)

您还可以运行交互式命令,在这种情况下,您应该使用它ssh -t来分配 TTY。

此解决方案的问题在于,您必须对 UNIX 本地套接字的路径进行硬编码:在本地,这并不是什么大问题,因为您可以$$在路径中包含临时目录,以使其对每个进程或用户都是唯一的,但是在远程端你最好不要/tmp/像我在示例中那样使用 world-writeable 目录。ssh当会话启动时,该目录也必须已经存在。即使会话关闭后,套接字 inode 仍将保留,因此使用“$HOME/.ssh.$$”之类的内容会随着时间的推移用死 inode 使您的目录变得混乱。

您还可以使用绑定到 的 TCP 套接字localhost,这将使您免于因死 inode 而使文件系统变得混乱,但即使使用它们,您仍然需要选择一个(唯一的)未使用的端口号。所以还是不太理想。(ssh有动态分配端口的代码,但我发现无法在远程主机上检索该信息。)

复制文件的最简单的解决方案可能是使用 ssh 的内置连接共享功能,并在交互式会话仍在并行运行时执行scp或命令。sfrp参阅使用 ssh 将文件复制回本地系统