Сценарий bash регистрирует только изменения хоста вверх или вниз

Вы должны проверить ncdu , который представляет собой команду duс ncurses, которая по умолчанию получает размер файла всех папок.

1
19.12.2019, 18:05
2 ответа

Как и Ромео, я рекомендую использовать cron вместо бесконечного цикла,но чтобы решить вашу проблему с ведением журнала, я придумал:

#!/usr/bin/env bash

hosts=("$@")

log=~/tmp/ping.log

[[ ! -f "$log" ]] && touch "$log"

check_log () {
    local h=$1
    local s
    s=$(awk -v h="$h" '$2 == h {print $1}' "$log" | tail -1)
    printf '%s' "$s"
}

for host in "${hosts[@]}"; do
    ping -qc 5 "$host" >/dev/null 2>&1 &
    pids+=([$!]="$host")
done
for pid in "${!pids[@]}"; do
    host=${pids[$pid]}
    s=$(check_log "$host")
    if wait "$pid"; then
        if [[ "$s" == down || -z "$s" ]]; then
            printf '%s\n' "up $host $(date +%Y%m%d-%H%M)" >> "$log"
        fi
    else
        if [[ "$s" == up || -z "$s" ]]; then
            printf '%s\n' "down $host $(date +%Y%m%d-%H%M)" >> "$log"
        fi
    fi
done

Функция check_logбудет искать в файле журнала записи для данного хоста, в частности, самую последнюю запись для указанного хоста и независимо от того, была ли она включена или отключена.

Сценарий будет циклически проходить через каждый хост и пинговать их с количеством пакетов 5. Он пингует их как фоновый процесс, чтобы попытаться немного ускорить работу. Затем он перебирает идентификаторы PID фоновых команд ping и ожидает их завершения. Если проверка связи прошла успешно, он проверяет журнал, чтобы увидеть, была ли последняя запись для этого хоста ошибкой, если это так, он регистрирует запись up для этого хоста, если нет, он ничего не делает. Если команда ping не удалась, она проверит журнал, чтобы убедиться, что последняя запись для этого хоста была успешной, если это так, она зарегистрирует запись down для этого хоста, если нет, она ничего не сделает.

2
27.01.2020, 23:22

Я бы использовал ассоциативный массив для хранения статуса и регистрации только изменений статуса. Примерно так:

#!/usr/bin/env bash

## This will let us use the host names as keys in the associative array 'status'
declare -A status

while :; do
  for host in "$@"; do
    ## Ping the server and, if the ping is successful, set $isUp to "Up", 
    ## if the ping fails, set $isUp to "Down".
    ping -c 1 -w 2 "$host" &>/dev/null &&
      isUp="Up" || isUp="Down"
    ## If the current value of $isUp isn't the same as what is stored in the
    ## status array for this server, we should report it. 
    if [[ ${status[$host]} != $isUp ]]; then
      spd-say "$host is $isUp"
      notify-send "$host is $isUp"
      printf "%s is %s\n" "$host" "$isUp" >> /tmp/ping.log
      ## save the current status in the array for this server.
      status[$host]=$isUp
    fi
  done
  sleep 2s;
done

Затем вы можете запустить его с именами хостов в качестве аргументов:

checkHost.sh hostname1.foo.com hostanme2.bar.com

Если вы не можете использовать ассоциативные массивы (, если вы используете старую версию bash ), вместо этого вы можете использовать два отдельных массива:

hosts=("$@");
while :; do
  for ((i=0;i<${#hosts[@]}; i++)); do
    host=${hosts[i]};
    ping -c 1 -w 2 "$host" &>/dev/null &&
      isUp="Up" || isUp="Down"
    if [[ ${status[i]} != $isUp ]]; then
      spd-say "$host is $isUp"
      notify-send "$host is $isUp"
      printf "%s is %s\n" "$host" "$isUp" >> /tmp/ping.log
      status[i]=$isUp
    fi
  done
  sleep 2s;
done
1
27.01.2020, 23:22

Теги

Похожие вопросы