Zum Inhalt springen

Apache/11 Logging/Benutzerdefiniert

Aus Foxwiki

Beschreibung

Benutzerdefinierte Debug-Log-Meldungen

In Apache 2.3.14-beta wurde das Modul mod_log_debug hinzugefügt. Es ermöglicht die gezielte Ausgabe benutzerdefinierter Meldungen ins ErrorLog, optional unter einer bestimmten Bedingung. Damit lässt sich beispielsweise prüfen, ob und wann bestimmte Zweige der Konfiguration überhaupt gelesen werden oder ob bestimmte Bedingungen jemals eintreffen. Das Modul stellt nur eine Direktive bereit: LogMessage

LogMessage

Eine Debug-Log-Meldung ins ErrorLog schreiben

Seit Version 2.3.14
Modul mod_log_debug
Kontext <Directory>
Syntax LogMessage Meldung [hook=Hook] [if=Ausdruck]
Standardwert nicht gesetzt

Wenn diese Direktive interpretiert wird, schreibt Apache einen frei definierbaren Meldungstext in die ErrorLog-Datei. Der Meldungstext selbst kann Ausdrücke in der ap_expr-Syntax enthalten, die in Kapitel 6, »Grundkonfiguration«, im Zusammenhang mit den Direktiven <If>, <ElseIf> und <Else> beschrieben wurde. Das LogLevel der Meldungen ist info

Optional können Sie mit hook=Hook einen der folgenden Hooks angeben; dies bestimmt, in welcher Phase der Anfrage-Verarbeitung die Meldung geschrieben wird – und damit indirekt, welche Variablen und Ausdrücke zu diesem Zeitpunkt überhaupt verfügbar sind

  • translate_name
  • type_checker
  • quick_handler
  • map_to_storage
  • check_access
  • check_access_ex
  • insert_filter
  • check_authn
  • check_authz
  • fixups
  • handler
  • log_transaction

Die Bedeutung der einzelnen Hooks wird in Kapitel 17, »Apache erweitern«, beschrieben. Wenn Sie keinen Hook angeben, wird log_transaction verwendet

Wenn Sie ein Argument vom Typ if=Ausdruck hinzufügen, wird die Meldung nur protokolliert, falls der Ausdruck zutrifft. Die Syntax dieses Ausdrucks entspricht ebenfalls ap_expr

Das folgende Beispiel gibt immer dann eine Log-Meldung aus, wenn der URLPfad /check/ angefordert wird

<Location /check/>
 LogMessage "URL-Pfad /check/ angefordert."
</Location>

Hier ein weiteres Beispiel, das nur für Unterabfragen auf /check/ ausgeführt wird (hier muss explizit ein Hook angegeben werden, da log_transaction bei Unterabfragen nicht ausgeführt wird)

<Location /check/>
 LogMessage "URL-Pfad /check/ in Unterabfrage angefordert." \
 hook=type_checker if=%{IS_SUBREQ}
</Location>

11.2 Auswertung von Log-Dateien

Log-Dateien sind ein sehr wichtiges und praktisches Hilfsmittel. Allerdings nützen sie nur dann wirklich etwas, wenn sie effizient ausgewertet werden können Deshalb werden hier kurz die mit Apache mitgelieferten und darüber hinaus

einige externe Tools vorgestellt. Wenn Sie wissen möchten, was man noch alles mit Log-Dateien anfangen kann, empfehle ich Ihnen darüber hinaus das Buch [HEIN 2003]

=== 11.2.1 Apache-Hilfsprogramme ))) Einige Hilfsprogramme zur Verarbeitung von Log-Dateien werden automatisch mit Apache installiert. Ihr grundsätzlicher Einsatz wurde weiter oben bereits erwähnt; hier finden Sie eine Kurzreferenz

rotatelogs Das Programm rotatelogs ermöglicht den regelmäßigen Wechsel der Log-Datei nach Ablauf einer bestimmten Zeitspanne. Dabei kann der Name der Datei mit strftime()-konformen Datums- und Uhrzeitkürzeln versehen werden. Die Syntax des Programms ist folgende

rotatelogs Dateimuster \ [Sekunden [Zeitzonendifferenz]] | [DateigrößeM]

