尝试编写一个shell脚本来不断远程测试服务器,但当我注销时它总是陷入else语句

尝试编写一个shell脚本来不断远程测试服务器,但当我注销时它总是陷入else语句

尝试在这里编写一个 shell 脚本来不断测试我的服务器并在服务器出现故障时给我发送电子邮件。

问题是,当我从 ssh 连接注销时,尽管在&命令末尾运行它,例如./stest01.sh &,它会自动落入 else 并不间断地向我发送邮件,直到我再次登录并终止它。

#!/bin/bash
while true; do
    date > sdown.txt ;
    cp /dev/null pingop.txt ;
    ping -i 1 -c 1 -W 1 myserver.net > pingop.txt &
    sleep 1 ;
    if
        grep "64 bytes" pingop.txt ;
    then
        :
    else
        mutt -s "Server Down!" [email protected] < sdown.txt ;
        sleep 10 ;
    fi
done

答案1

当 GNUgrep尝试写入其结果时,它将失败并返回非零退出状态,因为 SSH 连接已断开,它无处可写输出。

这意味着该if语句总是走else分支。

为了说明这一点(这不是确切地您遇到的情况是这样的,但它显示了如果 GNUgrep无法写入其输出会发生什么情况):

$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2

这里我们grep为生成的字符串echo,但我们关闭两个输出流,以便grep它无法写入任何地方。正如你所看到的,GNU 的退出状态grep是 2 而不是 0。

这是 GNU 所特有的grepgrep在 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!" [email protected] <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!" [email protected]
        break
    fi

    sleep 10
done

在上述脚本的两个变体中,我选择在无法到达主机时退出循环,只是为了最大限度地减少发送的电子邮件数量。如果您希望服务器最终再次启动,您可以将其替换break为例如或其他内容。sleep 10m

ping我还稍微调整了与as一起使用的选项,因为-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!" [email protected]

作为每分钟运行的 cron 作业(如果服务器继续关闭,将继续每分钟发送电子邮件):

* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" [email protected] )

相关内容