[Tipp] Wenn die Apache Logfiles unter SysCP aus allen Nähten platzen

  • Hallo vServer Betreiber!


    Dieser Tipp hier bezieht sich auf netcup vServer mit Apache und SysCP!


    Um was geht's?
    Wenn man unter SysCP mehrere Domains hat, diese stark besucht sind und man auch noch für jede Domain eine Speciallogfile angelegt hat, kann man schneller Festplattenplatz verlieren als einem lieb ist. Diese Speciallogfiles sind eine separate Apache accesslog und errorlog Datei, die für Webalizer benutzt wird (die Dateien liegen in /var/kunden/logs). Man erhält also nach Domains getrennt Statistiken. Ansich eine gute Sache, aber leider geht SysCP hier, wie so oft, wieder eigene Wege.
    Durch diese "Auskopplung", wird die normale Config Datei von Webalizer nicht beachtet und somit kann man auch nicht für jede Domain einzeln bestimmen, dass die Statistiken inkrementell geführt werden. Das wäre aber nötig, um die Logfiles in das Logrotate aufzunehmen, damit diese Logfiles hin und wieder geleert werden, ohne die Statistik zu verlieren.
    Man denkt sich vielleicht "na und? ist doch egal ob man die Logs löschen kann", aber so einfach ist das nicht. Die Logfiles werden nämlich kontinuierlich erweitert, wodurch sie wachsen und wachsen. Auf einer meiner Domains habe ich im Schnitt am Tag ca. 320 unique Besucher, diese durchstöbern natürlich die Webseite und fordern somit eine Menge Dateien vom Server an, was alles fein säuberlich in der accesslog festgehalten wird. Jedes Bildchen, Grafik, CSS, usw. wird protokolliert. Dadurch ist die accesslog allein in den letzten 6 Wochen um fast 70 MB gewachsen! Man kann sich leicht ausrechnen was da in einem Jahr zusammenkommt oder was erst abgehen muß, wenn man 2000+ Besucher am Tag hat.
    Wie erwähnt, Webalizer selbst würde ja eine Lösung anbieten, aber das wird leider von SysCP zunichte gemacht. Man müsste die Cron Dateien von SysCP schon um einiges erweitern, damit man für jede zu loggende Domain eine eigene Config Datei generieren lässt, damit man Logrotate benutzen kann.


    Es gibt aber einen Workaround, der zwar auch nicht die ultimative Lösung ist, aber das Problem deutlich reduziert!



    Der Workaround
    Wir bringen einfach dem Apache bei, dass er nicht jeden Sch... loggen soll, sondern nur Zugriffe auf Informationsdateien (HTML, PHP Seiten) und nicht auf Bilder, CSS, JS, usw.
    Wir können auch wieder nicht einfach in der Apache Config einstellen was wir möchten, sondern müssen (müssen nicht, aber ist das sauberste und flexibelste) der vHost Datei, die von SysCP alle 5 Minuten neu erstellt wird, einen Zusatz hinzufügen, damit wir im SysCP Control Panel die Konfiguration vornehmen können.



    Schritt 1
    Die Cron Datei im Editor öffnen:
    /var/www/syscp/scripts/cron_tasks.inc.http.10.apache.php
    Vorher Backup der Datei machen!!



    Schritt 2
    Hier diese Zeile suchen

    Code
    $logfiles_text.= '  CustomLog "' . $this->settings['system']['logfiles_directory'] . $domain['loginname'] . $speciallogfile . '-access.log" combined' . "\n";


    und hinter das "combined" ein "env=!dontlog" setzen. Damit sollte die Zeile so aussehen

    Code
    $logfiles_text.= '  CustomLog "' . $this->settings['system']['logfiles_directory'] . $domain['loginname'] . $speciallogfile . '-access.log" combined [B][COLOR='Red']env=!dontlog[/COLOR][/B]' . "\n";


    Speichern und Editor verlassen.



    Schritt 3
    Apache neu starten


    Jetzt warten wir ca. 5 Minuten, bis der Cron das nächste mal ausgeführt wurde und schauen dann kurz in die Datei /etc/apache2/sites-available/99_syscp_vhosts.conf
    Dort sollte jetzt eigentlich für jede Domain eine Zeile stehen die ähnlich dieser ist

    Code
    CustomLog "/var/kunden/logs/<domain name>-access.log" combined env=!dontlog

    Wichtig ist der Zusatz "env=!dontlog". Fehlt der, habt Ihr an der falschen Stelle in der Cron Datei gewerkelt!



    Schritt 4
    Die Konfiguration findet im Admin Panel statt, unter Domains->Eigene vHost-Einstellungen.
    Dort können wir jetzt dem Apache mitteilen, welche Zugriffe auf Dateien er jetzt loggen soll und welche nicht. Um z.B. keine Logeinträge mehr von Grafikdateien (darunter fallen Hintergründe einer Seite, spacer, Banner, einfach alles was grafisch ist) zu erstellen, geben wir in das vHost Feld ein:

    Code
    SetEnvIfNoCase Request_URI ".(gif)|(jpg)|(png)|(css)|(js)|(ico)$" dontlog


    Wichtig ist hier wieder das korrespondierende "dontlog". Hier werden also Zugriffe auf Dateien, die auf .gif, .jpg, .png, .ico, .css, .js enden nicht mehr in die accesslog geschrieben.
    Möchte man keine Logeinträge von Dateien in einem bestimmten Unterverzeichnis, benutzt man z.B.

    Code
    SetEnvIf Request_URI "^/unterordner" dontlog


    Logeinträge von Spider, z.B. Googlebot kann man unterbinden mit

    Code
    SetEnvIFNoCase User-Agent "Googlebot" dontlog


    Ebenso kann man Zugriffe von bestimmten Seiten ausschließen

    Code
    SetEnvIfNoCase Referer "domain.tld" dontlog



    Fazit
    Der bessere Weg wäre natürlich immer noch die Logfiles in das logrotate aufzunehmen und alte Logfiles zu löschen, aber das erweist sich als erheblich komplexer, als es auf den ersten Blick aussieht. Mit diese Ausdünnung der Logfile kann man aber das Volumen enorm reduzieren. Ich habe Logeinträge bei Zugriffe auf Grafiken, CSS, JS und einige Unterverzeichnisse, in denen interner Kram liegt, ausgeschlossen und das täglich dazu kommende Volumen beträgt nur noch 1/10 von dem Ursprünglichen.


    Vielleicht ist der Tipp hier ja dem ein oder anderen von Nutzen. Bald beginnt ein neues Jahr, da wäre es eigentlich der perfekte Zeitpunkt die alten Logfiles zu entsorgen und mit den entschlackten anzufangen. ;)



    vg koweto

  • Ich habe mir vor einiger Zeit zwei kleine PHP-Scripts gebastelt um die Logs zu archivieren. Dabei wird wöchentlich ein Ordner mit aktuellen Datum erstellt, alle Logs hineinverschoben, komprimiert und der Indianer neugestartet, damit neue Log-Dateien angelegt und verwendet werden. Funktioniert soweit prima und spart verdammt viel Speicherplatz. Wenn man die Logs dann irgendwann gar nicht mehr braucht, muss man so einfach nur die Ordner mit dem jeweiligen Datum löschen und kann die Logs so wöchentlich entfernen (oder täglich, monatlich, whatever - je nachdem wie oft man das Script mit Cron ausführt). Die Verwendung der Scripte ist auf eigene Gefahr, Feedback usw. wie immer erwünscht. /var/kunden/logs/ muss natürlich an den eigenen Log-Ordner angepasst werden ;)


    ~/scripts/apache_logs.php
    [PHP]<?php


    // Archiviert alle alten Apache Logs in einem Ordner mit heutigem Datum,
    // komprimiert sie mittels bzip2 (höchste Stufe) und startet den Indianer neu.
    // Dieses Script kann minimal einmal täglich aufgerufen werden!


    // Alle Logs suchen
    $files = glob('/var/kunden/logs/*.log');
    if(is_array($files) && count($files))
    {
    // Neuen Ordner anlegen
    $folder = '/var/kunden/logs/'.date('Y-m-d').'/';
    if(file_exists($folder) && is_dir($folder))
    {
    die("Das Script kann nur einmal täglich ausgeführt werden!\n");
    }
    elseif(!mkdir($folder))
    {
    die("Der Ordner konnte nicht angelegt werden!\n");
    }

    foreach($files as $file)
    {
    if(is_file($file) && !is_link($file))
    {
    // Datei verschieben
    rename($file, $folder.basename($file));
    }
    }

    // Indianer neu starten
    exec('/etc/init.d/apache2 restart', $result, $code);
    if($code !== 0)
    {
    die("Der Apache konnte nicht neu gestartet werden!\n");
    }

    // Dateien komprimieren
    exec('php ~/scripts/compress_all.php '.escapeshellarg($folder).' bzip2 9', $result, $code);
    if($code !== 0)
    {
    die("Die Dateien konnten nicht komprimiert werden!\n");
    }
    }


    ?>[/PHP]


    ~/scripts/compress_all.php
    [PHP]<?php


    $dir = @realpath($_SERVER['argv'][1]);
    $method = (isset($_SERVER['argv'][2])) ? $_SERVER['argv'][2] : 'bzip2';
    $block = (isset($_SERVER['argv'][3])) ? $_SERVER['argv'][3] : 5;


    if(!in_array($method, array('bzip2', 'gzip', 'zip')))
    {
    die("Unbekannte Komprimierung!\n");
    }


    if(!preg_match('#^[0-9]+$#', $block) || $block < 1 || $block > 9)
    {
    die("Blockgröße ist keine Zahl!");
    }


    /*
    var_dump($dir);
    var_dump($method);
    var_dump($block);
    die("\n");
    */


    if(@is_dir($dir))
    {
    do_it($dir);
    }
    elseif(@is_file($dir))
    {
    exec($method.' '.escapeshellarg($dir).' -'.$block);
    }
    else
    {
    die("Order/Datei existiert nicht!\n");
    }


    function do_it($dir)
    {
    global $method, $block;

    $handle = @opendir($dir);
    while ($file = @readdir ($handle))
    {
    if($file != '.' && $file != '..')
    {
    if(is_dir($dir.'/'.$file))
    {
    dot_it($dir.'/'.$file);
    }
    elseif(is_file($dir.'/'.$file))
    {
    exec($method.' '.escapeshellarg($dir.'/'.$file).' -'.$block);
    }
    }
    }
    @closedir($handle);
    }


    ?>[/PHP]


    Meine Logfiles waren dank den SC:Banner die auf meinem vServer laufen nämlich innerhalb von einer Woche schnell mal 1 GB groß, mit diesem Script dann nur mehr wenige MB. Eine nachträgliche Komprimierung bringt gerade bei Logfiles sehr viel :)



    MfG Christian

    "Wer nur noch Enten sieht, hat die Kontrolle über seine Server verloren." (Netzentenfund)

  • Übersehe ich etwas oder ist nicht das genau die Aufgabe von logrotate? Da kann man all diese Sachen schön einstellen: Wie oft rotiert werden soll (z.b. wöchentlich oder bei 10 MB), wie viele alte Logs gespeichert werden sollen, ob komprimiert werden soll usw. Drei Tipps noch: Standardmäßig ist für den Apache eingestellt, dass er nach dem Rotieren neustarten soll. Wenn man das nicht will, kann man einfach in der Konfig-Datei das "restart" durch "reload" ersetzen. Um das Datum im Dateinamen zu haben, einfach "dateext" in die Konfig-Datei schreiben. Und die Möglichkeit nutzen, Wildcards im Dateinamen anzugeben - ist bei einer Verzeichnisstruktur wie z.B. /var/www/kunde123/logs/ praktisch.

  • Zitat von Robert;3955

    Übersehe ich etwas oder ist nicht das genau die Aufgabe von logrotate?


    Indirekt schon, aber ich bin einfach ein PHP-Freak, und erfinde das Rad oft neu :D



    MfG Christian

    "Wer nur noch Enten sieht, hat die Kontrolle über seine Server verloren." (Netzentenfund)