Das »Dateimuster« ist der mit strftime()-Formatangaben angereicherte Dateiname. Eine Tabelle der allgemein verfügbaren Kürzel finden Sie weiter oben in diesem Kapitel. Das folgende Beispiel verwendet Tag, Monat und Jahr access_log.%d.%m.%Y. Sie erhalten also Dateinamen wie beispielsweise access_ log.22.08.2011

Das zweite (optionale) Argument ist die Wechselfrequenz in Sekunden. Geben Sie beispielsweise 86400 für einen Tag oder 604800 für eine Woche an

Die Zeitzonendifferenz können Sie verwenden, um den Abstand Ihrer Zeitzone zur Greenwich Mean Time (oder UTC) anzugeben, damit der Wechsel auch zum passenden Zeitpunkt erfolgt. Der Wert wird mit vorangestelltem +/– in Minuten angegeben. In Deutschland müssen Sie also z. B. +60 verwenden

Eine Alternative zu den Zeitangaben ist die Dateigröße: Sie können eine Zahl mit nachgestelltem M verwenden, um festzulegen, dass Ihre Log-Datei nicht größer werden darf als die angegebene Megabyte-Zahl. Beispiel: 3M für drei Megabyte

rotatelogs wird so gut wie immer als Piped-Log-Programm aufgerufen. Das bedeutet, dass Sie in einer Logging-Direktive statt des einfachen Namens einer Log-Datei ein Konstrukt nach dem Schema "|rotatelogs Dateiname [Optionen]" verwenden können. Das folgende Beispiel legt wöchentlich eine neue ZugriffsLog-Datei an, deren Name die Wochennummer und die Jahreszahl enthält

Auswertung von Log-Dateien 11.2

CustomLog \ "|rotatelogs /usr/local/apache2/logs/access_log.%W-%Y 604800" \ common

Weitere Beispiele wurden bereits bei der Vorstellung der Logging-Direktiven gegeben

logresolve Dieses kleine Hilfsprogramm wird in der Regel nicht mittels Piped Logging, sondern über die Kommandozeile aufgerufen. Es ermittelt per DNS Hostnamen, die zu den IP-Adressen in Ihren Log-Dateien gehören. Das Programm liest von der Standardeingabe und schreibt auf die Standardausgabe, sodass Sie normalerweise die Umleitungen < Original-Logdatei und > Hostnamen-Logdatei verwenden sollten

Die Syntax des Tools ist demnach folgende

logresolve [-s Statistikdatei] [-c] < Original > Neue_Datei

Die Option -s erlaubt die Festlegung eines Dateinamens; in die Datei werden statistische Informationen geschrieben. -c bestimmt dagegen, dass ein DoubleReverse-DNS-Lookup durchgeführt wird (siehe Kapitel 6, »Grundkonfiguration«; dort bei der Beschreibung der Direktive Allow)

Wenn Sie möchten, können Sie logresolve zu einer Uhrzeit als Cronjob ausführen, zu der auf Ihrer Website wenig los ist. Das ist auf jeden Fall sparsamer als die Verwendung der Direktive HostnameLookups, zumal logresolve einen eingebauten DNS-Cache besitzt und somit jede Adresse nur einmal pro Durchgang ermitteln muss

split-logfile Das Perl-Skript split-logfile zerlegt Log-Dateien nach verschiedenen virtuellen Hosts. Dazu müssen Sie ein Log-Format verwenden, das den Namen des jeweiligen virtuellen Hosts (%v) an die erste Stelle setzt. Das Skript teilt die Log-Datei daraufhin in einzelne Dateien auf, die jeweils VIRTUELLER_HOST.log heißen

log_server_status Dieses kleine Perl-Skript dient nicht der Bearbeitung gewöhnlicher Log-Dateien Seine einzige Aufgabe besteht darin, den Status Ihres Webservers abzufragen, zu einer einzelnen Zeile zusammenzufassen und auf die Standardausgabe zu schreiben. Damit es funktionieren kann, müssen Sie mod_status aktivieren und einer URL den Handler server-status zuordnen (siehe Kapitel 8, »Weiterleitungen und Indizes«). Anschließend können Sie log_server_status regelmäßig per Cronjob aufrufen und erhalten auf diese Weise eine Status-Log-Datei

11.2.2 Log-Datei-Auswertung durch eigene Skripte

