Bash 脚本行为异常/奇怪

Bash script behaves unexpected / Strange

首先,我要为自己在编程、编写脚本等方面的绝对菜鸟道歉。 我是 运行 一个 FreeNAS 服务器和一个 Raspberry Pi,我想包含一个 sh-Script,它应该检查 8 个客户端(IP 地址)是否在线。如果是,他们应该停止,但如果所有 IP 都离线,它应该执行另一个任务/脚本。

这是我的问题:在 Internet (src: https://www.tech-blogger.net/freenas-automatisch-bei-nicht-benutzung-abschalten/) 上,我找到了一个检查特定 IP 的脚本,如果它们处于离线状态,它应该会自动关闭。当我 ping 这些地址时,我得到 100% 的包丢失,这表明它们处于离线状态。但脚本让我觉得至少有一个客户端离线。因为我不是那么笨,所以我认为它与我的代码有关。有谁知道我的脚本出了什么问题吗?:

HOST1=192.168.1.32
HOST2=192.168.1.33
HOST3=192.168.1.34
HOST4=192.168.1.35
HOST5=192.168.1.36

_exit () {
case  in
1) echo „No Shutdown – At least one PC is online“ ;;
2) echo „No PC is online – Shutdown“ ; shutdown -p now ;;
esac
exit ;
}

#Check if IPs are online
if [ `ping -c 1 -i 1 $HOST1 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST2 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST3 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST4 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST5 | grep -wc 100.0%` -eq 0 ] ; then _exit 1;

#All Clients are offline, shutdown
else
_exit 2
fi
fi

我不是 100% 确定我是否解决了您的问题。但我认为你应该尝试替换 ||在您的 if 语句中使用 &&。

|| = 或 && = 和

因此它只会在所有客户端关闭时进入关闭部分。

编辑:

ping -c 1 -i 1 192.168.1.36
PING 192.168.1.36 (192.168.1.36) 56(84) bytes of data.
From 62.155.241.85 icmp_seq=1 Destination Host Unreachable

--- 192.168.1.36 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

是 100% 丢包不是 100.0%。因此,您检查没有发生的事情。

#!/bin/bash

HOST1=192.168.1.32
HOST2=192.168.1.33
HOST3=192.168.1.34
HOST4=192.168.1.35
HOST5=192.168.1.36

_exit () {
case  in
1) echo „No Shutdown – At least one PC is online“ ;;
2) echo „No PC is online – Shutdown“ ;; # shutdown -p now ;;
esac
exit ;
}

#Check if IPs are online
if [ `ping -c 1 -i 1 $HOST1 | grep -wc 100%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST2 | grep -wc 100%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST3 | grep -wc 100%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST4 | grep -wc 100%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST5 | grep -wc 100%` -eq 0 ] ; then _exit 1;

#All Clients are offline, shutdown
else                                                                                                                                                                                           
_exit 2
fi

这按预期工作(在我的机器上)。 :-)

正如 William Pursell 在评论中所说,当 ping 没有到达请求的 IP 时,它 returns 一个 non-zero 退出代码指示失败。 if shell 中的 Bash 语句可以直接使用该退出代码,而无需使用括号中的条件表达式。

我建议使用循环而不是长条件语句。如果主机数量发生变化,这将更易于阅读和维护,并且更容易扩展。

# create an array of IPs
host_ips=(
    192.168.1.32
    192.168.1.33
    192.168.1.34
    192.168.1.35
    192.168.1.36
)

for ip in "${host_ips[@]}"
do
    if ping -c 1 -i 1 "$ip"
    then
        _exit 1
        # no need to break since _exit doesn't return
    fi
done
# if we made it this far, none are online
_exit 2