[gelöst] Selektiere Log-Einträge der letzten 24h (mit awk?)

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
bivvo
Beiträge: 47
Registriert: 16.09.2021 11:40:12

[gelöst] Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von bivvo » 22.01.2022 10:02:02

Hi,

ich hab ein Logfile, das ich mit cat "einlesen" möchte, um hier im Beispiel LOG1D später dann mit grep weiter zu filtern:

Code: Alles auswählen

LOG1D="$(cat ${MOUNTPOINTS[$i]}${NODELOGPATHS[$i]} 2>&1)"
Das funktioniert auch und LOG1D enthält dann Einträge wie z.B.:

Code: Alles auswählen

2022-01-22T08:45:12.295Z	INFO	piecestore	downloaded	{"Piece ID": "B2SHZETVWNASW3764GETRLYZKBNLPU2TL3DX6NWM5C5NW4AXURXA", "Satellite ID": "1wFTAgs9DP5RSnCqKV1eLf6N9wtk4EAtmN5DpSxcs8EjT69tGE", "Action": "GET"}
2022-01-22T08:45:12.490Z	INFO	piecestore	download started	{"Piece ID": "OGUOZMBAVB6AR3PO5JBAL3QDMCMDKBHCD4E5TN3RG7P2L5FI6Y2Q", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "GET"}
2022-01-22T08:45:12.532Z	INFO	piecestore	downloaded	{"Piece ID": "VUD2H7MNAG3TTXR6LK4R5T6FYBCDWCUH7IMAGBE2HZCI6Z5K44BA", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "GET"}
2022-01-22T08:45:12.768Z	INFO	piecestore	download canceled	{"Piece ID": "OGUOZMBAVB6AR3PO5JBAL3QDMCMDKBHCD4E5TN3RG7P2L5FI6Y2Q", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "GET"}
2022-01-22T08:45:14.146Z	INFO	piecestore	upload started	{"Piece ID": "B4Y5LCWNMUBXSCLNFPIBO6GMUW62SS5BPJLNYRZX7MHQOEZRB2FQ", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "PUT", "Available Space": 8185263356164}
2022-01-22T08:45:14.691Z	INFO	piecestore	uploaded	{"Piece ID": "B4Y5LCWNMUBXSCLNFPIBO6GMUW62SS5BPJLNYRZX7MHQOEZRB2FQ", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "PUT", "Size": 181504}
Allerdings möchte ich beim Einlesen nicht das ganze Logfile weiterverarbeiten, sondern nur z.B. die letzten 24.

Dafür bin ich im Netz auf folgenden Befehl gestolpert, weiß aber nicht, wie ich das korrekt umformuliere, um o.g. Selektion entsprechend zu ändern, so dass nur die letzten 24h selektiert werden.

Code: Alles auswählen

awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date) print Date FS $4}' access.log
Ich vermute, dass das Format nicht stimmt und bin mir auch unsicher, was ich mit dem hinteren Teil "print Date FS" machen soll, damit die selektierten Zeilen letztendlich in LOG1D landen.
Zuletzt geändert von bivvo am 22.07.2022 16:56:30, insgesamt 3-mal geändert.

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von Meillo » 22.01.2022 10:47:56

bivvo hat geschrieben: ↑ zum Beitrag ↑
22.01.2022 10:02:02
Das funktioniert auch und LOG1D enthält dann Einträge wie z.B.:

Code: Alles auswählen

2022-01-22T08:45:12.295Z	INFO	piecestore	downloaded	{"Piece ID": "B2SHZETVWNASW3764GETRLYZKBNLPU2TL3DX6NWM5C5NW4AXURXA", "Satellite ID": "1wFTAgs9DP5RSnCqKV1eLf6N9wtk4EAtmN5DpSxcs8EjT69tGE", "Action": "GET"}
2022-01-22T08:45:12.490Z	INFO	piecestore	download started	{"Piece ID": "OGUOZMBAVB6AR3PO5JBAL3QDMCMDKBHCD4E5TN3RG7P2L5FI6Y2Q", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "GET"}
2022-01-22T08:45:12.532Z	INFO	piecestore	downloaded	{"Piece ID": "VUD2H7MNAG3TTXR6LK4R5T6FYBCDWCUH7IMAGBE2HZCI6Z5K44BA", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "GET"}
2022-01-22T08:45:12.768Z	INFO	piecestore	download canceled	{"Piece ID": "OGUOZMBAVB6AR3PO5JBAL3QDMCMDKBHCD4E5TN3RG7P2L5FI6Y2Q", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "GET"}
2022-01-22T08:45:14.146Z	INFO	piecestore	upload started	{"Piece ID": "B4Y5LCWNMUBXSCLNFPIBO6GMUW62SS5BPJLNYRZX7MHQOEZRB2FQ", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "PUT", "Available Space": 8185263356164}
2022-01-22T08:45:14.691Z	INFO	piecestore	uploaded	{"Piece ID": "B4Y5LCWNMUBXSCLNFPIBO6GMUW62SS5BPJLNYRZX7MHQOEZRB2FQ", "Satellite ID": "12EayRS2V1kEsWESU9QMRseFhdxYxKicsiFmxrsLZHeLUtdps3S", "Action": "PUT", "Size": 181504}
Allerdings möchte ich beim Einlesen nicht das ganze Logfile weiterverarbeiten, sondern nur z.B. die letzten 24.

