【发布时间】:2012-07-18 14:29:26
【问题描述】:
我希望使用 SSH 建立一个临时端口转发,运行本地命令然后退出,关闭 ssh 连接。
该命令必须在本地运行,而不是在远程站点上。
例如,考虑 DMZ 中的服务器,您需要允许计算机中的应用程序连接到端口 8080,但您只有 SSH 访问权限。
如何做到这一点?
【问题讨论】:
标签: ssh portforwarding
我希望使用 SSH 建立一个临时端口转发,运行本地命令然后退出,关闭 ssh 连接。
该命令必须在本地运行,而不是在远程站点上。
例如,考虑 DMZ 中的服务器,您需要允许计算机中的应用程序连接到端口 8080,但您只有 SSH 访问权限。
如何做到这一点?
【问题讨论】:
标签: ssh portforwarding
假设您从命令行使用 OpenSSH....
SSH 可以打开一个连接来维持隧道并尽可能长时间地保持活动状态:
ssh -fNT -Llocalport:remotehost:remoteport targetserver
您也可以让 SSH 在服务器上启动一些运行一段时间的东西。隧道将在那个时候开放。只要隧道仍在使用中,远程命令退出后 SSH 连接就应该保持。如果您只使用隧道一次,请指定一个短暂的“睡眠”,让隧道在使用后过期。
ssh -f -Llocalport:remotehost:remoteport targetserver sleep 10
如果您希望能够杀死在本地运行的脚本中的隧道,那么我建议您在 shell 中将其作为背景,然后记录 pid 以便稍后杀死。假设您使用的是包含 Bourne shell 的操作系统......
#/bin/sh
ssh -f -Llocalport:remotehost:remoteport targetserver sleep 300 &
sshpid=$!
# Do your stuff within 300 seconds
kill $sshpid
如果您不喜欢使用 shell 将 ssh 设置为后台,您还可以使用高级 ssh 功能来控制后台进程。作为described here,SSH 功能ControlMaster 和ControlPath 是您完成这项工作的方式。例如,将以下内容添加到您的~/.ssh/config:
host targetserver
ControlMaster auto
ControlPath ~/.ssh/cm_sockets/%r@%h:%p
现在,您与targetserver 的首次连接将设置一个控件,以便您可以执行以下操作:
$ ssh -fNT -Llocalport:remoteserver:remoteport targetserver
$ ssh -O check targetserver
Master running (pid=23450)
$ <do your stuff>
$ ssh -O exit targetserver
Exit request sent.
$ ssh -O check targetserver
Control socket connect(/home/sorin/.ssh/cm_socket/sorin@192.0.2.3:22): No such file or directory
显然,这些命令也可以封装到您的 shell 脚本中。
【讨论】:
您可以使用与此类似的脚本(未经测试):
#!/bin/bash
coproc ssh -L 8080:localhost:8080 user@server
./run-local-command
echo exit >&${COPROC[1]}
wait
【讨论】:
coproc 是内置的 bash。不知道它最初出现在哪个版本的 bash 中,抱歉。