In questo infobox verra' illustrato come fare in modo che syslog-ng anziche' loggare su normali files di testo scriva all'interno di un database mysql.
Una configurazione tipica per salvare i log all'interno di un database prevede l'utilizzo di una pipe, ma dopo alcuni test ho preferito scartare la soluzione poiche' troppo messaggi venivano persi al momento della scrittura tramite il client mysql. In questo caso si e' optato per una soluzione differente che prevede di salvarei i log come query all'interno di diversi file poi processati in modo asincrono da uno shellscript che provvedera' a memorizzarli all'interno del database.
Si presuppone sia syslog-ng, mysqlserver ed il client mysql siano gia' installati sul sitema.
Innanzitutto e' necessario connettendosi a mysql con il comando mysql -u username -p passwhord -h 127.0.0.1
e creare il database che conterra' i log con il comando create database db_log;
.
Si presuppone che mysql sia in esecuzione sullo stesso sistema del syslog server ed in ascolto sull'indirizzo di loopback.
Una voltra create il database si suggerisce di creare un utente apposito che abbia i privilegi sullo stesso, in modo di evitare di utilizzare l'utenza di root. Anche in questo caso e' necessario loggarsi al dbms con un mysql -u username -p password -h 127.0.0.1
ed eseguir eil seguente comando:
GRANT ALL PRIVILEGES ON db_syslog.* TO [email protected] IDENTIFIED BY 'syslog_password'
.
L'ultima operazione da eseguire sul database e' la creazione della tabella che conterra' i messaggi syslog salvati da syslog-ng. Tale operazione puo' essere portata a termine con il comando mysql -u syslog_user -p syslog_password -h 127.0.0.1 < syslog_table.sql
.
syslog_table.sql sara' un file di testo contenente le istruzione per creare la tabella, e dovra' contenere le seguenti linee:
#
# Table structure for table `logs`
#
CREATE TABLE logs (
host varchar(32) default NULL,
facility varchar(10) default NULL,
priority varchar(10) default NULL,
level varchar(10) default NULL,
tag varchar(10) default NULL,
date date default NULL,
time time default NULL,
program varchar(15) default NULL,
msg text,
seq int(10) unsigned NOT NULL auto_increment,
PRIMARY KEY (seq),
KEY host (host),
KEY seq (seq),
KEY program (program),
KEY time (time),
KEY date (date),
KEY priority (priority),
KEY facility (facility)
) TYPE=MyISAM;
Ovviamente nel caso il file syslog_table non sia nella stessa directory dalla quale viene lanciato il client mysql
sara' necessario specificare il percorso del file in questione.
Una volta predisposta la parte relativa al database, e' stata aggiunta la seguente destinazione al file di configurazione di syslog-ng /etc/syslog-ng/syslog-ng.conf:
#file di destinazione con query sql che saranno processate dal feeder
destination file_sql {
file("/var/log/sqllog/log_sql_$HOUR.$MIN"
template("INSERT INTO logs (host, facility, priority, level, tag, date, time, program, msg) VALUES ( '$HOST', '$FACILITY', '$PRIORITY', '$LEVEL', '$TAG', '$YEAR-$MONTH-$DAY', '$HOUR:$MIN:$SEC','$PROGRAM', '$MSG' );\n")
template_escape(yes));
};
Questa direttiva fa in modo che all'interno del file /var/log/sqllog/log_sql_ORA.MINUTO vengano inserite una serie di istruzioni INSERT SQL che una volta eseguite dal client mysql andranno ad inserire i dati nella tabella logs del database db_syslog.
A meno che nel file di configurazione di syslog-ng non sia posta a yes l'opzione create_dirs sara' necessario creare la directory /var/log/sqllog ed impostare dei permessi coerenti con le opzioni owner, group, perm, dir_owner, dir_group e dir_perm se definite nel file di configurazione di syslog-ng.
Inoltre, come si puo' notare dall'opzione file della direttiva destination, non verra' creato un singolo file ma diversi a seconda dell'ora e del minuto in cui verranno generati. Tale scelta si e' resa necessaria per semplificare la creazione e l'esecuzione dello shellscript che eseguira effettivamente gli inserimenti nek database e che verra' successivamente illustrato.
Infine, la nuova destinazione creata dovra' essere utilizzata all'interno di una direttiva log del file /etc/syslog-ng/syslog-ng.conf perche' qualcosa possa essere scritto all'interno del file /var/log/sqllog/log_sql_ORA.MINUTO:
#log query per il feeder
log { source(s_all); destination(file_sql); };
Con questa configurazione, pero', nessun dato viene ancora scritto all'interno del database ma vengono solo scritte delle istruzioni INSERT nei file /var/log/sqllog/log_sql_ORA.MINUTO.
E' quindi necessario creare uno script che prenda questi file e inserisca effettivamente i log all'interno del database, ad esempio /opt/syslg-db/feeder.sh:
#!/bin/bash
# Script adattato da process_logs di Casey Allen Shobe
dbhost="localhost"
dbuser="syslog_user"
dbpass="syslog_password"
dbname="db_log"
datadir="/var/log/sqllog"
while true; do
logfiles=`find $datadir -name "log_sql_[0-2][0-9].[0-5][0-9]"`
sleep 70 # This is to ensure we don't screw up a log currently being written.
for logfile in $logfiles; do
cat $logfile | mysql --user=$dbuser --password=$dbpass $dbname
if [ $? -ne 0 ]; then
echo "[ERRORE] Problema nel processare il file $logfile!!!" >> $datadir"/feeder_log.log"
#exit 1 #Comment out this line if you want the script to
else
echo "[OK] $logfile inserito nel db in data `date --rfc-3339=seconds`" >> $datadir"/feeder_log.log"
rm -f $logfile
fi
done
done
Nella parte iniziale dello script vengono definite alcune variabili d'ambiente che indicano i parametri da utilizzare per la connessione al database e la directory dove si trovano i files scritti da syslog-ng contenenti le istruzioni inserti da eseguire.
Un aspetto importante dello script e' l'istruzione sleep 70
eseguita all'interno del ciclo while dopo avere settato la variabile contenente i nomi dei file da processare durante l'iterazione corrente. Quando eseguita essa sospende l'esecuzione dello script per 70 secondi, in modo da impedire che possa essere processato un file in corso di scrittura da parte di syslog-ng.
Poiche' la destination definita nel file di configurazione di syslog-ng, prevede la creazione di un nuovo file di log ogni minuto (grazie all'utilizzo della macro $MIN), con una sleep di 70 secondi si avra' la sicurezza che i files definiti nella variabile logfiles non siano piu' oggetto di scrittura, essendo trascorsi almeno 60 secondi dalla loro creazione.
Per ognuno di questi file, infine, vengono eseguite le istruzioni INSERT in essi contenute passandole in input al client mysql tramite la linea cat $logfile | mysql --user=$dbuser --password=$dbpass $dbname
.
Una volta processato, il file viene rimosso tramite il comando rm -f
. Lo script verifica inoltre l'exit code del comando mysql ed in base ad esso scrive l'esito del processing del file in /var/log/sqllog. Questa operazione puo' anche essere considerata superflua ed evitata semplicemente commentando le due istruzioni echo
all'interno del ciclo for.
Infine, per automatizzare l'utilizzo dello script feeder.sh e' possibile modificare lo script /etc/syslog-ng/syslog-ng in modo da avviare e terminare automaticamente feeder.sh insieme al syslog server:
#!/bin/sh
#
[...]
start() {
echo -n $"Starting $prog: "
daemon $exec $SYSLOGNG_OPTIONS
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
echo "Starting Feeder"
/opt/syslg-db/feeder.sh &
return $retval
}
stop() {
echo "Stopping Feeder"
killall feeder.sh
echo -n $"Stopping $prog: "
killproc $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
[...]
La scrittura dei log all'interno di un database potrebbe essere utile per semplificare la ricerca dei messaggi in base a determinati criteri o semplicemente visualizzarli tramite qualche interfaccia web scritta in php o con qualche altro linguaggio.
Una delle applicazioni piu' note in tal senso e' forse php-syslog-ng.
Nel caso specifico illustrato i log sono stati invece memorizzati su un database per potere poi essere consultati tramite un plugin di cacti chiamato h.aloe.
Analisi, monitoring, rotazione e gestione dei log di sistema. Configurazione di syslogd.