So analysieren Sie die Protokolldatei mit mehreren Zeilen in awk und geben Sie nur eine Zeile mit der letzten bekannten IP-Adresse aus

849
user882786

Ich bin festgefahren und suche Hilfe. Ich möchte ein Ereignis auslösen, das ich durch ein Bash-Skript weiter verarbeiten möchte. Die Daten werden aus einer Protokolldatei abgerufen. Bevor ich anfange zu erklären, zeige ich Ihnen einige Zeilen dieser Protokolldatei zum besseren Verständnis.

Wie es aussieht

test.log

[...] 24/04/2017 20:14:29 [7910] [INFO] [bob] method = 'POST' von = '192.168.0.163' getUser = 'bob' einige andere Spalten 24/04/2017 20:14:34 [10355] [INFO] [bob] method = 'POST' von = '192.168.0.163' getUser = 'bob' einige andere Spalten 24/04/2017 20:14:38 [10355] [INFO] [Bob] Verarbeitete '1' eingehende Änderungen 24/04/2017 20:14:47 [22518] [INFO] [bob] method = 'POST' von = '192.168.0.163' getUser = 'bob' einige andere Spalten 24/04/2017 20:14:50 [7910] [INFO] [bob] method = 'POST' von = '192.168.0.163' getUser = 'bob' einige andere Spalten 24/04/2017 20:14:53 [7910] [INFO] [Bob] Verarbeitete '1' eingehende Änderungen 24/04/2017 20:15:08 [10355] [INFO] [bob] method = 'POST' von = '192.168.0.151' getUser = 'bob' einige andere Spalten 24/04/2017 20:15:14 [22518] [INFO] [bob] method = 'POST' von = '192.168.0.151' cmd = 'Search' getUser = 'bob' einige andere Spalten 24/04/2017 20:15:15 [7910] [INFO] [bob] method = 'POST' von = '192.168.0.151' getUser = 'bob' einige andere Spalten 24/04/2017 20:15:16 [10355] [INFO] [bob] method = 'POST' von = '192.168.0.151' cmd = 'Search' getUser = 'bob' einige andere Spalten 24/04/2017 20:15:49 [32637] [INFO] [bob] method = 'POST' von = '192.168.0.163' getUser = 'bob' einige andere Spalten 24/04/2017 20:15:53 ​​[22518] [INFO] [bob] method = 'POST' von = '192.168.0.163' getUser = 'bob' einige andere Spalten 24/04/2017 20:15:56 [22518] [INFO] [Bob] Verarbeitete '1' eingehende Änderungen 24/04/2017 20:16:05 [10355] [INFO] [bob] method = 'POST' von = '192.168.0.151' getUser = 'bob' einige andere Spalten 24/04/2017 20:16:09 [32637] [INFO] [bob] method = 'POST' von = '192.168.0.151' getUser = 'bob' einige andere Spalten 01/05/2017 03:27:45 [4985] [INFO] [alice] method = 'POST' von = '192.168.0.153' getUser = 'alice' einige andere Spalten 01/05/2017 03:27:49 [13971] [INFO] [alice] method = 'POST' von = '192.168.0.153' getUser = 'alice' einige andere Spalten 01/05/2017 03:28:05 [13970] [INFO] [alice] method = 'POST' von = '192.168.0.153' getUser = 'alice' einige andere Spalten 01/05/2017 03:28:10 [4985] [INFO] [alice] method = 'POST' von = '192.168.0.153' getUser = 'alice' einige andere Spalten 01/05/2017 03:28:25 [13971] [INFO] [alice] method = 'POST' von = '192.168.0.153' getUser = 'alice' einige andere Spalten 01/05/2017 03:28:31 [13970] [INFO] [alice] method = 'POST' von = '192.168.0.153' getUser = 'alice' einige andere Spalten 15/03/2018 14:49:19 [12918] [INFO] [alice] method = 'POST' von = '192.168.0.171' getUser = 'alice' einige andere Spalten 15/03/2018 14:49:21 [12834] [INFO] [alice] method = 'POST' von = '192.168.0.171' getUser = 'alice' einige andere Spalten 15/03/2018 14:49:22 [12834] [INFO] [alice] SyncCollections-> CheckForChanges (): Warten auf Speicheränderungen ... (Lebensdauer 470 Sekunden) 15/03/2018 14:55:26 [12843] [INFO] [bob] method = 'POST' von = '192.168.0.166' getUser = 'bob' einige andere Spalten 15/03/2018 14:55:26 [12918] [INFO] [bob] method = 'POST' von = '192.168.0.166' getUser = 'bob' einige andere Spalten 15/03/2018 14:55:26 [12882] [INFO] [bob] method = 'POST' von = '192.168.0.166' getUser = 'bob' einige andere Spalten 15/03/2018 14:55:27 [12970] [INFO] [bob] method = 'POST' von = '192.168.0.166' getUser = 'bob' einige andere Spalten 15/03/2018 14:55:28 [12882] [INFO] [bob] method = 'POST' von = '192.168.0.166' getUser = 'bob' einige andere Spalten 15/03/2018 14:55:28 [12918] [INFO] [bob] method = 'POST' von = '192.168.0.166' getUser = 'bob' einige andere Spalten 15/03/2018 14:55:32 [12970] [INFO] [bob] method = 'POST' von = '192.168.0.166' getUser = 'bob' einige andere Spalten 15/03/2018 14:55:32 [12970] [INFO] [Bob] SyncCollections-> CheckForChanges (): Warten auf Speicheränderungen ... (Lebensdauer 470 Sekunden) [...] 

Tor

