Как обнаружить непрерывный лог-файл и совпадение шаблона в сценарии оболочки, использующем tail, while, read и? - PullRequest
2 голосов
/ 28 марта 2019

Я наблюдаю за файлом журнала, и если PATTERN не появился в нем в течение THRESHOLD секунд, сценарий должен вывести «error», в противном случае он должен вывести «clear».Скрипт работает нормально, но только если журнал катится.

Я пытался прочитать 'timeout', но не сработал.

log_file=/tmp/app.log
threshold=120

tail -Fn0 ${log_file} | \
while read line ; do
  echo "${line}" | awk '/PATTERN/ { system("touch pattern.tmp") }'

код, чтобы вычислить, как давно шаблонПрикосновениезавис по какой-либо причине, и журнал перестал работать, сценарий не будет выводить какие-либо данные.

Есть ли способ обнаружить отсутствие вывода tail и выполнить какую-либо команду в это время?

Ответы [ 4 ]

0 голосов
/ 28 марта 2019

Это выглядит для меня как сторожевой таймер.Я реализовал нечто подобное, заставив фоновый процесс обновить мой журнал, поэтому мне не нужно беспокоиться о read -t.Вот рабочий пример:

#!/usr/bin/env bash

threshold=10
grain=2

errorstate=0

while sleep "$grain"; do
        date '+[%F %T] watchdog timer' >> log
done &
trap "kill -HUP $!" 0 HUP INT QUIT TRAP ABRT TERM

printf -v lastseen '%(%s)T'
tail -F log | while read line; do
        printf -v now '%(%s)T'
        if (( now - lastseen > threshold )); then
                echo "ERROR"
                errorstate=1
        else
                if (( errorstate )); then
                        echo "Recovered, yay"
                        errorstate=0
                fi
        fi
        if [[ $line =~ .*PATTERN.* ]]; then
                lastseen=$now
        fi
done

Запустите это в одном окне, подождите $threshold секунд, пока оно сработает, затем в другом окне echo PATTERN >> log, чтобы увидеть восстановление.

Пока этоможет быть сделан как угодно детализированным (в примере я установил его на 2 секунды), он загрязняет ваш файл журнала.

О, и обратите внимание, что для формата printf '%(%s)T' требуется bash версии 4 или выше.

0 голосов
/ 28 марта 2019

Похоже, у вас проблема в том, что вычисления времени внутри вашего цикла while никогда не имеют шансов на запуск, когда read блокирует вход.В этом случае вы можете направить вывод tail в цикл while true, внутри которого вы можете сделать if read -t $timeout:

log_file=/tmp/app.log
threshold=120
timeout=10

tail -Fn0 "$log_file" | while true; do
  if read -t $timeout line; then
    echo "${line}" | awk '/PATTERN/ { system("touch pattern.tmp") }'
  fi

  # code to calculate how long ago pattern.tmp touched and same is assigned to diff 

  if [ ${diff} -gt ${threshold} ]; then
    echo "Error"
  else
    echo "Clear"
  fi
done

Как указал Эд Мортон, все имена переменных caps не являютсяхорошая идея в скриптах bash, поэтому я использовал строчные имена переменных.

0 голосов
/ 28 марта 2019

Для дальнейшего развития вашей идеи может быть полезно запустить часть awk в фоновом режиме и выполнить непрерывный цикл для проверки.

#!/usr/bin/env bash

log_file="log.txt"
# threshold in seconds
threshold=10

# run the following process in the background
stdbuf -oL tail -f0n "$log_file" \
   | awk '/PATTERN/{system("touch "pattern.tmp") }' &

while true; do
    match=$(find . -type f  -iname "pattern.tmp" -newermt "-${threshold} seconds")
    if [[ -z "${match}" ]]; then
        echo "Error"
    else
        echo "Clear"
    fi
done
0 голосов
/ 28 марта 2019

Как насчет чего-то простого, например:

sleep "$threshold"
grep -q 'PATTERN' "$log_file" && { echo "Clear"; exit; }
echo "Error"

Если это не все, что вам нужно, отредактируйте свой вопрос, чтобы уточнить ваши требования.Не используйте весь верхний регистр для неэкспортированных имен переменных оболочки, кстати - google it.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...