Awstats Auswertung multipler Vhosts und Alias- und Subdomains

#1
Hallo zusammen,

ich beschreibe hier, wie ich folgende Anforderung gelöst habe:


  1. Awstats Auswertung je Domain, auch wenn die Domains alle unter einem Vhost laufen (wie es z.B. bei Typo3 üblich ist)
  2. Auswertung der Logdateien mehrerer identischer Webserver (ISPConfig Mirror Setup), die hinter einem Loadbalancer stehen
  3. Kein Eingriff in das ISPConfig System, der z.B. durch ein Update zerstört werden könnte
  4. Integration in ISPConfig dahgingehend, dass für neu angelegte Websites automatisch auch die passenden Statistiken erstellt werden.
  5. Auswertung soll auch mehrfach täglich möglich sein.
  6. Automatische Komprimierung der Logfiles nach Auswertung
  7. Möglichkeit der Mandantenfähigkeit beim Zugriff auf die Statistiken
  8. Ein zentraler Statistik Webhost


OK, erstmal ein kurzer Überblick zur Umsetzung:



Setup:
1x ISPConfig Controlpanel Server (ispcfg.foo.bar)
2x ISPConfig Webserver (Mirror Setup) angebunden an ispcfg.foo.bar
2x ISPConfig DB-Cluster (Heartbeat/DRBD) angebunden an ispcfg.foo.bar
1x ISPConfig Webserver (stats.foo.bar) angebunden an ispcfg.foo.bar

Anmerkung: Das Ganze funktioniert auch mit einem einzigen ISPConfig Server, der alles macht.

Die einzelnen ISPConfig Webhosts leiten ein CustomLog (parallel zur vlogger Config) an den lokalen logger.

Der logger schickt es an den lokalen Syslog Server (in dem Fall rsyslogd).
Der rsyslogd schickt es an den zur Auswertung auserkorenen zentralen Webhost (in meinem Fall auch ein Host im ISPConfig Verbund - der oben zuletzt genannte.)

Auf dem zentralen Host, nennen wir ihn stats.foo.bar empfängt der rsyslog die Apache Logs der anderen Webserver inkl. seines eigenen.
Der rsyslogd schreibt die Logs in ein Verzeichnis je Vhost.

Die Website stats.foo.bar ist ein per ISPConfig ganz normal angelegter Vhost.

Ein stark modifiziertes cron_daily.php (aus der ISPConfig Distri) befragt die ISPConfig Master-DB nach allen vorhandenen Vhosts, Sub- und Aliasdomains und wertet darauf basierend die gesammelten Logfiles aus.

Die fertigen Statistiken werden dann in die Document Root von stats.foo.bar geschrieben und dort nach Vhost Hauptdomain separiert in Unterverzeichnissen abgelegt.

Falls nicht vorhanden, wird sicherheitshalber ein htaccess Schutz auf das stats Verzeichnis gelegt, welches unter http://stats.foo.bar/sites erreichbar ist. Als Authentifikation wird einfach auf das htpasswd File verwiesen, welches sich in der statistics Config der Website stats.foo.bar per ISPConfig mit Passwort versehen lässt.

Diese htaccess kann natürlich ersetzt werden. Die Unterverzeichnisse können separat geschützt werden, ... Das ist die gewünschte Mandantenfähigkeit. :)



Kommen wir zu den verschiedenen Konfigurationen


Erstmal die Log Config für Apache.


Es wird z.B. folgende Datei erstellt und nach /etc/apache2/sites-available/ verlinkt:

/etc/apache2/sites-available/custom-ispconfig.conf
Code:
#########################################################
# Custom ISPConfig Logfile configuration for remote logging
#########################################################

LogFormat "%v %{Host}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined_custom_ispconfig
CustomLog "| /usr/bin/logger -p local0.info -t apache2" combined_custom_ispconfig
Auf diese Art und Weise wird das Logging einfach parallel zur ISPconfig Methode per vlogger rausgeleitet. D.h. die ISPConfig eigene Logverwaltung und Auswertung wird nicht tangiert.


Die lokale rsyslog Config

/etc/rsyslog.d/apache2-remote.conf
Code:
# remote logging

if $syslogfacility-text == 'local0' and ( $syslogtag contains_i 'apache2' ) then @stats.foo.bar

# don't write to other logfiles
if $syslogfacility-text == 'local0' and ( $syslogtag contains_i 'apache2' ) then ~
Es wird alles erstmal an den zentralen Host weitergeleitet. Ich empfehle allerdings die IP statt des Namens einzutragen.


Das war's dann schon mit der Konfiguration auf dem oder den Webhosts.


rsyslog Konfig auf dem zentralen Sammler


Remote Logging einschalten nicht vergessen.


/etc/rsyslog.d/apache2-local.conf
Code:
# Apache2 Log reception

# strip the first space from message
$template Message,"%msg:2:$%\n"

# Field 2 = Apache LogFormat: %v = The canonical ServerName of the server serving the request
# Field 3 = Apache LogFormat: %{Host}i = The content of Host: header in the request sent to the server.
$template ApacheAccessLogFile,"/var/log/custom-ispconfig/httpd/%msg:F,32:2%/%$YEAR%%$MONTH%%$DAY%-access.log"


if $syslogfacility-text == 'local0' and ( $syslogtag contains_i 'apache2' ) then -?ApacheAccessLogFile;Message

