LINUX.ORG.RU
ФорумAdmin

Подскажите регексу

 ,


0

1

Нужно из лога вытянуть продолжительность сессий

[2025-06-12 10:32:15.142][INFO][1][xxx] Session UP
...bla
...bla
...bla...
[2025-06-12 10:40:15.142][INFO][1][xxx] Session Down by KAPEC

[2025-06-12 12:32:15.142][INFO][1][yyy] Session UP
...kukuku...
[2025-06-12 12:40:15.142][INFO][1][yyy] Session Down by KABZDEC

[2025-06-12 13:32:15.142][INFO][1][zzz] Session UP
...phphph...
[2025-06-12 13:40:15.142][INFO][1][zzz] Session Down by PIPEC

xxx|yyy|zzz - идентификатор сессии

Что я пытаюсь сделать и ни к чему пока не приводит (.+ сжирает все до конца строки)

journalctl --no-pager  | grep "Session UP" | grep -oEi "[0-9]{2}:[0-9]{2}:[0-9]{2}.*[0-9a-z]{8}"


Нужно в конце получить лог
Идентификатор / Время старта / Продолжительность (сек) / Причина (PIPEC|KAPEC|PIPEC)

Понимаю, что выглядит как целая работа, но может гений решит по быстрому

★★★★

Ну для начала как-то так.

< log.txt awk -vFPAT='[^][]+' '$5~/Session UP/ { start=$1; } $5~/Session Down/ {print start " | " $1 " | " $4 " | " $5}'
2025-06-12 10:32:15.142 | 2025-06-12 10:40:15.142 | xxx |  Session Down by KAPEC
2025-06-12 12:32:15.142 | 2025-06-12 12:40:15.142 | yyy |  Session Down by KABZDEC
2025-06-12 13:32:15.142 | 2025-06-12 13:40:15.142 | zzz |  Session Down by PIPEC

Парсить и вычитать датувремя awk может, но мне лень

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

Сходу не завелось. Я как понимаю там жестко по колонкам разбивка? Дело в том, что это упрощенный лог, я вообще думал по патернам выдергивать

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

Ну да, оно бьёт на поля строки, не содержащие квадратных скобочек.

legolegs ★★★★★
()

Надо скриптом на питоне парсить

>>> (dt.datetime.fromisoformat('2025-06-12 10:32:15.142') - dt.datetime.fromisoformat('2025-06-12 10:40:15.142')).seconds
85920

(надо только местами две даты поменять, мне лень)

rtxtxtrx ★★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)

продолжительность сессий

А в каком она месте? Это таймстемр Down минус Up? Если так, то grep здесь не помощник.

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

Эх ладно, наверное придется на nodejs делать нормальный парсер...

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

А такое?

[2025-06-12 10:32:15.142][INFO][1][xxx] Session UP
[2025-06-12 11:32:15.142][INFO][1][yyy] Session UP
[2025-06-12 12:32:15.142][INFO][1][xxx] Session Down by KAPEC
[2025-06-12 13:32:15.142][INFO][1][zzz] Session UP
[2025-06-12 14:32:15.142][INFO][1][yyy] Session Down by KABZDEC
[2025-06-12 15:32:15.142][INFO][1][zzz] Session Down by PIPEC
anonymous
()
#!/usr/bin/env perl

use strict;
use warnings;

my $rx_item = qr{
                \[       # opening bracket
                ([^\]]*) # captured value
                \]       # closing bracket
              }x;
my $rx_log_prefix = $rx_item x4;

my %sessions;

while(<>) {
    chomp;
    if (/Session UP$/) {
        my ($start_datetime, undef, undef, $id) = /^$rx_log_prefix/;
        warn "Session $id is already UP - overwriting"
            if exists $sessions{$id};
        $sessions{$id} = { start_datetime => $start_datetime };
    } elsif (/Session Down/) {
        warn "Missing reason" unless /by (.*)$/;
        my $reason = $1;
        my ($end_datetime, undef, undef, $id) = /^$rx_log_prefix/;
        warn "Session $id is down but no UP message found"
            unless exists $sessions{$id};
        my $start_datetime = $sessions{$id}{start_datetime};
        print "$id | $start_datetime | $end_datetime | $reason\n";
        delete $sessions{$id};
    }
}
$ ./pipec.pl t
xxx | 2025-06-12 10:32:15.142 | 2025-06-12 10:40:15.142 | KAPEC
yyy | 2025-06-12 12:32:15.142 | 2025-06-12 12:40:15.142 | KABZDEC
zzz | 2025-06-12 13:32:15.142 | 2025-06-12 13:40:15.142 | PIPEC
annulen ★★★★★
()
Ответ на: комментарий от annulen

journalctl --no-pager | ./s.pl

Use of uninitialized value $id in hash element at ./s.pl line 28, <> line 25987.
Use of uninitialized value $id in concatenation (.) or string at ./s.pl line 29, <> line 25987.
Use of uninitialized value $start_datetime in concatenation (.) or string at ./s.pl line 29, <> line 25987.
Use of uninitialized value $end_datetime in concatenation (.) or string at ./s.pl line 29, <> line 25987.
 |  |  | DTLS alert(warning CN), username=9d2t68gt:8MoR
