用于本地(非远程)命令执行的ssh隧道

时间:2013-10-19 18:26:31

标签: linux bash shell ssh

我想创建一个Linux shell(bash-)脚本,它创建一个SSH隧道,运行一个使用该隧道的本地命令,最后关闭隧道和周围的SSH连接。

为了减少难以解释的问题,可以考虑对名为“remoteserver”的主机进行本地SSH配置,该主机包含没有密码的本地私钥,所以

ssh remoteserver -L 4444:targetserver:5555

将直接打开与远程服务器的连接,并创建从本地端口4444到目标服务器的隧道。并且考虑本地命令是localclient --port 4444,脚本看起来如何打开隧道,执行本地命令并在本地客户端应用程序完成后关闭隧道?

由于应该可以保留其他并行正在进行的SSH连接,我不想要sudo killall ssh之类的内容。

2 个答案:

答案 0 :(得分:5)

您可以尝试类似

的内容
TIMEOUT=60 # seconds
ssh remoteserver -L 4444:targetserver:5555 sleep $TIMEOUT &
localclient --port 4444

隧道将在$ TIMEOUT秒后自动关闭。请注意,使用&仅对无密码连接有效。否则,您需要使用SSH的-f标志。

或者,

ssh -N remoteserver -L 4444:targetserver:5555 &
sshpid=$!
localclient --port 4444
kill $sshpid

将在localclient执行后立即终止隧道。请注意,这不适用于-f标志,因为进程是双重分叉。

答案 1 :(得分:1)

ssh解决方案(对我不起作用)

@damienfrancois的第二个建议是适当的,但是 由于某种原因,我不喜欢必须kill的想法 东西。

另外,我无法相信ssh没有内置机制。 确实如此。这就是工作的方式:

ssh remoteserver -o "PermitLocalCommand yes" -o "LocalCommand localclient --port 4444" \
    -L 4444:targetserver:5555 -N

但由于某种原因,这对我没有预期的效果: 我首先尝试使用w之类的简单内容来LocalCommand 但是-N使命令挂起,所以我使用了sleep 0代替, 这似乎有用。

但是当我插入实际的网络命令时,结果就会运行 非常慢。而不是在不到一秒钟内完成, 甚至在 start 消息出现之前花了40秒。 我在20分钟后终止了命令。

管道解决方案(适用于我)

经过一些实验,这就是我现在使用的:

ssh remoteserver -L 4444:targetserver:5555 keepalive.sh \
  | (sleep 0.5; localclient --port 4444)

远程端的keepalive.sh是这样的:

while true; do
   sleep 1
   echo "keepalive"
done

sleep 0.5需要确定(有点) 隧道是在localclient开始之前设置的 (对于遥远或缓慢的remoteserver,您可能需要更长的等待时间)。 localclient完成后隧道终止 因为shell会尽快终止管道 第二个命令关闭其标准输入。

这比@ damienfrancois的解决方案更好吗?取决于。

keepalive.sh的需求是一个明显的缺点,但是 无论如何清除隧道的方式 localclient终止的方式和原因更清晰。

我需要在Makefile上下文中使用它,就像它适合的事实一样 单行。