Во-первых, я хочу извиниться за то, что я абсолютный нуб в программировании, написании скриптов и т. д. Я использую сервер FreeNAS и Raspberry Pi, в который я хотел бы включить sh-скрипт, который должен проверять, подключены ли 8 клиентов (IP-адреса). Если да, они должны остановиться, но если все IP-адреса отключены, он должен выполнить другую задачу/скрипт.
Вот моя проблема: в Интернете (источник: https://www.tech-blogger.net/freenas-automatisch-bei-nicht-benutzung-abschalten/) я нашел скрипт, который проверяет определенные IP-адреса, и если они не в сети, он должен автоматически отключаться. Когда я пингую эти адреса, я получаю 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 $1 in
1) echo „No Shutdown – At least one PC is online“ ;;
2) echo „No PC is online – Shutdown“ ; shutdown -p now ;;
esac
exit $1;
}
#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
Но вы вообще не должны использовать grep
здесь. ping
вернет 0, если получит ответ, иначе не ноль, поэтому вы можете просто выполнить if ( ping -c 1 -t 1 $HOST1 || ping -c 1 -t 1 $HOST2 || ... ) > /dev/null 2>&1 ; then
, чтобы увидеть, отвечает ли какой-либо хост.
Я не уверен на 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 $1 in
1) echo „No Shutdown – At least one PC is online“ ;;
2) echo „No PC is online – Shutdown“ ;; # shutdown -p now ;;
esac
exit $1;
}
#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
Это работает, как и ожидалось (на моей машине). :-)
Да, это работало нормально. Большое спасибо за Вашу помощь :-)
Как сказал Уильям Перселл в комментарии, когда ping
не достигает запрошенного IP-адреса, он возвращает ненулевой код выхода, указывающий на сбой. Оператор if
в оболочках, таких как 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
Я пробовал это, но моя малина говорит мне, что есть синтаксическая ошибка из-за ( во второй строке.
@AlphaInc.: Вам нужно убедиться, что вы используете Bash, а не sh, поскольку первый поддерживает массивы, а второй обычно нет. #!/bin/bash
должна быть первой строкой в вашем скрипте.
if [ $(cmd | grep -c ...) -eq 0 ]
— это антипаттерн. Вместо этого используйтеif ! cmd | grep -q ...