我有一个包含 17 台服务器的列表,格式如下:
172.16.6.45 i-052463fs (test-mv1)
172.16.6.46 i-9e2263rf (test-mv2)
我想要一个脚本,可以通过 ssh/login 访问每个服务器并将它们关闭,这很容易,但问题是它们需要按照上面显示的特定顺序(列表下方)关闭,其中每个前一个服务器都必须在下一次关闭开始之前完全关闭。
也许有一种方法可以在命令后面放置一个循环,每 n 秒 ping 一次,如果在 k 秒内没有收到回复则中断?
答案1
你可以这样做:
while IFS=' (' read <&3 ip id name rest; do
ssh -n -o ConnectTimeout=3 -o BatchMode=yes -o HostKeyAlias="$name" "$ip" poweroff &&
while ping -qw 10 -c3 "$ip"; do
sleep 1
done
done 3< list.txt
关于该代码的一些注释:
- 我们使用姓名作为 HostKeyAlias 的一部分,也许
$id
更有意义。理想情况下,您需要将某些内容附加到 sshd 服务器主机密钥。 - 我们使用
-n
forssh
和 BatchMode,因为我们在这里正在执行无人值守脚本。您可能还想UserKnownHostsFile
为此目的指定一个专用项。 while
如果ssh
不成功,我们就不会运行循环。在这种情况下,您可能还想退出脚本并出现错误。您可能还需要为 while 循环的迭代添加上限,以解决服务器无法关闭的情况。- 我们的循环执行 3 次 ping 探测,间隔 1 秒,并在 10 秒后放弃。
ping
(如果至少有一个探测得到应答,则至少iputils
Debian 上的探测将返回 true,这应该涵盖真正的数据包丢失。三个探测中的两个之间的一秒延迟可以避免像while ping -c1
循环那样淹没服务器。额外的发送 3 个探测但未得到答复后的延迟有望为服务器在拆除其 IP 堆栈后提供足够的时间关闭。
答案2
ssh host sudo shutdown -h -y now ; ping -c 1 host ; while [ $? = 0 ] ; do ping -c 1 host ; done