Спецификация
По крайней мере один хост должен быть всегда доступным для проверки связи (ping success = UP).
Когда проверяемый хост становится недоступным (ошибка проверки связи) => mail и:
- если другой хостpingable уже => нет проблем => продолжить
- иначе => wakeonlan другой хост
Когда недоступный хост становится доступным для pingable назад => mail
Когда хост все еще недоступен после wakeonlan it => mail
Сценарий
Первоначальный сценарий был основан на bash
.Но ваш Ubuntu Server, похоже, использует слишком старую версию bash
без ассоциативного массива .К счастью, zsh
некоторое время поддерживает ассоциативный массив .Поэтому следующий скрипт был переписан для zsh
.Кроме того, была добавлена поддержка MAC-адреса.
Сценарий one_host_should_ping.sh
:
#!/bin/zsh
MYADDRESS=myadress@gmail.com
NEXTHOSTWOL=${1?Please provide hosts as arguments of the script}
PINGABLECOUNT=0
# use associative array to store the state of each host
unset HOSTS
typeset -A HOSTS
unset MAC
typeset -A MAC
while (($#))
do
let PINGABLECOUNT++
HOSTS[$1]=PINGABLE
MAC[$1]=$2
echo >&2 -e "Input #$PINGABLECOUNT:\tIP=$1\tMAC=$2"
shift 2
done
nexthostwol() {
for host in ${(k)HOSTS[@]}
do
if [[ ${HOSTS[$host]} == UNREACHABLE ]]
then
NEXTHOSTWOL=$host
break
fi
done
}
report() {
for host in ${(k)HOSTS[@]}
do
echo "HOST IP=$host MAC=${MAC[$NEXTHOSTWOL]} state=${HOSTS[$host]}"
done
echo "Number of hosts Up = $PINGABLECOUNT"
}
pingable() {
let PINGABLECOUNT++
HOSTS[$1]=PINGABLE
SUBJECT="[Server Up] ping $1 success at $(date +%c)"
echo "$SUBJECT"
report | mail -s "$MESSAGE" "$MYADDRESS"
report
[[ $NEXTHOSTWOL == $1 ]] && nexthostwol
}
unreachable() {
let PINGABLECOUNT--
HOSTS[$1]=UNREACHABLE
SUBJECT="[Server Down] ping $1 failed at $(date +%c)"
if [[ $PINGABLECOUNT -le 0 ]]
then
wakeonlan -i $NEXTHOSTWOL ${MAC[$NEXTHOSTWOL]}
HOSTS[$NEXTHOSTWOL]=WAKEONLAN
SUBJECT="$SUBJECT => wakeonlan $NEXTHOSTWOL"
fi
echo "$SUBJECT"
report | mail -s "$MESSAGE" "$MYADDRESS"
report
}
stillwol() {
SUBJECT="[Server Down] ping $1 failed at $(date +%c)"
echo "$SUBJECT"
report | mail -s "$MESSAGE" "$MYADDRESS"
report
}
# infinite loop => check every 5 minutes
# use CTRL+C or kill to break it
while true
do
for host in ${(k)HOSTS[@]}
do
STATE=${HOSTS[$host]}
case $STATE in
UNREACHABLE) ping -c 1 $host && pingable $host ;;
PINGABLE) ping -c 1 $host || unreachable $host ;;
WAKEONLAN) ping -c 1 $host && pingable $host || stillwol $host ;;
*) echo >&2 "ERROR: $host is in an unexpected state=[$STATE]";;
esac
done
echo "will check again in 5 minutes"
sleep $((5*60))
done
Использование
Предоставление разрешения на выполнение:
chmod +x one_host_should_ping.sh`
Если вы используете два хоста:
./one_host_should_ping.sh IP1 MAC1 IP2 MAC2
Если вы используете пять хостов:
./one_host_should_ping.sh IP1 MAC1 IP2 MAC2 IP3 MAC3 IP4 MAC4 IP5 MAC5
Пример
root@myc:/usr/local# ./one_host_should_ping.sh 192.168.0.197 00:1c:26:5c:7e:d5 192.168.0.187 f4:6d:04:e5:5c:4c
Input #1: IP=192.168.0.197 MAC=00:1c:26:5c:7e:d5
Input #2: IP=192.168.0.187 MAC=f4:6d:04:e5:5c:4c
PING 192.168.0.187 (192.168.0.186) 56(84) bytes of data.
From 192.168.0.168 icmp_seq=1 Destination Host Unreachable
--- 192.168.0.187 ping statistics
--- 1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
[Server Down] ping 192.168.0.187 failed at tor 26 jan 2012 12.44.29
HOST IP=192.168.0.186 MAC=00:1c:26:5c:7e:d5 state=UNREACHABLE
HOST IP=192.168.0.197 MAC=00:1c:26:5c:7e:d5 state=PINGABLE
Number of hosts Up = 1
PING 192.168.0.197 (192.168.0.197) 56(84) bytes of data.
From 192.168.0.168 icmp_seq=1 Destination Host Unreachable
--- 192.168.0.197 ping statistics
--- 1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
Sending magic packet to 192.168.0.197:9 with 00:1c:26:5c:7e:d5
[Server Down] ping 192.168.0.197 failed at tor 26 jan 2012 12.44.36
=> wakeonlan 192.168.0.197
HOST IP=192.168.0.187 MAC=00:1c:26:5c:7e:d5 state=UNREACHABLE
HOST IP=192.168.0.197 MAC=00:1c:26:5c:7e:d5 state=WAKEONLAN
Number of hosts Up = 0
will check again in 5 minutes