Use of uninitialized value $id in delete at ./s.pl line 30, <> line 25987.
Use of uninitialized value $id in exists at ./s.pl line 27, <> line 30111.

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

journalctl –no-pager | ./s.pl

Тебе уже напоминали на –no-pager при использовании пайп бесполезен.

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

У ТС идентификаторы не перекрывались. Хотя он вообще много темнит.

legolegs ★★★★★
()

Если сделаю решение в десяток строк на sam (часть проекта plan9port), устроит?

kaldeon
()

session.awk

/Session/ && match($0, /\[(.+)\]/, a) {
    match($0, /\[1\]\[(.+)\] Session/, session)
    session_id = session[1]
    split(a[1], t, "[-:. ]");
    log_time = mktime(t[1]" "t[2]" "t[3]" "t[4]" "t[5]" "t[6]) + t[7]/1000
    human_time = strftime("%Y-%m-%d %H:%M:%S", log_time)
    if ($4 == "UP") {
        sessions[session_id] = log_time
        sessions_start[session_id] = human_time
    } else {
        printf("%s\t%s\t%d\t%s\n", session_id, sessions_start[session_id], log_time - sessions[session_id], $NF)
    }
}

$ journalctl --no-pager | awk -f session.awk
xxx     2025-06-12 10:32:15     480     KAPEC
yyy     2025-06-12 12:32:15     480     KABZDEC
zzz     2025-06-12 13:32:15     480     PIPEC

Эх ладно, наверное придется на nodejs делать нормальный парсер.

Если бы люди умели пользоваться vim, grep, sed, awk, то миллионы программных продуктов так никогда и не были бы созданы (с) не моё

gagarin0
()
Последнее исправление: gagarin0 (всего исправлений: 2)

Однострочник (то есть можешь копиравать в терминал, ну, кроме первого $).

$ cat file.log | 
sed -n 's@^\[\([^ ]*\) \([^]]*\)]\[INFO]\[[^]]*]\[\([^]]*\)] Session \(UP\|Down by \(.*\)\)$@\3 \1T\2 \5@p' | 
sort -k1,1 | 
while read SESSION TIME REASON; do 
  TIME="${TIME%.*}"; 
  TIME_S="$( date -d "$TIME" +%s )"; 
  if [[ -z "$REASON" ]]; then 
    START="$TIME"; 
    START_S="$TIME_S"; 
  else 
    DURATION="$( bc <<< "$TIME_S - $START_S" )"; 
    echo "$SESSION $START $DURATION $REASON"; 
  fi; 
done

Пояснения:

  • sed с регуляркой конвертит в стоку вида «сессия время причина».
  • Сессия идёт первой, чтобы потом по ней сортировать на случай если сессии пересекаются.
  • Между датой и временем sed добавляет ‘T’, что, с одной стороны, позволяет в последующей логике использовать пробел как разделитель, а с другой стороны, нормально воспринимается date, которая переведёт это в секунды.
  • Ключ -n в sed говорит выводить только строки в которых встретился паттерн; то есть это работает еще и как grep.
  • ${TIME%.*} отрежет всё что после последней точки - миллисекунды.

Регулярка на самом деле простая, просто длинная:

  • В качестве разделителя в s использую ‘@’, чтобы в глазах не так рябило от слешей.
  • [^ ]* (тут LOR в конце съел пробел) - все символы до пробела, [^]]*] - все символы до закрывающейся квадратной скобки; на самом деле нотация «ноль или более не-пробела и потом пробел», «ноль или более не-скобки и потом скобка».
  • \(...\) - запомнить; далее можно использовать через \1, \2, \3 и т. п.
  • \(word1\|word2\) - или одно слово, или второе; ну и круглая скобка запоминает.

Остальное, думаю, понятно.

Kroz ★★★★★
()
Последнее исправление: Kroz (всего исправлений: 1)
ssam -e 'x/^\[[^\]]*\]/ y/\[|\]/ g/./ |date -j -f "%Y-%m-%d %H:%M:%S" "$(cat)" "+%s" |tr -d "\n"' |
ssam -e '{
	d
	x g/Session +UP/ {
		-#0+/\[[^\]]*\]/+//+//+// y/\[|\]/ g/./ {
			t $
			$ a| / |
		}
		-#0+/\[[^\]]*\]/ y/\[|\]/ g/./ {
			t $
			$ a| / |
			t $
			$ a/-/
		}
		/Session +Down/-+ {
			-#0+/\[[^\]]*\]/ y/\[|\]/ g/./ {
				t $
				$ a| / |
			}
			+#0-/[a-zA-Z_0-9]*/ {
				t $
				$ a/\n/
			}
		}
	}
}' |
ssam -e 'x {
	-#0+/[0-9]+/ |date -j -f "%s" "$(cat)" "+%Y-%m-%d %H:%M:%S" |tr -d "\n"
	-#0+/[0-9]+-[0-9]+/ |echo "-($(cat))" |bc |tr -d "\n"
}'
kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 3)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.