Log-datei mit Perl auswerten

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Fautzemann
Beiträge: 53
Registriert: 02.12.2011 08:02:33

Log-datei mit Perl auswerten

Beitrag von Fautzemann » 29.10.2012 09:44:11

Mein Problem ist im Grunde Folgendes,

Ich habe einen Apache-Proxy laufen, der fleißig eine log-datei mitschreibt. Diese möchte ich nun mit Perl auswerten. also es sollen die Ip-Adressen und der angefallene Traffic
für jede dieser angezeigt werden.
Mein erster Test war dieser:

#!usr/bin/perl


my $IPPfad = "./access_test.log"; # Der Pfad zu meiner Logdatei
open(FILEHAND,"< $IPPfad") || die("Konnte Datei nicht öffnen. Fehlerbeschreibung: $!"); #Dateihandler wird zum lesen geöffnet, und wenn die Datei nicht geöffnet werden kann wird die Fehlermeldung vom System ausgegeben.
my @fileinhalt = ; # der inhalt der Logdatei wird in das Arrays fileinhalt gelesen und dabe entspricht eine Zeile einem element des Arrays
close(FILEHAND); #Hier wird der Dateihandler wieder geschlossen
foreach $zeile (@fileinhalt) {
@splzeile = split(/\ +/, $zeile); # An " " trennen
print $splzeile[2] . "\n"; # Gibt die Zeile der IP's aus
}
die Proxydatei ist in der Art also eine Zeile davon:
172.16.0.4 - - [14/Feb/2012:14:56:25 +0100] "GET http://www.google.de/ HTTP/1.1" 403 420 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0) Gecko/20100101 Firefox/7.0"
Das Programm soll halt hingehen und die IP mit einer IP in einer CSV datei vergleichen und in eine neue Datei dann den Standort und die Dateigröße ablegen und jedesmal wenn dieser IP-Bereich wieder auftaucht soll aus der anfrage dann die Größe zu dem Standort hinzu addiert werden, und wenn ein neuer IP-Bereich auftaucht soll dieser automatisch in der neuen Datei hinzugefügt werden...
diede "neue Datei" muss später dann aufbereitet werden und in Tabellenform (auch in einer CSV) dargestellt werden.

ich hoffe ihr könnt mir helfen,

hab mich bemüht so ausführlich wie möglich mein Problem zu schildern... ist sehr dringend..

Danke im Voraus

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: Traffic pro IP/User auswerten

Beitrag von Cae » 30.10.2012 01:45:20

Ich ignoriere mal, dass du einen drei Jahre alten Thread ausgräbst, um ein Thema anzufangen, das nur im Randbereich mit dem Topic zu tun hat (Mods: Neuer Thread in Skripting?). Außerdem glaube ich nicht, dass dein Perl-Ding da funktioniert, und mir ist auch erstmal egal, dass du eine einzelne Datei haben willst.

Perl ist da Overkill, das geht prima mit Shell-Mitteln:

Code: Alles auswählen

#/bin/sh

datadir=./data;

cut -d\  -f1 | while read ip dropit; do
	file="$datadir/$ip"
	test -f "$file" && {
		counter="$(cat $file)"; # $(< does not work somehow, even
		echo $((1 + counter)) >"$file"; # in bash
	} || {
		echo 1 >"$file";
	}
done
Das Skript bekommt ein Log vorgesetzt und schreibt für jede IP in der ersten, Leerzeichen-getrennten Spalte des Logs eine Datei in $datadir. Als Dateiname und Schlüssel wird eben dieser Inhalt, also die IP verwenden (aufpassen, besser mit md5sum gegen unerwuenschte Zeichen filtern):

Code: Alles auswählen

$ mkdir data
$ for a in $(seq 0 10); do for b in $(seq 0 10); do echo "10.0.$a.$b fnord blah blubb" >>log; done; done # Testdaten erzeugen
$ ./parse <log # auswerten
Anschließend kann man sich mit die Häufigkeit anschauen:

Code: Alles auswählen

$ cat data/10.0.0.0
3
Hier habe ich offensichtlich ein dreifach langes Log oder drei Durchläufe (kein Reset!) gefahren.

Wie du das Ganze in eine einzelne Datei bekommst, darfst du selbst herausfinden. Arrays werden nützlich sein, die gehen in awk brauchbar, oder auch in der Bash.

Gruß Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

uname
Beiträge: 12406
Registriert: 03.06.2008 09:33:02

Re: Log-datei mit Perl auswerten

Beitrag von uname » 30.10.2012 08:19:50

Also Perl als Lösung finde ich gar nicht so schlecht. Wenn ich es richtig verstanden habe enthält deine Logdatei:

Code: Alles auswählen

ip anzahl
Um damit zu arbeiten musst du bei Perl Hash-Variablen nutzen. Setze in deinem geposteten Ablauf beim Einlesen der Logdatei:

