So analysieren Sie eine mehrzeilige Protokolldatei in awk und geben nur eine Zeile mit der zuletzt bekannten IP-Adresse aus

0

Ich stecke fest und suche Hilfe. Ich möchte ein Ereignis auslösen, das ich mit einem Bash-Skript weiterverarbeiten möchte. Die Daten werden aus einer Protokolldatei abgerufen. Bevor ich zu erklären beginne, zeige ich Ihnen einige Zeilen dieser bestimmten Protokolldatei zum besseren Verständnis.

Wie es aussieht

test.log

[...]
24/04/2017 20:14:29 [7910] [INFO] [bob] method = 'POST' from = '192.168.0.163' getUser = 'bob' einige andere Spalten
24/04/2017 20:14:34 [10355] [INFO] [bob] method = 'POST' from = '192.168.0.163' getUser = 'bob' einige andere Spalten
24/04/2017 20:14:38 [10355] [INFO] [bob] Eingehende '1'-Änderungen verarbeitet
24/04/2017 20:14:47 [22518] [INFO] [bob] method = 'POST' from = '192.168.0.163' getUser = 'bob' einige andere Spalten
24/04/2017 20:14:50 [7910] [INFO] [bob] method = 'POST' from = '192.168.0.163' getUser = 'bob' einige andere Spalten
24/04/2017 20:14:53 [7910] [INFO] [bob] Eingehende '1'-Änderungen verarbeitet
24/04/2017 20:15:08 [10355] [INFO] [bob] method = 'POST' from = '192.168.0.151' getUser = 'bob' einige andere Spalten
24/04/2017 20:15:14 [22518] [INFO] [bob] method = 'POST' from = '192.168.0.151' cmd = 'Suche' getUser = 'bob' einige andere Spalten
24/04/2017 20:15:15 [7910] [INFO] [bob] method = 'POST' from = '192.168.0.151' getUser = 'bob' einige andere Spalten
24/04/2017 20:15:16 [10355] [INFO] [bob] method = 'POST' from = '192.168.0.151' cmd = 'Search' getUser = 'bob' einige andere Spalten
24/04/2017 20:15:49 [32637] [INFO] [bob] method = 'POST' from = '192.168.0.163' getUser = 'bob' einige andere Spalten
24/04/2017 20:15:53 ​​[22518] [INFO] [bob] method = 'POST' from = '192.168.0.163' getUser = 'bob' einige andere Spalten
24/04/2017 20:15:56 [22518] [INFO] [bob] Eingehende '1'-Änderungen verarbeitet
24/04/2017 20:16:05 [10355] [INFO] [bob] method = 'POST' from = '192.168.0.151' getUser = 'bob' einige andere Spalten
24/04/2017 20:16:09 [32637] [INFO] [bob] method = 'POST' from = '192.168.0.151' getUser = 'bob' einige andere Spalten
01/05/2017 03:27:45 [4985] [INFO] [alice] method = 'POST' from = '192.168.0.153' getUser = 'alice' einige andere Spalten
01/05/2017 03:27:49 [13971] [INFO] [alice] method = 'POST' from = '192.168.0.153' getUser = 'alice' einige andere Spalten
01/05/2017 03:28:05 [13970] [INFO] [alice] method = 'POST' from = '192.168.0.153' getUser = 'alice' einige andere Spalten
01/05/2017 03:28:10 [4985] [INFO] [alice] method = 'POST' from = '192.168.0.153' getUser = 'alice' einige andere Spalten
01/05/2017 03:28:25 [13971] [INFO] [alice] method = 'POST' from = '192.168.0.153' getUser = 'alice' einige andere Spalten
01/05/2017 03:28:31 [13970] [INFO] [alice] method = 'POST' from = '192.168.0.153' getUser = 'alice' einige andere Spalten
15/03/2018 14:49:19 [12918] [INFO] [alice] method = 'POST' from = '192.168.0.171' getUser = 'alice' einige andere Spalten
15/03/2018 14:49:21 [12834] [INFO] [alice] method = 'POST' from = '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' from = '192.168.0.166' getUser = 'bob' einige andere Spalten
15/03/2018 14:55:26 [12918] [INFO] [bob] method = 'POST' from = '192.168.0.166' getUser = 'bob' einige andere Spalten
15/03/2018 14:55:26 [12882] [INFO] [bob] method = 'POST' from = '192.168.0.166' getUser = 'bob' einige andere Spalten
15/03/2018 14:55:27 [12970] [INFO] [bob] method = 'POST' from = '192.168.0.166' getUser = 'bob' einige andere Spalten
15/03/2018 14:55:28 [12882] [INFO] [bob] method = 'POST' from = '192.168.0.166' getUser = 'bob' einige andere Spalten
15/03/2018 14:55:28 [12918] [INFO] [bob] method = 'POST' from = '192.168.0.166' getUser = 'bob' einige andere Spalten
15/03/2018 14:55:32 [12970] [INFO] [bob] method = 'POST' from = '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 möchte den Benutzernamen (in diesem Beispiel "alice" oder "bob") aus der Protokolldatei in der 5. Spalte und der entsprechenden IP-Adresse in der 7. Spalte abrufen. Falls die IP-Adresse vom letzten Status abweicht, sollte eine E-Mail-Benachrichtigung über ein kleines Bash-Skript gesendet werden.

