![启动多个“ssh”会话,每个会话转发到不同的端口](https://linux22.com/image/212448/%E5%90%AF%E5%8A%A8%E5%A4%9A%E4%B8%AA%E2%80%9Cssh%E2%80%9D%E4%BC%9A%E8%AF%9D%EF%BC%8C%E6%AF%8F%E4%B8%AA%E4%BC%9A%E8%AF%9D%E8%BD%AC%E5%8F%91%E5%88%B0%E4%B8%8D%E5%90%8C%E7%9A%84%E7%AB%AF%E5%8F%A3.png)
我有一个别名,可以启动ssh
带有端口转发的自定义命令,如下所示:
ssh -Y -L 8888:localhost:8888 hostname
当然,这对于我为同一主机启动的第一个会话来说效果很好,但在随后的时间中,转发将失败,因为端口 8888 已在使用中。
我想要做的是想出一种方法,每次启动ssh
到同一服务器的连接时,端口都会自动调整,以便每个不同的ssh
连接都有自己单独的端口可以转发。
因此,例如,我第一次发出命令时,它相当于
ssh -Y -L 8888:localhost:8888 hostname
第二次它相当于
ssh -Y -L 8889:localhost:8889 hostname
等等。
我知道我可以使用 Python 或其他东西来做到这一点,但我想知道是否有比编写自己的(可能有点复杂)脚本更简单的解决方案。那可能吗?
PS:我知道我可以轻松地手动完成此操作,但我每天都会启动其中几个,这不仅需要我输入更多内容,而且还需要跟踪哪些端口已在使用以及哪些端口已在使用中不是。
答案1
这是一个简短的脚本,可以完成您所描述的事情。它的工作原理是尝试锁定以端口号命名的文件,如果失败,则增加端口号并重试。
端口锁定文件是在$HOME/.ssh/ports
.它们在创建后不会被清理,但这没关系;我们不会检查是否存在;我们正在获取文件锁。
该脚本并不关心您每次连接到同一服务器还是不同的服务器;每个连接都会获得一个唯一的端口。
#!/bin/bash
PORTPATH="$HOME/.ssh/ports"
port=8888
while :; do
# We use the -E option to specify a custom exit code so that we can
# differentiate between "failed to lock file" and "ssh failed for some
# reason".
flock -n -E 121 "$PORTPATH/$port" \
ssh -Y -L "${port}:localhost:${port}" "$@" && break
exitcode=$?
if (( exitcode == 121 )); then
(( port++ ))
continue
fi
exit $exitcode
done
如果我将此脚本保存在名为的文件中portfw.sh
并运行它三次,如下所示:
sh portfw.sh remote.example.com
我将在输出中看到以下进程ps
:
flock -n -E 121 /home/lars/.ssh/ports/8888 ssh -Y -L 8888:localhost:8888 remote.example.com
flock -n -E 121 /home/lars/.ssh/ports/8889 ssh -Y -L 8889:localhost:8889 remote.example.com
flock -n -E 121 /home/lars/.ssh/ports/8890 ssh -Y -L 8890:localhost:8890 remote.example.com