Eingabedatei
Mar 19 06:10:16 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:00:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
Mar 19 14:41:26 ip-172-2-0-53 sendmail[29483]: v2JLfNFN029481: to=<[email protected]>,<[email protected]>, delay=00:00:03, xdelay=00:00:03, mailer=esmtp, pri=151738, relay=ifaded-com.mail.p...ction.outlook.com. [xx.xxx.x.x], dsn=2.0.0, stat=Sent (<[email protected]> [InternalId=31288836753166, Hostname=ERGsDGddssdD5.namprd07.prod.outlook.com] 8924 bytes in 0.309, 28.142 KB/sec Queued mail for delivery)
Mar 19 06:10:26 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:20:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
Ich habe folgenden Befehl versucht
cat logh.txt | grep -E -o " delay=.[^,]*|^[^ip]+"
ich möchte die 5 häufigsten Verzögerungszeiten mit Datum herausfinden. Wie kann ich dieses Problem mit dem Linux-Befehl lösen? Ich erhalte folgende Ausgabe
Mar 19 06:10:16
delay=00:00:15
Mar 19 14:41:26
delay=00:00:03
Mar 19 06:10:26
delay=00:20:15
Gewünschte Ausgabe
Mar 19 06:10:26 delay=00:20:15
Mar 19 06:10:16 delay=00:00:15
Mar 19 14:41:26 delay=00:00:03
Antwort1
Sie benötigen mehrere Durchläufe. Hier ist eine Lösung, die sed
, sort
, head
und verwendet cut
, um Ihnen die Top 5 in der gewünschten Reihenfolge anzuzeigen.
sed -e 's/^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*/\4\5\6 \1 \3/' | sort -nr | head -n5 | cut -d\ -f2-
Mit Ihrer Eingabe wird Folgendes ausgegeben:
Mar 19 06:10:26 delay=00:20:15
Mar 19 06:10:16 delay=00:00:15
Mar 19 14:41:26 delay=00:00:03
(Setzt voraus, dass die Eingabe im von Ihnen angegebenen Protokollformat erfolgt und nur Zeilen mit den gewünschten Daten bereitgestellt werden. Möglicherweise ist ein zusätzliches Grep am Anfang erforderlich.)
Was es tut
Lassen Sie es uns aufschlüsseln.
sed
sed
steht für Stream EDitor. Es wird routinemäßig zum Anwenden regulärer Ausdrücke auf Textströme verwendet.
seds regulärer Ausdruck
's/^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*/\4\5\6 \1 \3/'
Das ist ein ganz schöner Brocken, aber das muss es auch sein, um zu vermeiden,katastrophales Zurückweichen.
Wir verwenden Regex-Ersetzungen. Um zu sehen, was das im Detail bewirkt,Versuchen Sie Regex101. Für den Moment müssen Sie wissen, dass die Eingabe folgende ist:
Mar 19 06:10:16 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:00:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
Mar 19 14:41:26 ip-172-2-0-53 sendmail[29483]: v2JLfNFN029481: to=<[email protected]>,<[email protected]>, delay=00:00:03, xdelay=00:00:03, mailer=esmtp, pri=151738, relay=ifaded-com.mail.p...ction.outlook.com. [xx.xxx.x.x], dsn=2.0.0, stat=Sent (<[email protected]> [InternalId=31288836753166, Hostname=FOOBAR1.namprd07.prod.outlook.com] 8924 bytes in 0.309, 28.142 KB/sec Queued mail for delivery)
Mar 19 06:10:26 ip-172-2-0-53 sendmail[28131]: v2JDA1k4028131: to=root, ctladdr=root (0/0), delay=00:20:15, xdelay=00:00:00, mailer=relay, pri=30580, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (v2JDAG5W028134 Message accepted for delivery)
und konvertiert es in
000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03
002015 Mar 19 06:10:26 delay=00:20:15
sed Regex-Übereinstimmung
^\([A-Za-z]\{3\} \{1,2\}[0-9]\{1,2\} \{1,2\}\([0-9]\{2\}:\)\{2\}[0-9]\{2\}\).* \(delay=\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\).*
Wir gleichen zunächst die Datumskomponenten explizit ab; diese benötigen wir später für die Ausgabe. Anschließend suchen und gleichen wir die Verzögerung und ihre Zeitkomponenten einzeln ab; die Verzögerung, die Sie in Ihrer Ausgabe haben wollten. Die Zeitkomponenten benötigen wir später zum Sortieren.
seds Regex-Ersetzung
\4\5\6 \1 \3
Auf der Ersetzungsseite des regulären Ausdrucks nehmen wir die Zeitkomponenten, die wir erfasst haben, und verketten sie ohne das Trennzeichen „:“, das sie ursprünglich hatten. Das ist wichtig, da wir diese später verwenden werden sort
. Nach den Zeitkomponenten hängen wir die Datumszeichenfolge und die gesamte ursprüngliche Verzögerungszeichenfolge an; wir werden sie nach dem Sortieren benötigen.
Sortieren
sort -nr
Da unsere Eingabe jetzt mit einer Dezimalzahl statt mit einem Zeichenfolge-Zeitstempel beginnt, können wir sort
den mit der Flagge angegebenen numerischen Modus verwenden -n
.
Standardmäßig sort
wird in aufsteigender Reihenfolge sortiert, wobei die größten Werte am Ende stehen. Da dies bedeuten würde, dassalleder sort
Ausgabe, um die größten N-Werte zu finden, verwenden wir das Flag von sort, -r
um die Ausgabereihenfolge umzukehren. Jetzt werden die größten Werte zuerst ausgegeben und wir können head
anstelle von „tail“ verwenden.
Unsere Ausgabe sieht an diesem Punkt folgendermaßen aus:
002015 Mar 19 06:10:26 delay=00:20:15
000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03
Kopf
head -n5
An diesem Punkt enthält unsere Eingabe zuerst die größten Werte und wir wissen bereits, dass wir die größten 5 Werte möchten. Daher verwenden wir head
den -n
Parameter , um anzugeben, head
wie viele Werte wir möchten.
Da wir in diesem Beispiel tatsächlich nicht mehr als 5 Werte haben, erhalten wir trotzdem die gesamte Ausgabe, die uns eingegeben wurde.
002015 Mar 19 06:10:26 delay=00:20:15
000015 Mar 19 06:10:16 delay=00:00:15
000003 Mar 19 14:41:26 delay=00:00:03
schneiden
cut -d\ -f2-
Da wir ihn nicht mehr benötigen, müssen wir den numerischen Sortierschlüssel entfernen, den wir sed
im ersten Schritt mit eingefügt haben. Dazu verwenden wir cut
, wodurch wir auswählen können, welche Felder wir aus jeder bereitgestellten Zeile benötigen.
Wir verwenden den Parameter von cut, -d
um ihm mitzuteilen, was unser Feldtrennzeichen, unser Trennzeichen, ist. Da das Feldtrennzeichen ein Leerzeichen ist, müssen wir es mit maskieren \
, was uns gibt -d\
.
Aus cut
der Sicht von wird die Zeile dadurch 002015 Mar 19 06:10:26 delay=00:20:15
in unterteilt 002015
Mar
19
06:10:26
delay=00:20:15
.
Um anzugeben, welche Felder wir möchten, verwenden wir -f
. Da wir alle Felder außer dem ersten möchten, verwenden wir -f2-
, wodurch wir die gewünschte Ausgabe erhalten:
Mar 19 06:10:26 delay=00:20:15
Mar 19 06:10:16 delay=00:00:15
Mar 19 14:41:26 delay=00:00:03
Antwort2
perl -lane '
print join $", /\sdelay=\K(\S+)(?=,)/, splice(@F, 0, 3), /\s\K(delay=\S+)(?=,)/;
' | sort -t: -k 1,1nr -k 2,2nr -k 3,3nr | cut -d\ -f2- | head -n 5