在 shell 脚本中检查单个 SSH 隧道的进程?

在 shell 脚本中检查单个 SSH 隧道的进程?

在远程实验室系统上,我有一个 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

我的想法:

  1. Pid 文件。我认为这是通用的方法。
  2. XY问题, 使用autossh

(其他一些答案可能会详细阐述这些想法。)

  1. 有两个脚本,对吧?(不完全符合干燥)。给它们赋予不同的名称。您的脚本等待其ssh退出。附加实例不应检查 的 pid ssh,而应检查其自身名称的 pid。恰好一个 pid两个 pid 意味着没有先前的脚本仍在运行:

    [ $(pidof -x scriptname | wc -w) -eq 2 ] && createTunnel
    

    为什么是两个?因为$()启动一个子 shell,这个子 shell 也算数。太肮脏了,算了吧。

  2. 我觉得这有点不合常规。创建两个具有唯一名称的符号链接,例如:

    ln -s /usr/bin/ssh ssh-foo
    ln -s /usr/bin/ssh ssh-bar
    

    让第一个脚本运行ssh-foo,让第二个脚本运行ssh-bar。它们的pidof调用也应该分别以ssh-foo或为目标ssh-bar。这样它们就不会混淆。作为奖励,其他脚本ssh(将来可能出于完全不同的原因运行)不会影响它们。

最后:

  1. 您不需要检查任何东西。

    /usr/bin/ssh -o ExitOnForwardFailure=yes -N -R :2222:localhost:22 [email protected]
    

    如果隧道已经存在,端口转发肯定会失败并ssh退出。我猜你可以直接从 crontab 运行此行,不需要脚本。

相关内容