当GNU grep
尝试写入其结果时,它将以非零退出状态失败,因为它无处可写输出,因为SSH连接已消失。
这意味着该if
语句始终在else
分支中。
为了说明这一点(这不正是发生的事情在你的情况,但它表明,如果GNU会发生什么grep
无法写入它的输出):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
在这里,我们grep
要echo
生成的字符串,但是我们关闭了两个输出流,grep
以使其无法在任何地方写入。如您所见,GNU的退出状态grep
是2而不是0。
这是GNU特有的grep
,grep
在BSD系统上的行为将有所不同:
$ echo 'hello' | grep hello >&- 2>&- # using BSD grep here
$ echo $?
0
要解决此问题,请确保脚本不会生成输出。您可以使用exec >/dev/null 2>&1
。另外,我们应该使用grep
它的-q
选项,因为我们根本不希望看到它的输出(这通常也会加快速度,grep
因为它不需要解析整个文件,但是在这种情况下,它的作用很小由于文件太小而导致速度差异)。
简而言之:
#!/bin/sh
# redirect all output not redirected elsewhere to /dev/null by default:
exec >/dev/null 2>&1
while true; do
date >sdown.txt
ping -c 1 -W 1 myserver.net >pingop.txt
if ! grep -q "64 bytes" pingop.txt; then
mutt -s "Server Down!" myemail@address.com <sdown.txt
break
fi
sleep 10
done
您也可以ping
直接使用测试,从而消除对中间文件之一的需要(并且摆脱实际上只包含日期戳的其他中间文件):
#!/bin/sh
exec >/dev/null 2>&1
while true; do
if ! ping -q -c 1 -W 1 myserver.net; then
date | mutt -s "Server Down!" myemail@address.com
break
fi
sleep 10
done
在上述脚本的两种变体中,我都选择在无法到达主机时退出循环,以尽量减少发送的电子邮件数量。如果希望服务器最终重新启动,则可以break
用例如sleep 10m
或代替。
我还略微调整了与一起使用的选项,ping
因为与-i 1
并没有多大意义-c 1
。
更短(除非您希望主机无法访问时继续发送电子邮件):
#!/bin/sh
exec >/dev/null 2>&1
while ping -q -c 1 -W 1 myserver.net; do
sleep 10
done
date | mutt -s "Server Down!" myemail@address.com
作为每分钟运行一次的cron作业(如果服务器继续关闭,将每分钟继续发送电子邮件):
* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )
:
做什么?对我来说,这是一个分号;
……