# don't write to other logfiles
if $syslogfacility-text == 'local0' and ( $syslogtag contains_i 'apache2' ) then ~
Hier verwenden wir ein wenig rsyslog magic und schreiben die empfangenen Apache Logdaten in jeweils ein Unterverzeichnis je Vhost.


Dann benötigen wir noch eine eigene Awstats Config:


/etc/custom-ispconfig/awstats/awstats.conf.override

Code:
LogFormat = "%other %virtualname %host %other %logname %time1 %methodurl %code %bytesd %refererquot %uaquot"
LoadPlugin="geoip GEOIP_STANDARD /usr/share/GeoIP/GeoIP.dat"
DirData="/var/lib/custom-ispconfig/awstats"
Nicht vergessen, auch das Verzeichnis /var/lib/custom-ispconfig/awstats zu erstellen.


Auch hier ist wieder das Ziel erreicht, keine Konflikte mit der ISPConfig Logauswertung zu bekommen.


Im Prinzip war es das nun fast schon. Jetzt fehlt nur noch das Auswerte Script. Dafpür habe ich /usr/local/ispconfig/server/cron_daily.php als Grundlage verwendet.


Es heisst bei mir custom-ispconfig-awstats.php und befindet sich im Anhang. Von diesem Script wird noch eine Datei benötigt: /etc/custom-ispconfig/templates/awstats_index_subdir.php.master
Diese befindet sich ebenfalls im Anhang im ZIP File custom-ispconfig-awstats.zip


Das PHP-Script wird dann per Cron, wie das cron_daily.php von einem Shell Script aufgerufen. Ich habe nur noch einen Lock Mechanismus eingebaut, so dass sich das Script bei zu häufigem Aufruf nicht gegenseitig überholt:

/usr/local/custom-ispconfig-extras/server/custom-ispconfig-awstats.sh

Code:
#!/bin/sh
#
# $Rev:: 00            $:  Revision of last commit
# $Author:: mw         $:  Author of last commit
# $Date:: 2013-04-18 1#$:  Date of last commit


PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin

DEBUG=false

MY=`basename $0`
LOCK_FILE=/var/lock/$MY.lck
PROC_PID=/var/run/$MY.pid

# needed for debug loggig
hostname=`hostname`
logname=$LOGNAME


# If pidfile exists exit
if [ -e $PROC_PID ]; then
  echo
  echo "$MY[$$] Former process pid $(cat $PROC_PID) exits ... exiting."
  echo
  logger -t "$MY[$$]" "Former process pid $(cat $PROC_PID) exits ... exiting."
  exit 1
fi

logger -t "$MY[$$]" "Doing my job."

# Write pidfile
echo -n "$$" > $PROC_PID

func_exit() {
rm -f $PROC_PID && logger -t "$MY[$$]" "[ERROR] Unexpected exit."
}

func_exit_normal() {
rm -f $PROC_PID && logger -t "$MY[$$]" "Removed pidfile."
}


trap func_exit EXIT

if [ -f /usr/local/ispconfig/server/lib/php.ini ]; then
        PHPINIOWNER=`stat -c %U /usr/local/ispconfig/server/lib/php.ini`
        if [ $PHPINIOWNER == 'root' ] || [ $PHPINIOWNER == 'ispconfig'  ]; then
                export PHPRC=/usr/local/ispconfig/server/lib
        fi
fi

/usr/bin/php -q /usr/local/custom-ispconfig-extras/server/custom-ispconfig-awstats.php

logger -t "$MY[$$]" "Did it."

trap func_exit_normal EXIT
exit 0
In der ISPConfig der Website stats.foo.bar habe ich noch folgende Apache Directive eingebunden, damit sich durch die Statistikverzeichnisse browsen lässt:



Code:
<Directory /var/www/stats.foo.bar/web/sites>
    Options +Indexes
    HeaderName /include/HEADER.html
    IndexIgnore ..
    IndexOptions +FancyIndexing
    IndexOptions +HTMLTable
    IndexOptions +SuppressDescription
    IndexOptions +SuppressSize
    IndexOptions +SuppressIcon
    IndexOptions +SuppressRules
    IndexOptions +SuppressHTMLPreamble
    Order allow,deny
    AllowOverride All
    Allow from all
</Directory>
Ich hoffe, meine Erklärungen waren ausreichend. Der Gag an der ganzen Sache ist ja eigentlich nur die Ausleitung der Apache Logs an einen zentralen Loghost, ohne mit ISPConfig irgendwo in Konflikt zu geraten. Der Rest ist individuell handhabbar. Z.B. müssen die Statistiken nicht auf einem ISPConfig Server ausgewertet werden. Es muss auch nicht unbedingt die ISPConfig DB befragt werden. Es wäre ebenso denkbar einfach nur die Logs basierend auf ihrem Inhalt auszuwerten, ...


Es kann auch alles auf einem Host stattfinden. Dann ist nur die zweite rsyslogd Config zu verwenden.


Anmerkungen:

Was noch fehlt in meinem Setup, ist eine Löschung alter Apache Logs. Bis Dato werden die Logfiles nur durch das PHP Script komprimiert nach erfolgter Auswertung. Die Rotation erfolgt ja durch die rsyslog Konfig sowieso täglich.


Die User können nachwievor im ISPconfig wahlweise awstats oder webalizer als Statistik auswählen. Diese Statistiken landen wie gehabt unter vhost/stats. Die Generierung der zentralen Awstats läuft vollkommen unabhängig immer für alle Vhosts. Das lässt sich im PHP-Script anpassen.


Matthias
 

Anhänge

Werbung