我们有一个自动化工具,它会尝试通过 ssh 登录并发送命令,这在服务器运行时可以正常工作。另一方面,在服务器启动时,我们的工具会检查 ssh 端口 (22) 是否打开,如果打开,它会尝试连接到服务器并发送命令。
但是,当服务器处于启动序列并且我们的自动化工具检查端口 22 是否打开时,它会尝试使用 ssh 客户端连接到服务器,但服务器拒绝或 ssh 客户端返回错误“ssh 端口未打开”。
我们尝试使用 telnet 调查此问题,发现在启动过程中,sshd 启动并打开端口 22 并开始监听,但它不知何故再次关闭端口并在一段时间后再次打开。而这正是我们的自动化工具尝试登录的时间。
我的问题是;我们如何确保 ssh 端口成功打开并准备好接受命令?
感谢您抽出时间回答,谨致问候
答案1
首先,自动化工具似乎没有验证 ssh 的退出状态。我会尝试修复那里的问题。
一个解决方案是尝试为创建该工具的团队填补一个错误。
另一个解决方案是将 ssh 命令包装在一个可以透明执行此操作的脚本中。例如,在 /opt/myproject/ssh_wraper.sh 中创建一个脚本
在这里你可以得到类似的东西:
SSH_EXIT_STATUS=255
while [[ $SSH_EXIT_STATUS -eq 255 ]];do
ssh ....
SSH_EXIT_STATUS=$?
done
答案2
您可以尝试尝试从类似的东西中获得的退出状态ssh user@host "echo 0 > /dev/zero"
如果命令成功完成,您将得到0
(表示系统已准备就绪)。失败的尝试将导致退出代码为255
。
您可能也想考虑使用-o ConnectTimeout=
和-o ConnectionAttempts=
。
不过,我也同意史蒂夫的观点。也许再等一会儿就好了。根据您的工具探测端口的积极程度,在尝试登录之前增加延迟时间。
答案3
您可以在登录前放置一个循环来等待端口打开。
until nc -zvw 1 $host 22; do
sleep 2
done
ssh $host $cmd
如果您不想冒着条件永远不成立而陷入无限循环的风险,您可以以某种方式设置“或”值。练习留给读者。:)
答案4
您可以尝试将一个脚本添加到服务器的启动顺序中(例如在 /etc/rc.local 中),该脚本将关闭端口 22 上的防火墙。此脚本(如 /etc/rc.local 的注释中所述)将在所有其他 init 脚本之后执行。因此,只要您的服务器尚未完成其启动顺序,防火墙后面的端口 22 仍然无法访问。它的优点是保持自动化工具不变。
基于 RHEL6 操作系统。您的发行版上的初始化脚本可能有所不同。