在远程实验室系统上,我有一个 shell 脚本,它启动一个到我的主要跳转箱的反向 SSH 隧道,该隧道每 5 分钟通过 cron 作业运行一次。如果 SSH 隧道已启动,则不会发生任何事情,如果已关闭,则会启动它。
#!/bin/bash
createTunnel() {
/usr/bin/ssh -N -R :2222:localhost:22 [email protected]
if [[ $? -eq 0 ]]; then
echo Tunnel to jumpbox created successfully
else
echo An error occurred creating a tunnel to jumpbox. RC was $?
fi
}
/bin/pidof ssh
if [[ $? -ne 0 ]]; then
echo Creating new tunnel connection
createTunnel
fi
如果远程机器重新启动或我的跳转箱 IP 发生变化,这种方法非常可靠,可以确保我能够访问远程机器。但是,我最近向该系统添加了第二个 SSH 隧道,并且出现了两个隧道中的一个关闭并且从未重新建立的情况。看来,由于有一个隧道处于开启状态,因此 pidof 输出仍返回 PID,因此脚本从未运行过“createTunnel”。由于我有两个 SSH 隧道,因此 pidof 输出显示两个 PID:
$ /bin/pidof ssh
28281 28247
我如何调整脚本来确定只有一条隧道发生故障?
答案1
我的想法:
- Pid 文件。我认为这是通用的方法。
- XY问题, 使用
autossh
。
(其他一些答案可能会详细阐述这些想法。)
有两个脚本,对吧?(不完全符合干燥)。给它们赋予不同的名称。您的脚本等待其
ssh
退出。附加实例不应检查 的 pidssh
,而应检查其自身名称的 pid。恰好一个 pid两个 pid 意味着没有先前的脚本仍在运行:[ $(pidof -x scriptname | wc -w) -eq 2 ] && createTunnel
为什么是两个?因为
$()
启动一个子 shell,这个子 shell 也算数。太肮脏了,算了吧。我觉得这有点不合常规。创建两个具有唯一名称的符号链接,例如:
ln -s /usr/bin/ssh ssh-foo ln -s /usr/bin/ssh ssh-bar
让第一个脚本运行
ssh-foo
,让第二个脚本运行ssh-bar
。它们的pidof
调用也应该分别以ssh-foo
或为目标ssh-bar
。这样它们就不会混淆。作为奖励,其他脚本ssh
(将来可能出于完全不同的原因运行)不会影响它们。
最后:
您不需要检查任何东西。
/usr/bin/ssh -o ExitOnForwardFailure=yes -N -R :2222:localhost:22 [email protected]
如果隧道已经存在,端口转发肯定会失败并
ssh
退出。我猜你可以直接从 crontab 运行此行,不需要脚本。