Für angepasste Einsatzzwecke lohnt es sich, eigene Skripte für die Auswertung von Log-Dateien zu schreiben. Die ideale Sprache dafür ist Perl, weil sich die Regeln zur Zerlegung der Dateien am besten durch reguläre Ausdrücke beschreiben lassen; diese sind bekanntlich in Perl perfekt integriert

In diesem Unterabschnitt werden drei kleine Skriptbeispiele betrachtet, die Ihnen einen Einblick in die vielfältigen Möglichkeiten geben. Davor werden hier noch die beiden regulären Ausdrücke vorgestellt, die das Common beziehungsweise das Combined Log Format erkennt. Für das CLF gilt das folgende Ungetüm

^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+\[([^\]]+)\]\s+"([^"]+)"\s+ (\d+)\s+([\d\-]+)$

Die Teilausdrücke in den runden Klammern bilden die einzelnen Komponenten, die tatsächlich gefunden werden sollen. Viele von ihnen werden einfach durch [^\s]+ – ein oder mehrere Nicht-Leerzeichen – beschrieben, da sie jeweils durch Leerzeichen voneinander getrennt werden. Hinzu kommen die Sonderzeichen, die manche Bestandteile umschließen: Die eckigen Klammern um das Datum sowie die Anführungszeichen um die Anfrage (genau wie Referer und User-Agent beim Combined Log Format) stehen außerhalb der runden Klammern, werden also nicht mitgespeichert. Vorsichtshalber werden die Felder jeweils durch »ein oder mehrere Leerzeichen« (\s+) getrennt. Wichtig ist das Dollarzeichen als Abschlussmarkierung, da das Regexp ansonsten auch auf das Combined Log Format passen würde. Dessen regulärer Ausdruck sieht entsprechend so aus

^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+\[([^\]]+)\]\s+"([^"]+)"\s+ (\d+)\s+([\d\-]+)\s+"([^"]+)"\s+"([^"]+)"

Der Vollständigkeit halber sei noch angemerkt, dass der beliebte deutsche Hoster 1&1 ein eigenes Log-Format verwendet, das sich mithilfe der nachfolgenden Skripte nicht verarbeiten lässt – vor dem Referer steht hier noch der Name des virtuellen Hosts; ganz am Ende kommt eine eventuelle Proxy-Liste (oder "-") hinzu. Der reguläre Ausdruck müsste entsprechend erweitert werden, was hier allerdings aus Platzgründen unterbleibt

Formatierte Ausgabe Das erste Beispiel dient eher der Erläuterung der Grundlagen als der praktischen Nutzeranwendung. Es gibt die Komponenten jeder Log-Zeile in einem Format wie diesem aus

1. Format: Combined Log Format Remote Host: 84.165.169.1

Auswertung von Log-Dateien 11.2

RFC 1413 ID: Remote User: Date/Time: 24/Aug/2011:00:00:53 +0200 HTTP Request: GET /it_komp/fragen.html HTTP/1.1 HTTP Status: 200 Content Length: 6337 Referer: http://buecher.lingoworld.de/it_komp/aus -wert.php User Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)

Aufgerufen wird es mithilfe der folgenden Syntax

$ ./format_log.pl Logdatei [n]

Wenn Sie den zweiten Parameter (eine ganze Zahl) angeben, werden nur die ersten n Zeilen betrachtet. Die meisten echten Log-Dateien sind zu lang, um auf diese Weise behandelt zu werden

Listing 11.1 zeigt den vollständigen Code des Skripts. Sie finden es im Verzeichnis logscripts der beiliegenden DVD-ROM

  1. !/usr/bin/perl -w use strict;
  1. *****************************************
  2. * Skript: log_format.pl *
  3. * Apache-Logdateien formatiert ausgeben *
  4. * *
  5. * (C) 2005-2011, Sascha Kersken *
  6. * *
  7. * Free Software under the terms of the *
  8. * GNU General Public License, V2.0: *
  9. * www.gnu.org/licenses/gpl-2.0.html *
  10. *****************************************
  1. Namen der Logdatei von der Kommandozeile lesen my $logfile = $ARGV[0] || die "Verwendung: $0 Logdatei [n]\n";
  2. Eventuelle Höchstzahl lesen my $maxlines = $ARGV[1] || 0;
  1. Versuchen, die Logdatei zu öffnen open (LOG, "<$logfile") || die "Kann $logfile nicht öffnen\n";
  1. Variablen für die Logdatei-Bestandteile my ($host, $id1413, $uid, $date, $request, $status, $size, $referer, $useragent);
  1. Zähler, Gültigkeit der Zeile my $count = 1;

