Отправка почты при изменении строки в лог-файле, хвост -f конвейер на почту не работает

На всякий случай, если кому-то это будет полезно, вот вам однострочник для обнаружения переменных PHP с помощью Snake Case в коде (предполагает GNUgrep):

grep -r --include='*.php' -E '\$[a-zA-Z]+_[a-zA-Z]'.
1
28.11.2019, 23:12
3 ответа

Проблема в том, что tail -f никогда не завершается, --он просто ожидает ввода навсегда. Таким образом, канал остается открытым, почта никогда не получает EOF и просто ждет, пока сообщение «завершится», чего никогда не может.

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

Если вы уверены, что хотите, чтобы каждая строка, добавленная в журнал, находилась в отдельном письме, вы можете использовать:

tail -f access.log | head -n 1 | mail -s "Dateizugriff" <user@domain>

Head выйдет, как только прочитает одну строку, tail получит SIGPIPE и выйдет, mail получит EOF и продолжит отправку почты.

Если запись журнала может быть многострочной, но вы всегда можете распознать последнюю строку, вы можете использовать sed с условием q, чтобы разорвать канал.

Первый недостаток заключается в том, что почтовый процесс постоянно зависает, пока не придет следующая строка.

Вторым недостатком является то, что вам придется признать, что процесс завершился каждый раз, и перезапускать все это.

Лично я бы написал цикл оболочки, который неоднократно пытался найти любые добавленные строки, внутри цикла, который включает сон (может быть, 60 секунд ). Когда размер файла увеличивается, он может работать tail без -f, поэтому он не зависает.

Инициализировать nLine перед циклом до текущего количества строк. Перенаправление важно, потому что оно перестает сообщать имя файла со счетчиком.

nLine="$( wc -l < access.log )"

while : ; do
    NEW=$( tail -n +$(( 1 + nLine )) access.log )
    [[ "${#NEW}" -gt 0 ]] && {
        echo "${NEW}" | mail....
        nLine=$(( nLine + $( wc -l <<<${NEW} ) ))
    }
    sleep 60
done
2
27.01.2020, 23:57

Поскольку вы, вероятно, хотите, чтобы этот процесс «мониторинга» запускался автоматически при каждой перезагрузке системы,Я думаю, что путьsystemdявляется разумным способом выполнить это.

Это означает, что вы должны написать файл monitor_nginx_access.pathс содержимым вида

[Unit]
Description=Alert admin about access

[Path]
PathChanged=/absolute/path/to/access.log

и служба с тем же именем, monitor_nginx_access.service, которая содержит, по сути, обертку для сценария оболочки -, который выполняет магию:

[Unit]
Description=Send mail when access log changes

[Service]
ExecStart=/absolute/path/to/mailscript.sh

Оба эти файла должны быть помещены в /etc/systemd/system или туда, где ваша установка предполагает, что администратор -определил systemdмодули (cf. справочная страница ).

Тогда mailscript.shбудет содержать что-то вроде

#!/bin/bash
MAILLINES=5  # how many of the last lines of access.log to mail
...

tail -n "$MAILLINES" /absolute/path/to/access.log | mail -s <your arguments here>
0
27.01.2020, 23:57

Как упоминал Макс Мюллер, вы можете сделать

tail -f access.log | grep --line-buffered GET | 
while read line 
do 
echo $line | mail -s New Access <Destinationaddress>
done

или, если хотите, в одну строку, используйте мое решение

tail -f access.log | awk -W interactive '/GET/{system("echo "$0" | mail -s \"New Access\" <Destinationaddress>")}'
0
27.11.2020, 14:06

Теги

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