LINUX.ORG.RU
ФорумAdmin

treb есть? а нужен кому?

 ,


0

1

treb = time range regular expression builder

Существует ли тулза, которая по заданному временному интервалу генерирует регулярное выражение для отбора grep'ом из логов? Ну например сделать из временного интервала:

Jan 22 16:11:23 - Mar 08 13:43:54

такое:

Jan (22 (16:(11:(2[3-9]|[3-5])|1[2-9]|[2-5])|1[7-9]|2[0-3])|2[3-9]|3)|Feb|Mar (08 (13:(43:([0-4]|5[0-4])|[0-3]|4[0-2])|0|1[0-2])|0[1-7])

Я просто попробовал через date преобразовывать timestamp'ы в секунды и отбирать то, что входит в интервал, но это страшно медленно, как оказалось.

Пример задачи: есть OpenVPN клиент к vpnbook, который, как известно, периодически меняет пароль. Есть скрипт на клиенте, котрый проверяет OpenVPN интерфейс, скажем, каждые 5 минут. Если интерфейс упалый, то, чтобы не парсить лишний раз сайт vpnbook в поисках нового пароля, надо бы узнать из логов, что причина именно в смене пароля. Т. е. найти в логе записи с предыдущего запуска скрипта, а в них - AUTH_FAILED.

Все это из$ебство чистой воды, я понимаю и знаю про tail -r пицот, но мы перфекционисты таки таковы. Задача показалась интересной для ума. Алгоритм я додумаю, но сам уж лет 20 как не программист. Какой-нибудь знакомый для меня C - это слишком большой порог вхождения при переходе на linux. Немного колупаю Perl, но тащить его за собой ради такой задачи - это слишком. На чем писать-то? Какой-нибудь shell умеет в рекурсию?


... надо было в Development же((

rubic
() автор топика

эммм... в логах timestamp'ы перемешаны? или все ж «отсортированы» по возрастающей?

Deleted
()

Делать такое регулярками — знатное извращение.

good_riddance
()
Ответ на: комментарий от rubic

у меня были логи с таким шаблоном:

INFO -- TIMESTAMP -- DATA
TIMESTAMP формата Jan 22 16:11:23.

парсил так:

$perl -lne 'print if /Jan 22 16:11:23/.../Mar 08 13:43:54/' LOG

Deleted
()
Ответ на: комментарий от Deleted

Ух ты! Perl таки есть у меня на той VPS-ке с pfSense. Однако, попробую, спасибо!

rubic
() автор топика
Ответ на: комментарий от Deleted

/Jan 22 16:11:23/.../Mar 08 13:43:54/

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

В норме же дать границы не глядя предварительно в лог.

futurama ★★★★★
()

Я просто попробовал через date преобразовывать timestamp'ы в секунды и отбирать то, что входит в интервал, но это страшно медленно, как оказалось.

т.е. ты в bash читал построчно и парсил строку и date'ом преобразовывал в секунды? Неудивительно что получил тормоза, столько запусков внешних утилит. Пиши все на нормальном языке, perl или хотя бы awk и все сразу изменится в лучшую сторону.

futurama ★★★★★
()
Ответ на: комментарий от futurama

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

да, универсальность аукается)

В норме же дать границы не глядя предварительно в лог.

можно делать такую проверку:

if ($timestamp ge "Jan 22 16:11:23" && $timestamp le "Mar 08 13:43:54")
{
   ...

думаю это тоже окажется быстрее, чем вариант ТС. Но не проверял)

Deleted
()

Какой-нибудь shell умеет в рекурсию?

Любая оболочка умеет в рекурсию, а что?

Я просто попробовал через date преобразовывать timestamp'ы в секунды

Нафига? Перевод фиксированного формата даты в секунды от сотворения Юникса — операция довольно тривиальная — date(1) для этого не нужен. Единственная проблема — у нас нет года, из нее два следствия: во-первых, мы не знаем, високосный ли он, придется предположить, что имеется в виду, например, текущий год; а во-вторых, если мы анализируем поток именно построчно, то я не могу предложить никакого внятного алгоритма перехода через точку нового года.

В остальном же тут все должно быть просто:

#!/bin/bash

printf -v Y '%(%Y)T'

if ((Y % 4 == 0 && Y % 100 != 0)); then
    declare -A b_to_d=( [Jan]=0   [Feb]=31  [Mar]=60  [Apr]=91
                        [May]=121 [Jun]=152 [Jul]=182 [Aug]=213
                        [Sep]=244 [Oct]=274 [Nov]=305 [Dec]=335 )
else
    declare -A b_to_d=( [Jan]=0   [Feb]=31  [Mar]=59  [Apr]=90
                        [May]=120 [Jun]=151 [Jul]=181 [Aug]=212
                        [Sep]=243 [Oct]=273 [Nov]=304 [Dec]=334 )
fi

date_to_seconds () # $b $d $H $M $S s
{
    printf -v "$6" $((24*60*60*b_to_d[$1] + 24*60*60*10#$2
                      + 60*60*10#$3 + 60*10#$4 + 10#$5))
}

IFS+=':' read f_b f_d f_H f_M f_S __ t_b t_d t_H t_M t_S <<< "$@"

date_to_seconds $f_b $f_d $f_H $f_M $f_S from_s
date_to_seconds $t_b $t_d $t_H $t_M $t_S to_s

while read line; do
    IFS+=':' read b d H M S msg <<< "$line"
    date_to_seconds $b $d $H $M $S s
    if (( from_s <= s && s <= to_s )); then
        printf '%s\n' "$line"
    fi
done

Впрочем не проверял, могут быть ошибки вплоть до синтаксических. Но смысл, я думаю, понятен и без комментариев?

Zmicier ★★★★★
()
Ответ на: комментарий от Zmicier

Да, usage example, если непонятно, предполагается такой:

$ gdateintp Jan 22 16:11:23 - Mar 08 13:43:54 < log
Zmicier ★★★★★
()
Последнее исправление: Zmicier (всего исправлений: 1)

Примерно так вот

awk -v start="012216:11:23" -v finish="030813:43:54" '
BEGIN { for(i=0;i<12;i++) month[strftime("%b",i*2764800)]=sprintf("%02",i) }
month[$1] { now=month[$1] sprintf("%02d",$2) $3 }
now >= start  { print }
now >= finish { exit }
'

без поправки на новый год. Не проверял.

DonkeyHot ★★★★★
()
Последнее исправление: DonkeyHot (всего исправлений: 2)
Ответ на: комментарий от Zmicier

Да, я понял про арифметику. С regexp - это просто наваждение какое-то нашло. Может потому, что частенько приходится иметь с ними дело.

rubic
() автор топика
19 сентября 2016 г.
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.