my $valid;

  1. Zeilenweise einlesen und auswerten while (my $line = <LOG>) {

chomp $line; if ($line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+ \[([^\]]+)\]\s+"([^"]+)"\s+(\d+)\s+([\d\-]+)$/) { $valid = 1;

  1. Common Log Format zerlegen

($host, $id1413, $uid, $date, $request, $status, $size) = ($1, $2, $3, $4, $5, $6, $7);

  1. Fehlende Felder setzen

$referer = "[ohne]"; $useragent = "[ohne]"; print "$count. Format: Common Log Format\n"; } elsif ($line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+ \[([^\]]+)\]\s+"([^"]+)"\s+(\d+)\s+([\d\-]+)\s+ "([^"]+)"\s+"([^"]+)"/) { $valid = 1;

  1. Combined Log Format zerlegen

($host, $id1413, $uid, $date, $request, $status, $size, $referer, $useragent) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); print "$count. Format: Combined Log Format\n"; } else { $valid = 0; print "$count. Unrecognized line: \"$line\"\n\n"; }

  1. Ausgeben, falls gültig if ($valid) {

print " Remote Host: $host\n"; print " RFC 1413 ID: $id1413\n"; print " Remote User: $uid\n"; print " Date/Time: $date\n"; print " HTTP Request: $request\n"; print " HTTP Status: $status\n"; print " Content Length: $size\n"; print " Referer: $referer\n"; print " User Agent: $useragent\n\n"; }

  1. Zähler erhöhen

$count++;

  1. Beenden, falls begrenzt

Auswertung von Log-Dateien 11.2

last if $maxlines && $count > $maxlines; }

Listing 11.1 log_format.pl; formatierte Ausgabe von Log-Dateien

Einfache Statistik Interessanter als die einfache Formatierung ist es, die erhaltenen Daten statistisch auszuwerten. Das hier vorgestellte Perl-Skript beschränkt sich beispielhaft auf zwei typische Werte solcher Statistiken: die treuesten Besucher(-URLs) und die am häufigsten besuchten URLs, jeweils mit Angabe ihrer Anzahl. Als Pflichtparameter müssen Sie wieder den Namen einer Log-Datei angeben; optional können Sie zusätzlich die gewünschte Höchstzahl der Ergebnisse setzen (ansonsten wird 20 verwendet). Ein typischer Aufruf dieses Skripts mit seinem Ergebnis sieht so aus

$ ./log_stat.pl access_log 10 Die (bis zu) 10 haeufigsten Besucher

1. 66.246.218.107: 696 2. 213.160.11.114: 683 3. 66.249.65.67: 386 4. 65.54.188.71: 379 5. 81.173.174.49: 306 6. 213.196.248.98: 271 7. 66.249.65.133: 270 8. 213.196.241.196: 237 9. 66.249.65.79: 157 10. 87.78.46.0: 151

Die (bis zu) 10 haeufigsten erfolgreichen Anfragen

1. /main.css: 1791 2. /pixel.gif: 1771 3. /galileo.gif: 1593 4. /apache2/c_168_240.jpg: 1158 5. /apache2/noepatents.jpg: 1090 6. /it_komp/c_180_240.jpg: 409 7. /it_komp/noepatents.jpg: 345 8. /: 261 9. /fachinfo/c_190_240.jpg: 184 10. /apache2/mod_ssl.html: 170