Code: Alles auswählen

$summe{$splzeile[0]}= $splzeile[1];
Wenn nun bei der anderen Datei eine Zeile mit der IP vorbeikommt (Variable sei $ip) wird der Wert wie folgt erhöht:

Code: Alles auswählen

$summme{$ip} = $summe{$ip} + 1;
Wenn nun die Logdatei durch ist kannst du das ganze Zeug wieder ausgeben:

Code: Alles auswählen

foreach $ent (keys %summe)
{
     print $ent . " " . $summe{$ent} . "\n";
}
... ungetestet ...

Suche im Internet nach diesen Codeabschnitten und nach Hash-Variablen bei Perl.

ralfi
Beiträge: 285
Registriert: 02.06.2011 11:16:11
Wohnort: Brandenburg

Re: Log-datei mit Perl auswerten

Beitrag von ralfi » 30.10.2012 08:28:18

Das ist natürlich echt schick, wenn man die Log-Auswertung so 100%tig anpassen kann. IMHO reicht aber auch logcheck / logcheck-database und evtl. noch einige kleine Anpassungen vollkommen aus.
Viele Grüße, ralfi

Niveau sieht von unten oft wie Arroganz aus ...

Benutzeravatar
Fautzemann
Beiträge: 53
Registriert: 02.12.2011 08:02:33

Re: Traffic pro IP/User auswerten

Beitrag von Fautzemann » 05.11.2012 07:56:41

Cae hat geschrieben:Ich ignoriere mal, dass du einen drei Jahre alten Thread ausgräbst, um ein Thema anzufangen, das nur im Randbereich mit dem Topic zu tun hat (Mods: Neuer Thread in Skripting?). Außerdem glaube ich nicht, dass dein Perl-Ding da funktioniert, und mir ist auch erstmal egal, dass du eine einzelne Datei haben willst.

Perl ist da Overkill, das geht prima mit Shell-Mitteln:

Code: Alles auswählen

#/bin/sh

datadir=./data;

cut -d\  -f1 | while read ip dropit; do
	file="$datadir/$ip"
	test -f "$file" && {
		counter="$(cat $file)"; # $(< does not work somehow, even
		echo $((1 + counter)) >"$file"; # in bash
	} || {
		echo 1 >"$file";
	}
done
Das Skript bekommt ein Log vorgesetzt und schreibt für jede IP in der ersten, Leerzeichen-getrennten Spalte des Logs eine Datei in $datadir. Als Dateiname und Schlüssel wird eben dieser Inhalt, also die IP verwenden (aufpassen, besser mit md5sum gegen unerwuenschte Zeichen filtern):

Code: Alles auswählen

$ mkdir data
$ for a in $(seq 0 10); do for b in $(seq 0 10); do echo "10.0.$a.$b fnord blah blubb" >>log; done; done # Testdaten erzeugen
$ ./parse <log # auswerten
Anschließend kann man sich mit die Häufigkeit anschauen:

Code: Alles auswählen

$ cat data/10.0.0.0
3
Hier habe ich offensichtlich ein dreifach langes Log oder drei Durchläufe (kein Reset!) gefahren.

Wie du das Ganze in eine einzelne Datei bekommst, darfst du selbst herausfinden. Arrays werden nützlich sein, die gehen in awk brauchbar, oder auch in der Bash.

Gruß Cae
in anderen foren ist es verboten neue auf zumachen. da bekommt man ständig abmahnungen und somit hab ich es hier gleich richtig machen wollen.

Benutzeravatar
novalix
Beiträge: 1909
Registriert: 05.10.2005 12:32:57
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: elberfeld

Re: Log-datei mit Perl auswerten

Beitrag von novalix » 05.11.2012 11:03:14

ralfi hat geschrieben:Das ist natürlich echt schick, wenn man die Log-Auswertung so 100%tig anpassen kann. IMHO reicht aber auch logcheck / logcheck-database und evtl. noch einige kleine Anpassungen vollkommen aus.
Unterschreib. Debianlogwatch ist eine weitere Möglichkeit. Dann hat man es in Perl.
Da das Format der Logdatei das übliche "combined" des Apache ist, kann man auch so ein nützliches Tool wie Debianvisitors in Anschlag bringen.
Groetjes, niels
Das Wem, Wieviel, Wann, Wozu und Wie zu bestimmen ist aber nicht jedermannns Sache und ist nicht leicht.
Darum ist das Richtige selten, lobenswert und schön.

Benutzeravatar
Fautzemann
Beiträge: 53
Registriert: 02.12.2011 08:02:33

Re: Log-datei mit Perl auswerten

Beitrag von Fautzemann » 06.11.2012 09:14:40

Code: Alles auswählen