Dafür bin ich im Netz auf folgenden Befehl gestolpert, weiß aber nicht, wie ich das korrekt umformuliere, um o.g. Selektion entsprechend zu ändern, so dass nur die letzten 24h selektiert werden.

Code: Alles auswählen

awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date) print Date FS $4}' access.log
Der Befehl ist vom Ansatz nicht falsch, passt aber nicht ganz auf dein Szenario und ist etwas umstaendlich. So passt es:

Code: Alles auswählen

awk -v Date=`date -d 'now - 24 hours' +'%Y-%m-%dT%H:%M:%S.000Z'` '$1 > Date'
Das Prinzip ist folgendes: Der erste Wert im Logfile ist ein Datum, das erfreulicherweise ein Format hat, das sortierbar bzw. asciibethisch vergleichbar ist. Folglich erzeugen wir mit date(1) ein Datum im gleichen Format, das genau 24h zurueck liegt. Dieses uebergeben wir awk in der Variable `Date'. Dann lassen wir alle Eintraege ausgeben, bei denen das Datum im Logfile groesser is als das Datum in `Date'.

Ich vermute, dass das Format nicht stimmt und bin mir auch unsicher, was ich mit dem hinteren Teil "print Date FS" machen soll, damit die selektierten Zeilen letztendlich in LOG1D landen.
Beim Datumsformat kannst du die Formatangabe hinter dem Plus-Zeichen vergleichen. Die Manpage von date(1) hilft dir dabei was was bedeutet. Du hattest recht, das hat nicht gepasst.

Der print-Befehl des von dir geposteten awk-Befehls muss fuer irgendein spezifisches Szeanario gewesen sein. Da du hier nur bestimmte Zeilen selektieren (d.h. ausgeben willst) reicht es, nur eine Bedingung anzugeben. Dann werden alle Zeilen ausgegeben, auf die die Bedingung zutrifft.


Performancetechnisch ist es eher nicht die beste Option, zuerst das ganze Logfile in eine Variable zu lesen, weil die dann ja so viel Speicher verbraucht wie das Logfile gross ist. Wenn das Logfile 80 MB gross ist, dann verbraucht die Variable und damit dein Script auch 80 MB Speicher! Wende besser gleich den awk-Befehl auf das Logfile an, um nur die relevanten Eintraege in deine Variable zu speichern.
Use ed once in a while!

bivvo
Beiträge: 47
Registriert: 16.09.2021 11:40:12

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von bivvo » 22.01.2022 11:58:51

Woah, danke! .. auch für deine Erklärungen - das hilft wirklich sehr.

"Performancetechnisch" schlägst du dann so etwas vor, wenn ich es richtig verstehe - korrekt?

Code: Alles auswählen

LOG1D="$(cat ${MOUNTPOINTS[$i]}${NODELOGPATHS[$i]} 2>&1 | 
    awk -v Date=`date -d 'now - 24 hours' +'%Y-%m-%dT%H:%M:%S.000Z'` '$1 > Date')"

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von Meillo » 22.01.2022 12:15:22

bivvo hat geschrieben: ↑ zum Beitrag ↑
22.01.2022 11:58:51
"Performancetechnisch" schlägst du dann so etwas vor, wenn ich es richtig verstehe - korrekt?

Code: Alles auswählen

LOG1D="$(cat ${MOUNTPOINTS[$i]}${NODELOGPATHS[$i]} 2>&1 | 
    awk -v Date=`date -d 'now - 24 hours' +'%Y-%m-%dT%H:%M:%S.000Z'` '$1 > Date')"
Ja, das ist schon viel besser.

Es kommt halt darauf an was du sonst noch damit machen willst. Manchmal muss man die Werte gar nicht in eine Variable speichern, sondern kann eher streamorientiert damit arbeiten, die Informationen also durchfliessen lassen, statt sie zwischenzuspeichern. Aber das haengt von deinem Problem ab. Ist aber auch nicht so wichtig.