In Listing 11.2 sehen Sie den Quellcode dieses Beispiels. Die Funktionsweise dürfte durch die relativ ausführlichen Kommentare einigermaßen klar werden

  1. !/usr/bin/perl -w use strict;
  2. *****************************************
  3. * Skript: log_stat.pl *
  4. * Einfache Statistik für Web-Logdateien *
  5. * *
  6. * (C) 2005-2011, Sascha Kersken *
  7. * *
  8. * Free Software under the terms of the *
  9. * GNU General Public License, V2.0: *
  10. * www.gnu.org/licenses/gpl-2.0.html *
  11. *****************************************
  1. Namen der Logdatei von der Kommandozeile lesen my $logfile = $ARGV[0] || die "Verwendung: $0 Logdatei [Max]\n";
  2. Gewünschte Höchst-Zeilenzahl lesen oder auf 20 setzen my $maxlines = $ARGV[1] || 20;
  1. Versuchen, die Logdatei zu öffnen open (LOG, "<$logfile") || die "Kann $logfile nicht öffnen\n";
  1. Arrays für die Logdatei-Bestandteile my (@hosts, @ids, @uids, @dates, @requests, @status, @sizes, @referers, @useragents);
  1. Zeilenweise einlesen und auswerten while (my $line = <LOG>) {

chomp $line; if ($line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+ \[([^\]]+)\]\s+"([^"]+)"\s+(\d+)\s+([\d\-]+)$/) { push @hosts, $1; push @ids, $2; push @uids, $3; push @dates, $4; push @requests, $5; push @status, $6; push @sizes, $7; push @referers, "-"; push @useragents, "-"; } elsif ($line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+ \[([^\]]+)\]\s+"([^"]+)"\s+(\d+)\s+([\d\-]+)\s+ "([^"]+)"\s+"([^"]+)"/) { push @hosts, $1; push @ids, $2; push @uids, $3; push @dates, $4;

Auswertung von Log-Dateien 11.2

push @requests, $5; push @status, $6; push @sizes, $7; push @referers, $8; push @useragents, $9; } }

  1. Anzahlen unterschiedlicher Hosts ermitteln my %sorthosts;

foreach my $host(@hosts) {

  1. Im Hash %sorthosts ist der Host der Schlüssel;
  2. der Wert dient als Zähler und wird um 1 erhöht

$sorthosts{$host}++; } print "Die (bis zu) $maxlines haeufigsten Besucher:\n\n"; my $c = 1; foreach my $host (sort {$sorthosts{$b} <=> $sorthosts{$a}} (keys %sorthosts)) { print "$c. $host: ${sorthosts{$host}}\n"; $c++; last if $c > $maxlines; } print "\n";

  1. Anzahlen unterschiedlicher erfolgreich angeforderter URLs my %sorturls;

my $i = 0; foreach my $request(@requests) {

  1. URL aus dem Request ermitteln my $url;

if ($request =~ /[A-Z]+\s+([^\s]+)/) { $url = $1; }

  1. War diese Anfrage erfolgreich?

if ($status[$i] == 200) {

  1. URL zählen

$sorturls{$url}++; } $i++; } print "Die (bis zu) $maxlines haeufigsten erfolgreichen Anfragen:\n\ n"; $c = 1; foreach my $url (sort {$sorturls{$b} <=> $sorturls{$a}} (keys %sorturls)) {

print "$c. $url: ${sorturls{$url}}\n"; $c++; last if $c > $maxlines; }

Listing 11.2 log_stat.pl; einfache statistische Auswertung von Log-Dateien

Ein wenig kompliziert ist in diesem Beispiel das Verfahren zur sortierten Ausgabe der Hashes – diese sollen nämlich nicht nach ihren Schlüsseln (den IP-Adressen beziehungsweise URL-Pfaden), sondern nach den Werten sortiert werden. Die Perl-Funktion sort() erlaubt für solche Zwecke die Angabe einer Sortiervorschrift in Form einer eingebetteten Funktion. Die stilisierten Variablen $a und $b geben die Reihenfolge an. Für numerische Vergleiche wird der spezielle Operator <=> verwendet, während die String-Sortierung durch cmp geregelt wird. Beispielsweise werden die URL-Pfade wie folgt absteigend nach ihrer Anzahl sortiert

sort {$sorturls{$b} <=> $sorturls{$a}} (keys %sorturls)

Die Log-Daten in eine Datenbank übernehmen Das letzte Beispielskript erfüllt eine besonders nützliche Aufgabe: Es schreibt die Inhalte der angegebenen Log-Datei in eine MySQL-Datenbank. Zu diesem Zweck müssen Sie eine Datenbank namens log mit einer Tabelle namens logs anlegen Im Kommandozeilen-Client mysql (siehe Kapitel 15, »Technologien zur Webprogrammierung«) sehen die entsprechenden Anweisungen so aus

