Сценарий Bash ведет себя неожиданно/странно

Во-первых, я хочу извиниться за то, что я абсолютный нуб в программировании, написании скриптов и т. д. Я использую сервер 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
if [ $(cmd | grep -c ...) -eq 0 ] — это антипаттерн. Вместо этого используйте if ! cmd | grep -q ...
William Pursell 27.05.2019 19:08

Но вы вообще не должны использовать grep здесь. ping вернет 0, если получит ответ, иначе не ноль, поэтому вы можете просто выполнить if ( ping -c 1 -t 1 $HOST1 || ping -c 1 -t 1 $HOST2 || ... ) > /dev/null 2>&1 ; then, чтобы увидеть, отвечает ли какой-либо хост.

William Pursell 27.05.2019 19:21
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
67
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я не уверен на 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

Это работает, как и ожидалось (на моей машине). :-)

Да, это работало нормально. Большое спасибо за Вашу помощь :-)

AlphaInc. 27.05.2019 19:12

Как сказал Уильям Перселл в комментарии, когда 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. 28.05.2019 20:09

@AlphaInc.: Вам нужно убедиться, что вы используете Bash, а не sh, поскольку первый поддерживает массивы, а второй обычно нет. #!/bin/bash должна быть первой строкой в ​​вашем скрипте.

Dennis Williamson 28.05.2019 21:40

Другие вопросы по теме