Btw: Warum hast du denn ein `2>&1' bei deinem cat-Aufruf?
Use ed once in a while!

bivvo
Beiträge: 47
Registriert: 16.09.2021 11:40:12

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von bivvo » 22.01.2022 20:47:49

Meillo hat geschrieben: ↑ zum Beitrag ↑
22.01.2022 12:15:22
Btw: Warum hast du denn ein `2>&1' bei deinem cat-Aufruf?
Da hast du Recht, das macht hier keinen Sinn. Ich sollte vorher prüfen, ob die Datei existiert. ;-)
Danke für deine Unterstützung!

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von Meillo » 22.01.2022 22:13:23

bivvo hat geschrieben: ↑ zum Beitrag ↑
22.01.2022 20:47:49
Meillo hat geschrieben: ↑ zum Beitrag ↑
22.01.2022 12:15:22
Btw: Warum hast du denn ein `2>&1' bei deinem cat-Aufruf?
Da hast du Recht, das macht hier keinen Sinn. Ich sollte vorher prüfen, ob die Datei existiert. ;-)
Vor allem verschwindet die Fehlermeldung in der Pipeline, wo sie im konkreten Fall immer weggefiltert wird, da sie kein Datum enthaelt, ... statt auf dem Terminal rauszukommen, wo jemand die sehen koennte.
Use ed once in a while!

bivvo
Beiträge: 47
Registriert: 16.09.2021 11:40:12

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von bivvo » 12.02.2022 21:15:27

Hey. Ich hab noch eine ähnliche Herausforderung, bei der ich Unterstützung brauche:

Ich bekomme ein Datum im Format 2022-02-10 und möchte dieses mit dem aktuellen Datum vergleichen. Die Differenz soll als Integer in einer Variable gespeichert werden, weil ich damit später dann weiter arbeiten möchte.

Für MacOS hab ich das wie folgt umgesetzt, aber für Debian bekomme ich Fehlermeldungen - offenbar funktionieren die Parameter -jf unter Debian nicht.

Code: Alles auswählen

COMPDATE=$(cut -c1-10 <<< $FULLDATE) # Inhalt ist dann z.B. "2022-02-10"
TODAY=$(date +%Y-%m-%d)
DIFF=$(((`date -jf "%Y-%m-%d" "$TODAY" +%s` - `date -jf "%Y-%m-%d" "$COMPDATE" +%s`)/86400))
Im Netz gibt es unzählige Varianten... Ich möchte gern in einem einzigen Script sowohl die MacOS-Variante als auch eine für Debian laufen lassen.

Ich hab dabei an folgendes gedacht und würde dann entsprechend dem OS type unterscheiden:

Code: Alles auswählen

unameOut="$(uname -s)"
case "${unameOut}" in
    Linux*)     machine=Linux;;
    Darwin*)    machine=Mac;;
    CYGWIN*)    machine=Cygwin;;
    MINGW*)     machine=MinGw;;
    *)          machine="UNKNOWN:${unameOut}"
esac
echo ${machine}

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von Meillo » 12.02.2022 21:39:39

Statt diesem Aufruf fuer das FreeBSD date(1) in MacOS X:

Code: Alles auswählen

date -jf "%Y-%m-%d" "$TODAY" +%s
kannst du fuer das GNU date(1) das verwenden:

Code: Alles auswählen

date -d "$TODAY" +%s

Oder falls du auch unter MacOS X gawk verwendest: Das hat Datumserweiterungen, so dass du die Datumsrechnungen darin machen kannst.
Use ed once in a while!

bivvo
Beiträge: 47
Registriert: 16.09.2021 11:40:12

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von bivvo » 12.02.2022 23:41:29

Danke, läuft prima:

Code: Alles auswählen

    case "${UNAMEOUT}" in
        Linux*)     DIFF=$(((`date -d "$TODAY" +%s` - `date -d "$RDATE" +%s`)/86400));;
        Darwin*)    DIFF=$(((`date -jf "%Y-%m-%d" "$TODAY" +%s` - `date -jf "%Y-%m-%d" "$RDATE" +%s`)/86400));;
        *)          DIFF=0
    esac

bivvo
Beiträge: 47
Registriert: 16.09.2021 11:40:12

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von bivvo » 29.06.2022 22:39:27

bivvo hat geschrieben: ↑ zum Beitrag ↑
22.01.2022 11:58:51

Code: Alles auswählen

LOG1D="$(cat ${MOUNTPOINTS[$i]}${NODELOGPATHS[$i]} 2>&1 | 
    awk -v Date=`date -d 'now - 24 hours' +'%Y-%m-%dT%H:%M:%S.000Z'` '$1 > Date')"
Interessant, neuerlich bekomme ich folgenden Fehler zu dieser Zeile:

Code: Alles auswählen

LOG1X="$(cat ${MOUNTPOINTS[$i]}${NODELOGPATHS[$i]} | awk -v Date=`date -d 'now - $LOGMAX minutes' +'%Y-%m-%dT%H:%M:%S.000Z'` '$1 > Date')"
...
date: invalid date ‘now - $LOGMAX minutes’
Dann hab ich versucht, den Fehler zum umschiffen, was auch geklappt hat, aber selektiert werden alle Datensätze und nicht nur die, die durch awk eingeschränkt werden sollten (im Übrigen wie oben auch, nur eben ohne Fehlermeldung):

Code: Alles auswählen

LOGMAXDATE=$(date --date="$LOGMAX minutes ago" +'%Y-%m-%dT%H:%M:%S.000Z')
LOG1X="$(cat ${NODELOGPATHS[$i]} | awk -v date="$LOGMAXDATE" '$1 > Date')"
Hast du einen heißen Tipp für mich?

Benutzeravatar
Meillo
Moderator
Beiträge: 8813
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von Meillo » 29.06.2022 23:24:09

Wenn die Fehlermeldung so lautet, dann ist die Variable `$LOGMAX' nicht expandiert (= durch ihren Wert ersetzt) worden. D.h. das Quoting scheint kaputt zu sein. Eigentlich muesste `date' an der Stelle einen Zahlenwert bekommen.