#!/usr/bin/perl -w
use strict;
system('clear');
open (IN,"<access.log")|| die "access.log Datei wurde nicht gefunden";
my (%hash,$alt,$neu,$ip,$size,$run,$key,$value,$IP,$T);
foreach $run (<IN>) {
if ($run =~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.*\[\d{2}\/[a-zA-z]{3}\/\d{4}:\d{2}:\d{2}:\d{2}\s[\+|\-]\d{4}\]\s\"GET.*HTTP\/1\.[1|0]\"\s200\s(\d*)\s\".*\".*/) {
	$run =~ s/(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*\[\d{2}\/[a-zA-z]{3}\/\d{4}:\d{2}:\d{2}:\d{2}\s[\+|\-]\d{4}\]\s\"GET.*HTTP\/1\.[1|0]\"\s200\s(\d*)\s\".*\".*/$1+$2/g;
	($ip,$size)=split(/\+/,$run);
	if (exists $hash{$ip}) {
	$alt=$hash{$ip};
	$neu=$alt+$size;
	$hash{$ip}="$neu";
	}
else {
	$hash{$ip}="$size";
	}
	}
     }
close (IN);
open (OUT,">Traffic.csv");
$IP="IP-Adresse";
$T="Traffic";
printf OUT "%-25s %25s\n", $IP, $T;
printf "%-25s %25s\n", $IP, $T;
while (($ip,$size) = each(%hash)) {
	chomp($size);
	$size = $size." byte";
	printf OUT "%-25s %25s\n", $ip, $size;
	printf "%-25s %25s\n", $ip, $size;
	}
close (OUT);
so hab ich es jetz. aber ne ausgabe nach datum wäre noch schön. hat da wer ne idee, die ich das anstell?

MfG

Benutzeravatar
Fautzemann
Beiträge: 53
Registriert: 02.12.2011 08:02:33

Re: Log-datei mit Perl auswerten

Beitrag von Fautzemann » 08.11.2012 08:07:32

so danke für die hilfe. mein proggi is fertig:-)

Code: Alles auswählen

#!/usr/bin/perl -w
use strict;
system('clear');
if (-e "access.log") {
   open (IN,"<access.log")|| die "access.log Datei wurde nicht gefunden";
}
my (%hash,$alt,$neu,$ip,$size,$run,$key,$value,$IP,$T,$date, $tag,$monat, $jahr);
&DATE();
sub DATE {
print "Geben Sie das Datum in Form von  tt.mm.jjjj ein\n";
chomp($date = <STDIN>);
if ($date =~ m/(\d{2})\.(\d{2})\.(\d{4})/) {
   $tag = $1;
   $monat = $2;
   $jahr = $3;
}
else {
   print "Geben sie das Datum im angegebenen Format ein!\n";
   &DATE();
   exit;
}
if ($monat eq "01") {$monat = "Jan"}
if ($monat eq "02") {$monat = "Feb"}
if ($monat eq "03") {$monat = "Mar"}
if ($monat eq "04") {$monat = "Apr"}
if ($monat eq "05") {$monat = "May"}
if ($monat eq "06") {$monat = "Jun"}
if ($monat eq "07") {$monat = "Jul"}
if ($monat eq "08") {$monat = "Aug"}
if ($monat eq "09") {$monat = "Sep"}
if ($monat eq "10") {$monat = "Oct"}
if ($monat eq "11") {$monat = "Nov"}
if ($monat eq "12") {$monat = "Dec"}
print "$tag $monat $jahr\n";
}
foreach $run (<IN>) {
if ($run =~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.*\[$tag\/$monat\/$jahr:\d{2}:\d{2}:\d{2}\s[\+|\-]\d{4}\]\s\"GET.*HTTP\/1\.[1|0]\"\s200\s(\d*)\s\".*\".*/) {
	$run =~ s/(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*\[\d{2}\/[a-zA-z]{3}\/\d{4}:\d{2}:\d{2}:\d{2}\s[\+|\-]\d{4}\]\s\"GET.*HTTP\/1\.[1|0]\"\s200\s(\d*)\s\".*\".*/$1+$2/g;
	($ip,$size)=split(/\+/,$run);
	if (exists $hash{$ip}) {
	$alt=$hash{$ip};
	$neu=$alt+$size;
	$hash{$ip}="$neu";
	}
else {
	$hash{$ip}="$size";
	}
	}
     }
close (IN);
open (OUT,">Traffic.csv");
$IP="IP-Adresse";
$T="Traffic";
printf OUT "%-25s %25s\n", $IP, $T;
printf "%-25s %25s\n", $IP, $T;
while (($ip,$size) = each(%hash)) {
	chomp($size);
	$size = $size." byte";
	printf OUT "%-25s %25s\n", $ip, $size;
	printf "%-25s %25s\n", $ip, $size;
	}
close (OUT);

Antworten