5

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

为了让这更容易解释,请考虑一个名为“remoteserver”的主机的本地 SSH 配置,其中包含一个没有密码的本地私钥,所以

ssh remoteserver -L 4444:targetserver:5555

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

因为应该可以保持其他并行的持续 SSH 连接,所以我不想要类似sudo killall ssh.

4

2 回答 2

5

你可以尝试类似的东西

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

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

或者,

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

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

于 2013-10-19T18:43:03.453 回答
1

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

@damienfrancois 的第二个建议是足够的,但由于某种原因,我不喜欢必须kill 做某事的想法。

另外,我不敢相信ssh没有内置机制。确实如此。事情应该是这样的:

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

但是由于某种原因,这对我来说并没有像预期的那样工作:我首先尝试了一些简单的东西,比如wforLocalCommand 但是-N让命令挂起,所以我sleep 0改用它,这似乎有效。

但是当我插入我的实际网络命令时,结果运行得非常慢。不是在不到一秒的时间内完成,而是在开始消息出现之前花了 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上下文中使用它,并且喜欢它适合单行的事实。

于 2016-09-04T13:04:17.133 回答