Ich bin daran interessiert, den Benutzernamen (in diesem Beispiel "alice" oder "bob") aus der Protokolldatei, die in der 5. Spalte angezeigt wird, und der entsprechenden IP-Adresse, die in der 7. Spalte aufgeführt ist, abzurufen. Falls sich die IP-Adresse vom letzten Status unterscheidet, sollte eine E-Mail-Benachrichtigung über ein kleines Bash-Skript gesendet werden.

Die Bedingung sollte sein:

  • Wenn die Zeile "alice" ODER "bob" UND die Zeile "from =" enthält, geben Sie den Benutzernamen und die entsprechende IP-Adresse aus.

Die endgültige Ausgabe sollte aussehen

Bob 192.168.0.166 alice 192.168.0.171 

Hinweis: Es wird nur die letzte bekannte IP-Adresse gewünscht, daher sollte die Ausgabe in diesem Beispiel nur richtig 2 Zeilen erzeugen (eine für jeden Benutzer).

Was ich bisher ausprobiert habe

Ich habe mit awk angefangen, bin aber schnell einer Hürde begegnet, weil awk standardmäßig Leerzeichen als Feldtrennzeichen verwendet. Meine Absicht war es, mit einer Anweisung '' zu beginnen. Ich erkannte, dass die dritte Spalte diese Filterung manchmal aufgrund eines führenden Leerzeichens in der Prozess-ID aufhebt, z

24/04/2017 20:14:50 [7910] ... 

Wie mein awk-Befehl aktuell aussieht

Mit folgendem Befehl suche ich nach dem String "alice" OR "bob" UND dem String "from =" und generiere dann eine Ausgabe von zwei unformatierten Spalten

awk 'BEGIN { FS = "[?!([ )]+" } /alice|bob/ && /from=/ { print $5,$7 }' test.log

Ausgabe ->

bob] from = '192.168.0.163' bob] from = '192.168.0.163' bob] from = '192.168.0.163' bob] from = '192.168.0.163' bob] from = '192.168.0.151' bob] from = '192.168.0.151' bob] from = '192.168.0.151' bob] from = '192.168.0.151' bob] from = '192.168.0.163' bob] from = '192.168.0.163' bob] from = '192.168.0.151' bob] from = '192.168.0.151' alice] from = '192.168.0.153' alice] from = '192.168.0.153' alice] from = '192.168.0.153' alice] from = '192.168.0.153' alice] from = '192.168.0.153' alice] from = '192.168.0.153' alice] from = '192.168.0.171' alice] from = '192.168.0.171' bob] from = '192.168.0.166' bob] from = '192.168.0.166' bob] from = '192.168.0.166' bob] from = '192.168.0.166' bob] from = '192.168.0.166' bob] from = '192.168.0.166' bob] from = '192.168.0.166' 

Ich bin hier festgefahren. Ich habe versucht, herumzuspielen, indem ich die letzte bekannte Zeile in einer Variablen abspeichere und "" ausgab, aber offensichtlich mache ich etwas falsch, weil ich entweder Fehler bekomme oder die Ausgabe falsch ist. Meine nächste Idee war, "tac" zu verwenden, die Logdatei von ihrem Ende aus zu lesen und nach dem ersten Match zu beenden. Sowas in der Art:

tac test.txt | awk 'BEGIN / alice | bob / && / from = / ' 

Dies hört jedoch sofort nach dem ersten Spiel auf und es wird ausgegeben:

bob] from = '192.168.0.166' 

Ich brauche zusätzlich eine Formatierung für die Ausgabe, indem ich die rechte Klammer ']' und die Zeichenfolge 'from =' und die einzelnen Anführungszeichen um die IP-Adresse streife.

Jede Hilfe hat wirklich geschätzt. Danke im Voraus.

0

2 Antworten auf die Frage

0
meuh

Sie können Ihr Regex-Feldtrennzeichen durch einschließen erweitern, ]und 'Sie erhalten dann den Namen und die IP-Adresse in den Feldern 5 und 9 sauber. Sie können diese in einem assoziativen Array speichern, das durch den Namen indiziert ist und die letzte IP-Adresse enthält. Am Ende der Datei drucken Sie dieses Array aus.

awk 'BEGIN { FS = "[?!([ )\\]'\'']+" } /alice|bob/ && /from=/ {  user = $5; ip = $9; userip[user] = ip } END{ for(user in userip)print user,userip[user] }' 
0
user882786

Hallo meuh und vielen Dank für deinen Vorschlag mit Beispiel. Das funktioniert ziemlich gut. Aber ich frage mich immer noch, ob es nicht besser wäre, die Verarbeitung rückgängig zu machen und am Ende der Datei zu lesen. Wenn in diesem Fall die zu lesende Protokolldatei Tausende Zeilen enthält, verbraucht sie viel Rechenleistung. Ich denke, es wäre effektiver, wenn Sie mit dem Lesen beginnen und nach dem ersten Match für jeden Benutzer stoppen.

Andererseits frage ich mich, ob es möglich ist, mein gesamtes Projekt als One-Liner in awk zu integrieren.

Das Ziel ist, jede Minute einen Cron-Job auszuführen und die Protokolldatei zu lesen. Wenn sich die IP-Adresse geändert hat und neuer als die letzte ist und das IP-Subnetz nicht in Subnet-C (LAN) liegt, sollte die E-Mail-Benachrichtigung gesendet werden.

/etc/cron.d/access-audit.log

*/1 * * * * root nice -n5 /usr/bin/awk 'BEGIN { FS = "[?!([ )\]'\'']+" } /alice|bob/ && /from=/ { user = $5; ip = $9; userip[user] = ip } END{ for(user in userip)print user,userip[user] }' | ...

Ich weiß nicht, wie ich das schaffen soll. Muss ich eine Flag-Datei berühren, in der ich die aktuelle IP-Adresse jedes Benutzers speichere, und diese dann irgendwie abfragen? Kann man alles in awk machen?