mysql> CREATE DATABASE log; mysql> USE log mysql> CREATE TABLE logs ( -> id INT AUTO_INCREMENT, -> host VARCHAR(50), -> rid VARCHAR(30), -> uid VARCHAR(30), -> rdate DATETIME, -> request VARCHAR(400), -> status INT, -> size INT, -> referer VARCHAR(400), -> useragent VARCHAR(200), -> PRIMARY KEY (id) -> );

Näheres über die Perl-Datenbankschnittstelle DBI, die für die Datenbankverbindung eingesetzt wird, erfahren Sie ebenfalls in Kapitel 15, »Technologien zur Webprogrammierung«. Wichtig ist hier, dass Sie username und password durch die korrekten Werte für Ihren eigenen MySQL-Server ersetzen

Auswertung von Log-Dateien 11.2

  1. !/usr/bin/perl -w use strict;

use DBI;

  1. *****************************************
  2. * Skript: log2db.pl *
  3. * Web-Logdateien in MySQL-DB schreiben *
  4. * *
  5. * (C) 2005-2011, Sascha Kersken *
  6. * *
  7. * Free Software under the terms of the *
  8. * GNU General Public License, V2.0: *
  9. * www.gnu.org/licenses/gpl-2.0.html *
  10. *****************************************
  1. Namen der Logdatei von der Kommandozeile lesen my $logfile = $ARGV[0] || die "Verwendung: $0 Logdatei\n";
  1. Verbindung zur MySQL-Datenbank herstellen my $conn = DBI->connect ("dbi:mysql:log;localhost", "username", "password") ||

die "Kann Datenbankverbindung nicht herstellen\n";

  1. Versuchen, die Logdatei zu öffnen open (LOG, "<$logfile") || die "Kann $logfile nicht öffnen\n";
  1. Variablen für die Logdatei-Bestandteile my ($host, $id, $uid, $date, $request, $status, $size, $referer, $useragent);
  1. Gültigkeit der Zeile my $valid;
  1. Monate für die Datumsumwandlung my %months = (

Jan => '01', Feb => '02', Mar => '03', Apr => '04', May => '05', Jun => '06', Jul => '07', Aug => '08', Sep => '09', Oct => '10',

Nov => '11', Dec => '12' );

  1. Zeilenweise einlesen und in die DB schreiben while (my $line = <LOG>) {

chomp $line; if ($line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+ \[([^\]]+)\]\s+"([^"]+)"\s+(\d+)\s+([\d\-]+)$/) {

  1. Gültig

$valid = 1;

  1. Bestandteile übernehmen

$host = $1; $id = $2; $uid = $3; $date = $4; $request = $5; $status = $6; $size = $7; $referer = "-"; $useragent = "-"; } elsif ($line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+ \[([^\]]+)\]\s+"([^"]+)"\s+(\d+)\s+ ([\d\-]+)\s+"([^"]+)"\s+"([^"]+)"/) {

  1. Gültig

$valid = 1;

  1. Bestandteile übernehmen

$host = $1; $id = $2; $uid = $3; $date = $4; $request = $5; $status = $6; $size = $7; $referer = $8; $useragent = $9; } else {

  1. Ungültig

$valid = 0; }

  1. Daten in die Datenbank schreiben, falls gültig if ($valid) {
  2. Datum in SQL-Format umwandeln, z.B
  3. 24/Oct/2005:00:06:58 +0200 -> "2005-10-24 00:06:58"

my $sqldate; if ($date =~

Auswertung von Log-Dateien 11.2

m|(\d+)/([A-Za-z]+)/(\d+):(\d+):(\d+):(\d+)|) { $sqldate = "$3-".$months{$2}."-$1 $4:$5:$6"; }

  1. "-" in Content-Length durch 0 ersetzen

$size =~ s/\-/0/;

  1. Die SQL-Abfrage my $q = "INSERT INTO logs

(host, rid, uid, rdate, request, status, size, referer, useragent) VALUES (\"$host\", \"$id\", \"$uid\", \"$sqldate\", \"$request\", \"$status\", \"$size\", \"$referer\", \"$useragent\")";

  1. Abfrage durchführen

$conn->do ($q); } }

Listing 11.3 log2db.pl; Log-Datei-Inhalte in eine MySQL-Datenbank schreiben

