Hallo Leute, ich befasse mich erst seit Neusten mit dem Thema Python.
Mein Ziel ist es ein Logfile zur Auswertung umzuformatieren.
Das ganze funktioniert schon soweit ganz gut, nur ich habe ein Problem das ich das Datum mit der Uhrzeit nicht mitformatiert bekomme.
Das Log hat folgende Einträge.
2019:03:23-00:00:01 hag-fw-ltd-1 ulogd[31638]: id="2001" severity="info" sys="SecureNet" sub="packetfilter" name="Packet dropped" action="drop" fwrule="60002" initf="lag0" outitf="eth6" srcmac="xx:xx:xx:xx:xx:xx" dstmac="xx:xx:xx:xx:xx:xx" srcip="xxx.xxx.xxx.xxx" dstip="xxx.xxx.xxx.xxx" proto="17" length="56" tos="0x00" prec="0x00" ttl="63" srcport="56080" dstport="53"
2019:03:23-00:00:01 hag-fw-ltd-1 ulogd[31638]: id="2002" severity="info" sys="SecureNet" sub="packetfilter" name="Packet accepted" action="accept" fwrule="216" initf="eth1" outitf="lag0" srcmac="xx:xx:xx:xx:xx:xx" dstmac="xx:xx:xx:xx:xx:xx" srcip="xxx.xxx.xxx.xxx" dstip="xxx.xxx.xxx.xxx" proto="6" length="48" tos="0x00" prec="0x00" ttl="247" srcport="17720" dstport="636" tcpflags="SYN"
Das was ich blau markiert habe ist das was mir in dem umformatierten noch fehlt.
Aussehen tut das csv dann wie folgt.
id,severity,sys,sub,name,action,fwrule,initf,srcmac,dstmac,srcip,dstip,proto,length,tos,prec,ttl,srcport,dstport,outitf,tcpflags,info,type,code,app,mark
"2001","info","SecureNet","packetfilter",,"drop","60002","lag0","xx:xx:xx:xx:xx:xx:a5","xx:xx:xx:xx:xx:xx","xxx.xxx.xxx.xxx","xxx.xxx.xxx.xxx","17","56","0x00","0x00","63","56080","53","eth6",,,,,,
"2002","info","SecureNet","packetfilter",,"accept","216","eth1","xx:xx:xx:xx:xx:xx","xx:xx:xx:xx:xx:xx","xxx.xxx.xxx.xxx","xxx.xxx.xxx.xxx","6","48","0x00","0x00","247","17720","636","lag0","SYN",,,
Realisiert habe ich das ganze dann so.
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog
POS = { "id": 1 ,"severity": 2 ,"sys": 3 ,"sub": 4
, "name": 5, "action": 6, "fwrule": 7, "initf": 8
, "srcmac": 9, "dstmac": 10, "srcip": 11, "dstip": 12
, "proto": 13, "length": 14, "tos": 15, "prec": 16
, "ttl": 17, "srcport": 18, "dstport": 19, "outitf": 20
, "tcpflags": 21, "info": 22, "type": 23, "code": 24
, "app": 25, "mark": 26
}
## Example of log file
## 2000:01:06-00:00:02 sophos ulogd[293]: id="2014" severity="info" sys="SecureNet" sub="packetfilter" name="DNS...
## 2000:01:06-00:00:02 sophos ulogd[293]: id="2014" severity="info" sys="SecureNet" sub="packetfilter" name="DNS requ...
# Menü for File select
logfilepath = tkFileDialog.askopenfilename(initialdir = "/media/sf_D_DRIVE/log/packetfilter/",title = "Select file",filetypes = (("log files","*.log"),("all files","*.*")))
logfile = open(logfilepath, "r")
csvfilepath = tkFileDialog.asksaveasfilename(initialdir = "/media/sf_D_DRIVE/log/",title = "Select file",filetypes = (("csv files","*.csv"),("all files","*.*")))
csvfile = open(csvfilepath, 'w')
# Print headers in file
k = [""] * len(POS)
for key, value in POS.items():
k[value - 1] = key
csvfile.writelines([",".join(k),'\n'])
# Print contet
for line in logfile:
k = [""] * len(POS)
for m in re.finditer(r'(\w+=\")((\w+)|((\w+:\w+)+)|((\w+\.)+\w+))\"', line):
key = re.search(r'\w+=\"', m.group()).group(0).replace('="', '')
value = re.search(r'\"((\w+)|((\w+:\w+)+)|((\w+\.)+\w+))\"', m.group()).group(0).replace('"', '')
k[POS.get(key) - 1] = '"' + value + '"'
csvfile.writelines([",".join(k),'\n'])
Könnt ihr mir bitte dort einmal helfen?
Danke und Gruß
Oerni
Logfile zu csv konvertieren
- __blackjack__
- User
- Beiträge: 14040
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@oerni: Sternchen-Importe sind Böse™. Gerade bei `Tkinter` holt man sich so Unmengen an Namen ins Moduk, von denen nur ein kleiner Bruchteil verwendet wird. Es ist so nicht mehr leicht nachvollziehbar was woher kommt. Das Du `re` zum Beispiel einfach so verwenden kannst ohne es zu importieren ist eher Zufall, denn nirgends ist garantiert, dass man dieses Modul über den Umweg über `Tkinter` bekommen kann. Soweit ich das sehe hast Du diesen Sternchen-Import tatsächlich *nur* um `re` zu importieren. 
`Tkinter` wird dann noch einmal importiert, aber genau wie `Tkconstants` überhaupt nicht verwendet.
Neue Projekte sollte man eher nicht mehr mit Python 2 anfangen. https://pythonclock.org/
Die Definition von `POS` enthält viel unnötige und damit fehleranfällige Schreibarbeit. Man könnte das Wörterbuch auch einfach aus einer Liste mit den Schlüsseln erstellen und sich das tippen von jedem Wert damit sparen.
Bei der Verwendung der Werte aus diesem Wörterbuch wird auch grundsätzlich 1 abgezogen. Warum also nicht gleich die richtigen Werte speichern, statt sie nach jedem Zugriff anpassen?
Wenn man für das erstellen der CSV-Datei einen `DictWriter` aus dem `csv`-Modul verwendet, kann man sich das Wörterbuch auch ganz sparen.
Die Dateidialoge können vom Benutzer auch abgebrochen werden, man sollte also prüfen ob tatsächlich Pfade ausgewählt wurden, bevor man die Datei(en) öffnet.
Dateien die man öffnet, sollte man auch wieder schliessen. Dazu lohnt ein Blick auf das ``with``-Schlüsselwort.
Die Suche mit regulären Ausrücken in den regulären Ausrücken sieht unnötig umständlich aus. Die Schlüssel/Wert-Paare lassen sich mit *einem* Ausdruck erkennen. Und ich würde das Datum damit auch nicht vermischen sondern extra parsen. Das geht ja auch ohne regulären Ausdruck und wirklich *suchen* muss man das Datum am *Anfang* ja auch nicht.
Ungetestet:

