Logdaten sind wichtig und lästig. Man muss sie oft aufheben und genauso oft stört der Platzbedarf.
Um Logdaten effizienter speichern zu können, wurde der Log-Server entwickelt. Auf ihm werden die Logdaten übers Netz (gewöhnlich per UDP) abgelegt, da es sich oft aber auch um sehr wichtige Daten handelt, will man sie nicht per UDP auf die Reise schicken!
Leider gibt es zur Zeit nur zwei Log-Daemon die Logdaten per TCP senden und empfangen können:
Große Linux-Distributionen stellen aus Kompatibilitätsgründen zunehmend auf rsyslogd um:
Anleitungen für TCP-Log-Server mit Datenbank-Back-End:
Die Direktive ErrorLog bestimmt den Namen der Datei, in welcher der Server alle auftretenden Fehler protokolliert. Wenn Dateiname nicht absolut ist, wird er relativ zu ServerRoot betrachtet.
Die Verwendung von syslog anstelle eines Dateinamens aktiviert die Protokollierung mittels syslogd(8), sofern das System es unterstützt. Als Voreinstellung wird der syslog-Typ (syslog facility) local7 verwendet, Sie können dies jedoch auch überschreiben, indem Sie die Syntax syslog:facility verwenden, wobei "facility" einer der Namen sein kann, die üblicherweise in syslog(1) dokumentiert sind.
ErrorLog syslog:local7
Leider kann CustomLog nicht nach syslog loggen. Hierfür muss man einen kleinen Umweg über ein Kommandozeilenwerkzeug logger verwenden.
Bei Ubuntu müssen dazu (mindestens) in den folgenden Dateien die unten genannte Änderung vorgenommen werden:
<virtualhost> ... ErrorLog syslog:local7.warn CustomLog "| cat $@ | logger -p local7.notice -t apache2" vhost_combined ... </virtualhost>
Möchte man zusätzlich noch eine Log-Datei schreiben lassen, dann muss CustomLog wie folgt aussehen:
CustomLog "| cat $@ | tee -a /var/log/apache2/access.log | logger -p local7.notice -t apache2" combined
Hat man mehrere Webserver, die in die selbe DB loggen, dann ist es sinnvoll die Bezeichnung apache2 gegen die Domain (z.B. www.domain.de) auszutauschen oder besser, mit der Domain zu kombinieren:
CustomLog "| cat $@ | tee -a /var/log/apache2/access.log | logger -p local7.notice -t apache2_www.domain.de" combined
# echo "SELECT ID,ReceivedAt,DeviceReportedTime,Facility,FromHost,Message,SysLogTag FROM SystemEvents WHERE SysLogTag LIKE 'apache%' ORDER BY ID DESC LIMIT 20;" | mysql -t -u rsyslog -p Syslog
Laut RFC ist es nämlich so, dass eine "Syslog-Message" maximal 1024 Byte lang sein darf. 1024 zeichen sind für eine Apache-Logzeile viel zu kurz. wenn du dir die inhalte der Tabelle "SystemEvents" genauer ansiehst wirst du feststellen das die inhalte der Message-Spalte nie 1024 zeichen überschreiten obwohl von anfang an der datentyp TEXT verwendet wurde. demnach sollten auch Messages die kleiner als 65535 zeichen sind problemlos in diesem feld gespeichert werden könnnen. es exsistiert in der tabelle aber kein einziger record dessen Message-Spalte > 1024 zeichen lang ist.
hier gibt es auch eine disskussion zu diesem Thema:
hier ist der RFC:
in dem es heißt:
4.1 syslog Message Parts The full format of a syslog message seen on the wire has three discernable parts. The first part is called the PRI, the second part is the HEADER, and the third part is the MSG. The total length of the packet MUST be 1024 Byte or less."
Da wir die Apache-Access-Log's durch den "logger" ins Syslog schreiben, gehen keine Daten verloren, da der "logger" alle Log-Zeilen in 1024 Byte lange Zeilen aufbricht. Allerdings wird auch mitten im Wort umgebrochen, so das man unter Umständen ein gesuchtes Wort im Log nicht finden kann weil es vom "logger" durchgebrochen wurde.
Laut Doku sollte der Default von derzeit 2k über den Parameter $MaxMessageSize in der rsyslog.conf modifizierbar sein: http://www.rsyslog.com/doc/rsyslog_conf_global.html
# echo '$MaxMessageSize 64k' > /etc/rsyslog.d/riesen_nachrichten.conf # /etc/init.d/rsyslog restart
Da der "logger" alle Log-Zeilen in 1024 Byte lange Zeilen umbricht, brauchen wir eine Alternative. Hier gibt es Perl- und C-Code für Alternativen: http://wiki.rsyslog.com/index.php/Working_Apache_and_Rsyslog_configuration
Hier liegt unsere leicht modifizierte Alternative zum "logger", von der oben genannten Webseite:
#include <stdio.h>
#define SYSLOG_NAMES
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
if (3 != argc)
{
fprintf(stderr, "Usage: stdin2syslogd priority syslog-tag\n");
exit (1);
}
const char *priority_name = argv[1];
const char *tag_name = argv[2];
int priority = -1;
int i;
for (i = 0; prioritynames[i].c_name; ++i)
{
if (! strcmp(prioritynames[i].c_name, priority_name))
{
priority = prioritynames[i].c_val;
break;
}
}
if (priority < 0)
{
fprintf(stderr, "stdin-syslogd: priority \"%s\" not recognized",
priority_name);
exit (1);
}
// Log-Level wurde hier mit "LOCAL7" festgelegt:
openlog(tag_name, LOG_PID|LOG_NDELAY, LOG_LOCAL7);
// max. Zeilenlänge wurde hier mit 64kB festgelegt:
char buffer[65536];
while (NULL != fgets(buffer, sizeof(buffer), stdin))
{
syslog(priority, "%s", buffer);
}
return 0;
}
# gcc -o /usr/local/bin/stdin2syslogd stdin2syslogd.c
# tail -f /var/log/messages | fgrep Test_Tag
# echo "Das ist ein Logger-Test!" | /usr/local/bin/stdin2syslogd notice Test_Tag
CustomLog "| /usr/local/bin/stdin2syslogd notice Apache2_www.domain.de" combined