Befinden sich die Daten erst einmal in der Datenbank, können Sie beliebige SQLOperationen damit ausführen – die Erstellung eigener Statistiken wird so noch leichter. Abbildung 11.1 zeigt einen kleinen Ausschnitt der Daten in der webbasierten MySQL-Arbeitsoberfläche »phpMyAdmin«

Abbildung 11.1 Ein Ausschnitt einer in die Datenbank übernommenen Log-Datei in »phpMyAdmin«

Hier noch ein Beispiel für eine SQL-Abfrage zur statistischen Auswertung. Sie liefert die zehn Hosts mit den meisten Seitenaufrufen, genau wie das weiter oben vorgestellte Statistikskript. Sie können die Abfrage sowohl im KommandozeilenClient als auch in »phpMyAdmin« eingeben, sobald Sie log als Standarddatenbank ausgewählt haben

mysql> SELECT host, COUNT(*) AS Besuche FROM logs GROUP BY host -> ORDER BY Besuche DESC LIMIT 0,10; +-----------------+---------+ | host | Besuche | +-----------------+---------+ | 66.246.218.107 | 696 | | 213.160.11.114 | 683 | | 66.249.65.67 | 386 | | 65.54.188.71 | 379 | | 81.173.174.49 | 306 | | 213.196.248.98 | 271 | | 66.249.65.133 | 270 | | 213.196.241.196 | 237 | | 66.249.65.79 | 157 | | 87.78.46.0 | 151 | +-----------------+---------+

Weitere Informationen zur MySQL-Syntax würden den Rahmen dieses Buches sprengen. Wenn Sie sich für MySQL und seine Möglichkeiten interessieren, kann ich Ihnen mein Buch Praktischer Einstieg in MySQL mit PHP (2. Auflage; Köln 2007, O’Reilly Verlag) empfehlen.1

Wenn Sie die Verwaltung von Log-Daten in einer Datenbank nützlich finden, können Sie alternativ auch auf diverse Drittanbieter-Module zurückgreifen, beispielsweise mod_log_mysql für MySQL-Datenbanken. Einige dieser Module werden in Kapitel 17, »Apache erweitern«, erwähnt

11.2.3 Externe Tools Es gibt unzählige Hilfsprogramme von Drittanbietern zur Verwaltung, Analyse oder Visualisierung von Log-Dateien. Eine Auswahl davon finden Sie auf der DVD zum Buch. Unter anderem sind dort folgende Programme zu finden

  • cronolog

Dieses Programm von Andrew Ford ist eine erheblich leistungsfähigere Alter

1 Im Handel ausverkauft; kostenloser Download (PDF) unter: http://www.oreilly.de/german/freebooks/einmysql2ger/

Zusammenfassung 11.3

native zu rotatelogs. Download-Möglichkeiten und zusätzliche Informationen finden Sie unter http://www.cronolog.org

  • Webalizer

Der Webalizer ist das bekannteste Hilfsmittel zur Erzeugung grafischer Darstellungen aus Log-Dateien. Er erzeugt HTML-Dateien und Grafiken; über Konfigurationsdateien und Stylesheets können Sie ihn sehr flexibel an Ihre eigenen Bedürfnisse anpassen. Im Übrigen gibt es zahlreiche Erweiterungen und Plug-ins; interessant ist etwa der GeoLizer, der die geografische Verteilung nach IP-Adressen (per GeoIP-Datenbank) ermittelt. Die Website des Projekts ist http://www.webalizer.com

  • Wusage

Dieses Tool arbeitet browserbasiert durch seinen eigenen kleinen Webserver auf einem ungenutzten Port. Es erstellt die bei Weitem detailliertesten Statistiken im Testfeld und lässt sich sehr intuitiv nutzen. Die Buch-DVD enthält eine Trial-Version. Die Lizenz für einen Host kostet 25 $; für 75 $ ist eine Lizenz für fünf Hosts zu haben. Download und weitere Informationen unter http://www.boutell.com/wusage

  • Mescalero

Dies ist ein kommerzielles, aber recht kostengünstiges (Preis: 99 €) Programm für Windows. Es enthält zahlreiche Tools zur Auswertung von Log-Dateien Die Website für dieses Programm ist http://www.rendle.de/software/mescalero.html; auf der DVD finden Sie eine 30-Tage-Testversion