`Tkinter` wird dann noch einmal importiert, aber genau wie `Tkconstants` überhaupt nicht verwendet.
Neue Projekte sollte man eher nicht mehr mit Python 2 anfangen. https://pythonclock.org/
Die Definition von `POS` enthält viel unnötige und damit fehleranfällige Schreibarbeit. Man könnte das Wörterbuch auch einfach aus einer Liste mit den Schlüsseln erstellen und sich das tippen von jedem Wert damit sparen.
Bei der Verwendung der Werte aus diesem Wörterbuch wird auch grundsätzlich 1 abgezogen. Warum also nicht gleich die richtigen Werte speichern, statt sie nach jedem Zugriff anpassen?
Wenn man für das erstellen der CSV-Datei einen `DictWriter` aus dem `csv`-Modul verwendet, kann man sich das Wörterbuch auch ganz sparen.
Die Dateidialoge können vom Benutzer auch abgebrochen werden, man sollte also prüfen ob tatsächlich Pfade ausgewählt wurden, bevor man die Datei(en) öffnet.
Dateien die man öffnet, sollte man auch wieder schliessen. Dazu lohnt ein Blick auf das ``with``-Schlüsselwort.
Die Suche mit regulären Ausrücken in den regulären Ausrücken sieht unnötig umständlich aus. Die Schlüssel/Wert-Paare lassen sich mit *einem* Ausdruck erkennen. Und ich würde das Datum damit auch nicht vermischen sondern extra parsen. Das geht ja auch ohne regulären Ausdruck und wirklich *suchen* muss man das Datum am *Anfang* ja auch nicht.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function
import csv
import re
import tkFileDialog
HEADERS = [
'timestamp', 'id', 'severity', 'sys', 'sub', 'name', 'action', 'fwrule',
'initf', 'srcmac', 'dstmac', 'srcip', 'dstip', 'proto', 'length', 'tos',
'prec', 'ttl', 'srcport', 'dstport', 'outitf', 'tcpflags', 'info', 'type',
'code', 'app', 'mark',
]
KEY_VALUE_RE = re.compile(r'(?P<key>\w+)=\"(?P<value>[^"]*)\"')
def main():
log_file_path = tkFileDialog.askopenfilename(
initialdir='/media/sf_D_DRIVE/log/packetfilter/',
title='Select file',
filetypes=(('log files', '*.log'), ('all files', '*.*')),
)
csv_file_path = tkFileDialog.asksaveasfilename(
initialdir='/media/sf_D_DRIVE/log/',
title='Select file',
filetypes=(('csv files', '*.csv'), ('all files', '*.*')),
)
if log_file_path and csv_file_path:
with open(log_file_path, 'r') as log_file:
with open(csv_file_path, 'wb') as csv_file:
writer = csv.DictWriter(csv_file, HEADERS)
writer.writeheader()
for line in log_file:
row = {
match.group('key'): match.group('value')
for match in KEY_VALUE_RE.finditer(line)
}
row['timestamp'] = line[:19]
writer.writerow(row)
if __name__ == '__main__':
main()
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.