Скрипт парсинга syslog (разбор логов с помощью RegExp)

На самом деле это единственный раздел про unix на этом форуме

Модератор: /dev/random

anykey96
Сообщения: 4
ОС: CentOS

Скрипт парсинга syslog

Сообщение anykey96 » 10.01.2019 12:46

Добрый день.
Я новичок, пробую освоить Linux (экспериментирую с CetnOS). Возникла необходимость распарсить лог (на примере syslog'a) с помощью регулярок RegExp. Т.е. сделать некий Bash-скрипт. Помогите пожалуйста, если кому не сложно.

Имеется лог к примеру такого вида:
Spoiler
Jan 10 08:01:01 localhost systemd: Created slice User Slice of root.
Jan 10 08:01:01 localhost systemd: Starting User Slice of root.
Jan 10 08:01:01 localhost systemd: Started Session 312 of user root.
Jan 10 08:01:01 localhost systemd: Starting Session 312 of user root.
Jan 10 08:01:01 localhost systemd: Removed slice User Slice of root.
Jan 10 08:01:01 localhost systemd: Stopping User Slice of root.
Jan 10 09:01:01 localhost systemd: Created slice User Slice of root.
Jan 10 09:01:01 localhost systemd: Starting User Slice of root.
Jan 10 09:01:01 localhost systemd: Started Session 313 of user root.
Jan 10 09:01:01 localhost systemd: Starting Session 313 of user root.
Jan 10 09:01:01 localhost systemd: Removed slice User Slice of root.
Jan 10 09:01:01 localhost systemd: Stopping User Slice of root.
Jan 10 09:19:49 localhost systemd: Created slice User Slice of testuser.
Jan 10 09:19:49 localhost systemd: Starting User Slice of testuser.
Jan 10 09:19:49 localhost systemd: Started Session 314 of user testuser.
Jan 10 09:19:49 localhost systemd-logind: New session 314 of user testuser.
Jan 10 09:19:49 localhost systemd: Starting Session 314 of user testuser.

Нужно вывести на экран следующие данные из лог-файла:
Значение date (в качестве этого параметра даты, типо Jan 10 09:19:49)
Значение hostname (в качестве этого параметра localhost из лог файла)
Имя процесса\службы (в качестве примера systemd из лог файла)
Далее в строке лога идёт сообщение, необходимо с помощью "регулярок" вывести на экран только строки содержащие к примеру testuser (далее в других логах это может быть заменено на парсинг по наличию в строке значения error, Error)

P.S. опционально - выбрать из всего найденного в логе только данные за последние 20 минут (значение date)

Результат должен быть примерно таким:
Jan 10 09:19:49 localhost systemd: Created slice User Slice of testuser.
Jan 10 09:19:49 localhost systemd: Starting User Slice of testuser.
Jan 10 09:19:49 localhost systemd: Started Session 314 of user testuser.
Jan 10 09:19:49 localhost systemd-logind: New session 314 of user testuser.
Jan 10 09:19:49 localhost systemd: Starting Session 314 of user testuser.
Спасибо сказали:

Аватара пользователя
Vascom
Сообщения: 1460
ОС: Fedora 30

Re: Скрипт парсинга syslog

Сообщение Vascom » 10.01.2019 12:48

Показывай что уже сделал и что конкретно не получается.
Спасибо сказали:

anykey96
Сообщения: 4
ОС: CentOS

Re: Скрипт парсинга syslog

Сообщение anykey96 » 10.01.2019 12:56

Vascom писал:
10.01.2019 12:48
Показывай что уже сделал и что конкретно не получается.
Я только начал разбираться. У меня скрипта пока что нету.
Я в теории мог бы конечно grep использовать, но когда логи попадутся размером под сотни мегабайт, пошёл искать решение. Нашёл информацию про RegExp'ы. Решил попросить помощи, может кто накидает скрипт.
Спасибо сказали:

Аватара пользователя
Vascom
Сообщения: 1460
ОС: Fedora 30

Re: Скрипт парсинга syslog

Сообщение Vascom » 10.01.2019 12:57

grep работает очень быстро. Тебе по любому его использовать придётся, и он тоже умеет регулярные выражения.
Спасибо сказали:

anykey96
Сообщения: 4
ОС: CentOS

Re: Скрипт парсинга syslog

Сообщение anykey96 » 10.01.2019 13:02

Vascom писал:
10.01.2019 12:57
grep работает очень быстро. Тебе по любому его использовать придётся, и он тоже умеет регулярные выражения.
Да, само собой.
Но если кто нибудь сможет написать скриптик, я в дальнейшем попробовал бы доработать его, что бы например через регулярки исключить вывод данных по конкретным значениям (типо отфильтровать выводимую информацию).
Хочу понять как вообще данный скрипт выглядит и как работают регулярки (RegExp)
Спасибо сказали:

Аватара пользователя
devilr
Сообщения: 1705
ОС: Mandriva => Gentoo (~amd64)

Re: Скрипт парсинга syslog

Сообщение devilr » 10.01.2019 13:08

Ну так никто не мешает нанять кого-нибудь, если самому не хочется. А если хочется помощи - надо самому что-нибудь сделать, а там кто и поможет. А с халявой лучше куда нибудь в другое место обратиться.
Мудрость приходит с возрастом.
Иногда возраст приходит один.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15527
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Скрипт парсинга syslog

Сообщение Bizdelnick » 10.01.2019 13:32

anykey96 писал:
10.01.2019 12:46
необходимо с помощью "регулярок" вывести на экран только строки содержащие к примеру testuser
grep testuser /var/log/syslog
anykey96 писал:
10.01.2019 12:46
опционально - выбрать из всего найденного в логе только данные за последние 20 минут (значение date)
Это сложнее. Проще ограничить число обрабатываемых строк, скажем, 20-ю: tail -n20 /var/log/syslog | grep testuser.
anykey96 писал:
10.01.2019 12:56
Я в теории мог бы конечно grep использовать, но когда логи попадутся размером под сотни мегабайт, пошёл искать решение. Нашёл информацию про RegExp'ы.
Так grep и использует регулярки. Буквы re в его имени — сокращение от regular expression, если что.
anykey96 писал:
10.01.2019 13:02
Хочу понять как вообще данный скрипт выглядит и как работают регулярки (RegExp)
По этому поводу написано очень много, а в двух словах рассказать затруднительно. Не так давно переиздали «Регулярные выражения» Фридла, например. В начале там очень хорошее введение для начинающих, а дальше — подробный разбор для продолжающих.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

anykey96
Сообщения: 4
ОС: CentOS

Re: Скрипт парсинга syslog

Сообщение anykey96 » 10.01.2019 15:31

Bizdelnick писал:
10.01.2019 13:32
«Регулярные выражения» Фридла
Спасибо. Нужно изучить.
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 10.01.2019 17:43

Да вроде ни чего сложного:
Spoiler

Код: Выделить всё

#!/bin/bash
#DAT=$(date +%H:%M)
D_HOURS="9"
D_MINUTES="20"
HM=$[D_HOURS*60+D_MINUTES]
func() {
        while read file
        do
        tm="$(echo $file|awk '{print $3}')"
        tm=${tm%:[0-9][0-9]}
        if [[ "$tm" == [0-9][0-9]:[0-9][0-9] ]] ; then
                MASS=(${tm/:/ })
                HOURS=${MASS[0]}
         #Remove the first zero
                HOURS=${HOURS#0}
                MINUTE=${MASS[1]}
                HM2=$[HOURS*60+MINUTE]
                TIME=$[HM-HM2]
                if [ "$TIME" -le "20" ] ; then
                echo $file
                fi
        fi

        done <log.txt
}

func
Дальше сами думайте как доработать. В качестве примера брал ваш вывод и поместил в файл log.txt. Все примеры в этом скрипте есть.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15527
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Скрипт парсинга syslog

Сообщение Bizdelnick » 10.01.2019 17:59

ormorph писал(а):
10.01.2019 17:43
Да вроде ни чего сложного
Во-первых, это сложно, во-вторых, некрасиво, и в-третьих, неправильно, ибо не учитывает дату.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 266
ОС: OpenBSD

Re: Скрипт парсинга syslog

Сообщение nerve » 10.01.2019 18:09

ormorph писал(а):
10.01.2019 17:43
done <<< "$(cat log.txt)"
почему не
done < log.txt
ormorph писал(а):
10.01.2019 17:43
while read file
не логичнее ли
while read -r line
ormorph писал(а):
10.01.2019 17:43
HM=$[D_HOURS*60+D_MINUTES]
что это за конструкция? arithmetic expansion?
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 10.01.2019 18:13

Bizdelnick писал:
10.01.2019 17:59
и в-третьих, неправильно, ибо не учитывает дату.
Ну я же только пример привел как можно реализовать, а дату вполне можно забить тоже, просто парсить еще столбцы с месяцем и числом. По тому и сказал что дальше сами. Тут только пример как можно осуществить вывод за последние 20 минут, исключая месяц и день. Соответственно предполагается что топикластер это решит сам...
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 10.01.2019 18:23

nerve писал(а):
10.01.2019 18:09
что это за конструкция? arithmetic expansion?
Обычная конструкция вычисления в bash, работает только в нем. Просто вычисляет полное количество минут, знак долара в данной конструкции перед переменными не ставится.
nerve писал(а):
10.01.2019 18:09
не логичнее ли
while read -r line
Можете просто while read line сделать, разницы особо ни какой.
nerve писал(а):
10.01.2019 18:09
done < log.txt
Тут уже опоздали, я это уже было поправил.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15527
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Скрипт парсинга syslog

Сообщение Bizdelnick » 10.01.2019 18:27

ormorph писал(а):
10.01.2019 18:13
дату вполне можно забить тоже, просто парсить еще столбцы с месяцем и числом. По тому и сказал что дальше сами.
Это попахивает садизмом. ☺

Код: Выделить всё

#!/bin/sh -e

if [ $# -ne 2 -o ! -f "$2" ]; then
    echo "usage: $0 <minutes> <file>" >&2
    exit 1
fi

SEC=$(( $1 * 60 ))
FILE=$2
NOW=$( date +%s )

while read line; do
    TIME=$( date -d "$( echo "$line" | cut -d ' ' -f 1,2,3 )" +%s )
    if [ $(( NOW - TIME )) -lt $SEC ]; then
        echo "$line"
    fi
done < "$FILE"
На всякий случай уточню, что скрипт не для «продакшна», так как не хватает обработки ошибок. И регулярок нет, так что можно сказать, что решение не соответствует постановке задачи.
А вообще шелл — не самый эффективный инструмент для таких вещей: у меня этот скрипт больше 5 секунд обрабатывал лог размером 437K.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 10.01.2019 18:37

Bizdelnick писал:
10.01.2019 18:27
Это попахивает садизмом.
Всего лишь немного :)
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 10.01.2019 20:34

Bizdelnick писал:
10.01.2019 18:27
меня этот скрипт больше 5 секунд обрабатывал лог размером 437K
У меня моя конструкция вывод за последние 20 минут, обрабатывает лог за 4 секунды, размер лога 1.1G.
Обрабатывал свой лог в /var/log/messages, там похожий вывод. Давно я данный файл не чистил вот и набралось )
Скрипт немного переделанный c месяцем и днем:
Spoiler

Код: Выделить всё

#!/bin/bash
export LC_ALL=C
D_HOURS="$(date +%H)"
D_HOURS="${D_HOURS#0}"
D_MINUTES="$(date +%M)"
D_MINUTES="${D_MINUTES#0}"

HM=$[D_HOURS*60+D_MINUTES]

while read line
do
  tm="$(echo $line|awk '{print $3}')"
  tm=${tm%:[0-9][0-9]}
  if [[ "$tm" == [0-9][0-9]:[0-9][0-9] ]] ; then
        MASS=(${tm/:/ })
        HOURS=${MASS[0]#0}
        MINUTE=${MASS[1]#0}
        HM2=$[HOURS*60+MINUTE]
        TIME=$[HM-HM2]
        if [ "$TIME" -le "20" ] ; then
                echo $line
        fi
  fi
done <<<"$(grep "$(date '+%b %d')" /var/log/messages)"
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15527
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Скрипт парсинга syslog

Сообщение Bizdelnick » 10.01.2019 21:03

ormorph писал(а):
10.01.2019 20:34
Скрипт немного переделанный c месяцем и днем
А если в полночь запустить? А если внезапно будет запись вида

Код: Выделить всё

Jan 01 21:01:01 localhost somedaemon: Something will happen on Jan 10
?
С регулярками надо учитывать массу нюансов.
ormorph писал(а):
10.01.2019 20:34
Давно я данный файл не чистил
Ротацию принципиально не используете?
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 10.01.2019 21:39

Bizdelnick писал:
10.01.2019 21:03
С регулярками надо учитывать массу нюансов.
Ну это да, считать надо однако, но в данном случае просто вывод будет короче, а так соврал первый раз обработка занимает 17 секунд, а потом grep кеширует и обработка занимает 4 секунды.
Ну и если на то пошло то и без регулярок вывод будет не правильным если присутствует вывод другого года за данный месяц, date тоже покажет ложный ответ, так как в логе год не указан.
Немного подправил:
Spoiler

Код: Выделить всё

#!/bin/bash
export LC_ALL=C
D_HOURS="$(date +%H)"
D_HOURS="${D_HOURS#0}"
D_MINUTES="$(date +%M)"
D_MINUTES="${D_MINUTES#0}"

HM=$[D_HOURS*60+D_MINUTES]
while read line
do
  tm="$(echo $line|awk '{print $3}')"
  tm=${tm%:[0-9][0-9]}
  if [[ "$tm" == [0-9][0-9]:[0-9][0-9] ]] ; then
        MASS=(${tm/:/ })
        HOURS=${MASS[0]#0}
        MINUTE=${MASS[1]#0}
        HM2=$[HOURS*60+MINUTE]
        TIME=$[HM-HM2]
        if [ "$TIME" -le "20" ] && [ $TIME -ge "0" ]; then
                echo $line
        fi
  fi
done <<<"$(grep "$(date '+%b %d')" /var/log/messages)"
А так в вашем скрипте date скорее всего в цикле замедляет весь процесс.
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 10.01.2019 21:47

Bizdelnick писал:
10.01.2019 21:03
Ротацию принципиально не используете?
Лень мне этим заниматься))
А так обычно лог мне нужен в реальном времени, по этому обычно использую мониторинг лога:

Shell

# tail -f /var/log/messages
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15527
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Скрипт парсинга syslog

Сообщение Bizdelnick » 10.01.2019 21:50

ormorph писал(а):
10.01.2019 21:39
в данном случае просто вывод будет короче
Не вывод будет короче, а мы не увидим того, что рассчитывали увидеть. А кто-то, зная это, может воспользоваться и запустить нечто нехорошее без минуты полночь.
ormorph писал(а):
10.01.2019 21:39
Ну и если на то пошло то и без регулярок вывод будет не правильным если присутствует вывод другого года за данный месяц, date тоже покажет ложный ответ, так как в логе год не указан.
Ну у большинства ротация всё же настроена. ☺
ormorph писал(а):
10.01.2019 21:39
А так в вашем скрипте date скорее всего в цикле замедляет весь процесс.
Может быть. Зато время считается по-человечески.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 11.01.2019 22:48

Хм интересно на фига я awk в скрипт включил. Короче выпилил awk, теперь все вычисления в цикле идут только средствами bash. Как результат скорость обработки в цикле ускорилась в три раза.
Spoiler

Код: Выделить всё

#!/bin/bash
export LC_ALL=C
D_HOURS="$(date +%H)"
D_HOURS="${D_HOURS#0}"
D_MINUTES="$(date +%M)"
D_MINUTES="${D_MINUTES#0}"

HM=$[D_HOURS*60+D_MINUTES]
while read line
do
  tm=($line)
  tm=${tm[2]%:[0-9][0-9]}
  if [[ "$tm" == [0-9][0-9]:[0-9][0-9] ]] ; then
        MASS=(${tm/:/ })
        HOURS=${MASS[0]#0}
        MINUTE=${MASS[1]#0}
        HM2=$[HOURS*60+MINUTE]
        TIME=$[HM-HM2]
        if [ "$TIME" -le "20" ] && [ $TIME -ge "0" ]; then
                echo $line
        fi
  fi
done <<<"$(grep "$(date '+%b %d')" /var/log/messages)"
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15527
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Скрипт парсинга syslog

Сообщение Bizdelnick » 12.01.2019 01:14

ormorph, если хотите похвастаться скоростью bash, сначала переплюньте sudo cat /var/log/syslog | perl -MTime::Piece -MTime::Seconds -n -e '/^([a-zA-Z]+ [0-9]+ [0-9]+:[0-9]+:[0-9]+)/; my $now = localtime; my $time=Time::Piece->strptime($now->strftime("%Y $1 %z"), "%Y %b %d %T %z"); if ($time > $now) { $time -= ONE_YEAR; } print if (($now - $time)->minutes < 20);' :sarcastic_hand:
Ну и полуночную проблему решите.
Последний раз редактировалось Bizdelnick 12.01.2019 12:01, всего редактировалось 3 раза.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 12.01.2019 07:19

Bizdelnick писал:
12.01.2019 01:14
если хотите похвастаться скоростью bash, сначала переплюньте
Ну дык, ясен пень перл быстрее.
Я просто имел в виду, что вызов сторонних программ, всегда замедляет скорость работы.
Только вот эта конструкция у меня каждый месяц выводит, все жду когда же этот вывод прекратится, тогда уж сразу просто cat. После того как прошла минута надоело ждать и нажал ctrl+c.
Спасибо сказали:

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 15527
Статус: grammatikführer
ОС: Debian GNU/Linux

Re: Скрипт парсинга syslog

Сообщение Bizdelnick » 12.01.2019 11:52

ormorph писал(а):
12.01.2019 07:19
Только вот эта конструкция у меня каждый месяц выводит
Угу, поправил.
Пишите правильно:
в консоли
вкупе (с чем-либо)
в общем
вообще
в течение (часа)
команда
новичок
нюанс
приемлемо
проблема
пробовать
трафик
Спасибо сказали:

Аватара пользователя
ormorph
Сообщения: 861
ОС: Gentoo

Re: Скрипт парсинга syslog

Сообщение ormorph » 12.01.2019 15:36

Bizdelnick писал:
12.01.2019 11:52
Угу, поправил.
Заняло время:

Shell

real 19m57,305s
user 16m42,554s
sys 2m59,890s
Но перл тут не причем, у меня цикл обрабатывает то, что уже выбрал grep, по этому быстрее получилось, а так да - перл быстрее.
Спасибо сказали: