我想创建一个Linux shell(bash-)脚本,它创建一个SSH隧道,运行一个使用该隧道的本地命令,最后关闭隧道和周围的SSH连接。
为了减少难以解释的问题,可以考虑对名为“remoteserver”的主机进行本地SSH配置,该主机包含没有密码的本地私钥,所以
ssh remoteserver -L 4444:targetserver:5555
将直接打开与远程服务器的连接,并创建从本地端口4444到目标服务器的隧道。并且考虑本地命令是localclient --port 4444
,脚本看起来如何打开隧道,执行本地命令并在本地客户端应用程序完成后关闭隧道?
由于应该可以保留其他并行正在进行的SSH连接,我不想要sudo killall ssh
之类的内容。
答案 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
上下文中使用它,就像它适合的事实一样
单行。