Die Bedingung sollte sein:

  • Wenn die Zeile "Alice" ODER "Bob" enthält UND die Zeile "From =" enthält, geben Sie den Benutzernamen und die entsprechende IP-Adresse aus.

Die endgültige Ausgabe sollte so aussehen

bob 192.168.0.166
alice 192.168.0.171

Hinweis: Es wird nur die letzte bekannte IP-Adresse benötigt, daher sollte die Ausgabe in diesem Beispiel wie oben gezeigt nur 2 Zeilen erzeugen (eine für jeden Benutzer).

Was ich bisher versucht habe

Ich habe mit awk angefangen, war aber schnell mit einer Hürde konfrontiert, da awk standardmäßig Leerzeichen als Feldtrennzeichen verwendet. Meine Absicht war es, mit einer Anweisung '{print $ 4, $ 6}' zu beginnen. Ich habe festgestellt, dass die dritte Spalte diese Filterung manchmal aufgrund eines führenden Leerzeichens in der Prozess-ID unterbricht, z

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

Wie mein awk-Befehl derzeit aussieht

Mit folgendem Befehl suche ich den String "Alice" ODER "Bob" UND den String "From =" und erstelle 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 stecke hier fest. Ich habe versucht, herumzuspielen, indem ich die letzte bekannte Zeile in einer Variablen gespeichert und "{a = $ 0}" ausgegeben habe, aber offensichtlich mache ich etwas falsch, weil ich entweder Fehler bekomme oder die Ausgabe falsch ist. Meine nächste Idee war, "tac" zu verwenden und die Protokolldatei von ihrem Ende an zu lesen und nach dem ersten Match zu beenden. Sowas in der Art:

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

Dies hört jedoch sofort nach dem ersten Spiel auf und die Ausgabe ist:

bob] from = '192.168.0.166'

Ich muss die Ausgabe zusätzlich formatieren, indem ich die rechte Klammer ']' und die Zeichenfolge 'from =' und die einfachen Anführungszeichen um die IP-Adresse entferne.

Jede Hilfe sehr geschätzt. Danke im Voraus.

user882786
quelle

Antworten:

0

Sie können Ihre regex Feldtrenn aufzunehmen erweitern ]und 'und dann werden Sie den Namen und sauber in den Feldern 5 IP und 9. Sie können diese in einem assoziativen Array mit dem Namen indiziert speichern, und die letzte IP - Adresse zu halten. Am Ende der Datei drucken Sie dieses Array.

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

Hallo meuh und vielen dank für deinen vorschlag mit beispiel. Das funktioniert ganz gut. Aber ich frage mich immer noch, ob es nicht besser wäre, die Verarbeitung umzukehren und am Ende der Datei mit dem Lesen zu beginnen. In diesem Fall verbraucht die zu lesende Protokolldatei viel Rechenleistung, wenn sie Tausende Zeilen umfasst. Ich denke, es wäre effektiver in Bezug auf die Leistung, mit dem Lesen am Schwanz zu beginnen und nach dem ersten Spiel für jeden Benutzer anzuhalten.

Andererseits frage ich mich, ob es möglich ist, mein gesamtes Projekt als Einzeiler in awk aufzunehmen.

Ziel ist es, 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 bekannte ist und das IP-Subnetz nicht in Subnetz-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 erreichen soll. Muss ich eine Flag-Datei berühren, in der ich die aktuelle IP-Adresse jedes Benutzers speichere und diese dann irgendwie später abfrage? Kann man in awk alles machen?

user882786
quelle