Das waere meine Idee als Ansatzpunkt. Darauf basierend wuerde ich ein paar echo-Ausgaben machen oder ggf. `set -x' setzen, um nachvollziehen zu koennen was die Shell ausfuehrt.
Use ed once in a while!

bivvo
Beiträge: 47
Registriert: 16.09.2021 11:40:12

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von bivvo » 30.06.2022 21:49:17

Meillo hat geschrieben: ↑ zum Beitrag ↑
29.06.2022 23:24:09
Wenn die Fehlermeldung so lautet, dann ist die Variable `$LOGMAX' nicht expandiert (= durch ihren Wert ersetzt) worden. D.h. das Quoting scheint kaputt zu sein. Eigentlich muesste `date' an der Stelle einen Zahlenwert bekommen.
Ich habe folgendes probiert:

Code: Alles auswählen

pi@pi:~ $ LOGMAX=2
+ LOGMAX=2

pi@pi:~ $ cat /mnt/WD1003/logs/sn1.log | awk -v date=`date --date="$LOGMAX minutes ago" +'%Y-%m-%dT%H:%M:%S.000Z'` '$1 > Date'
+ cat /mnt/WD1003/logs/sn1.log
++ date '--date=2 minutes ago' +%Y-%m-%dT%H:%M:%S.000Z
+ awk -v date=2022-06-30T21:40:06.000Z '$1 > Date'
Sieht soweit eigentlich korrekt aus. Allerdings spuckt mir die Konsole wirklich alles aus -> awk scheint irgendwie logisch falsch zu sein. Ich komm aber einfach nicht drauf.

Code: Alles auswählen

date=2022-06-30T21:40:06.000Z
... ist exakt 2 Minuten vor dem Ausführen des Codes.

JTH
Moderator
Beiträge: 3023
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von JTH » 30.06.2022 23:19:17

Du hast in der Zeile mit cat… | awk … ganz am Ende Date groß geschrieben. Per -v übergibst du die Variable aber mit kleingeschriebenem Namen. Groß-/Kleinschreibung ist relevant.

Du benutzt damit die initialisierte Variable Date im Vergleich. Eine uninitialisierte Variable hat in awk meine ich immer den Wert 0, der Vergleich auf größer als wird damit wohl immer wahr sein.
Manchmal bekannt als Just (another) Terminal Hacker.

bivvo
Beiträge: 47
Registriert: 16.09.2021 11:40:12

Re: Selektiere Log-Einträge der letzten 24h (mit awk?)

Beitrag von bivvo » 30.06.2022 23:28:04

Danke, das kam mir auch seltsam vor. Letzt ist es aber umgekehrt: es werden keine Ergebnisse geliefert, obwohl in das Log permanent, sekündlich geschrieben wird.

Update: die Timezone war’s.

Code: Alles auswählen

 cat /mnt/WD1003/logs/sn1.log | awk -v date=`TZ=UTC date --date="2 minutes ago" +'%Y-%m-%dT%H:%M:%S.000Z'` '$1 > date'

Antworten