@jakuje给出的答案的问题是:它仅适用于套接字,但是您不能使用期望使用它们的文件的标准UNIX工具:
ssh -R/tmp/sock.remote:/tmp/sock.local "$HOST" 'LANG=C cat >/tmp/sock.remote'
bash:/tmp/sock.remote:没有这样的设备或地址
还有一个问题是本地套接字文件没有在远程主机上被删除。接下来,您运行相同的命令时,会收到警告,并且套接字未正确创建。你可以给的选项-o StreamLocalBindUnlink=yes
,以ssh
取消链接旧插座,但在我的测试中,它是不够的; 您还必须对其进行编辑sshd_config
以使其包含StreamLocalBindUnlink=yes
该选项才能起作用。
但是你可以使用socat
或netcat
或任何其他类似工具,支持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'
您还可以运行交互式命令,在这种情况下,应使用它ssh -t
来分配TTY。
该解决方案的问题在于,您必须对UNIX本地套接字的路径进行硬编码:就本地而言,这不是什么大问题,因为您可以将其包含$$
在路径中,以使其对每个进程或用户成为唯一的临时目录,而在目录上。远程端最好不要/tmp/
像在我的示例中那样使用世界可写目录。ssh
启动会话时,该目录也必须已经存在。并且套接字inode甚至在会话关闭后仍将保留,因此,使用诸如“ $ HOME / .ssh。$$”之类的东西会随着时间的过去使目录中的inode失效。
您还可以使用绑定到的TCP套接字localhost
,这可以避免因索引节点失效而使文件系统混乱,但是即使有了它们,您仍然不得不选择一个(唯一的)未使用的端口号。因此仍然不理想。(ssh
具有用于动态分配端口的代码,但是我找不到在远程主机上检索该信息的方法。)
复制文件最简单的方法可能是使用ssh的内置连接共享功能,并在交互式会话仍在并行运行时执行scp
或sfrp
命令。请参阅使用ssh将文件复制回本地系统。
closefrom(STDERR_FILENO + 1)
到OpenSSH源代码下的各种调用,可能并非没有棘手的源代码编辑。您要做什么才能做到这一点?