LINUX:LogWatch

De WIKI sur Linux (ADB)
Aller à la navigation Aller à la recherche

retour à la Surveillance


But

Ce logiciel effectue un résumé des activités de la veille du serveur sur base majoritairement des journaux. Il met l'accent sur les problèmes et alertes rencontrés. Le résultat est envoyé par messagerie. En le visionnant, j'ai pu mettre le doigt sur divers problèmes et prendre les mesures correspondantes.


Installation

La première étape consiste à installer le paquet:

dnf install logwatch


Configuration: structure

Les fichiers de configuration personnalisables se trouvent dans le répertoire "/etc/logwatch" et ceux de référence dans le répertoire "/usr/share/logwatch".

La structure est identique; si un fichier du même nom se retrouve aux deux endroits, celui sous le répertoire "/etc/logwatch" a la priorité. Donc pour adapter la configuration, il suffit de recopier le fichier correspondant du répertoire "/usr/share/logwatch" dans le répertoire "/etc/logwatch" ou du moins de reprendre dans ce fichier, le paramètre que l'on veut changer. Normalement on ne devrait rien changer.

Voici la structure:

  • répertoire "conf" sous "/etc/logwatch": contient la configuration personnalisée.
  • répertoire "default.conf" sous le répertoire "/usr/share/logwatch": contient la configuration par défaut.
    • fichier "conf/logwatch.conf" ou "default.conf/logwatch.conf": contient la configuration générale.
    • fichier "conf/override.conf": permet d'ignorer certains paramètres de configuration repris sous le répertoire "/usr/share/logwatch/default.conf".
    • répertoire "conf/logfiles" ou "default.conf/logfiles": contient les fichiers de configuration contenant la liste des noms des journaux à analyser pour chaque service, un fichier par groupe de journaux. Au nom du groupe, on ajoute l'extension ".conf".
    • répertoire "conf/services" ou "default.conf/services": contient les fichiers de configuration pour chaque service, un fichier par service. Au nom du service, on ajoute l'extension ".conf". Chaque fichier du service fait référence à un ou plusieurs fichiers de groupe de journaux. Il est à noter que certains services n'analysent aucun fichier journal mais on leur propre type de traitement. Par exemple, le service "zz-lm_sensors" récupère les températures des CPUs, des radiateurs, de la carte écran,... ou le service "zz-disk_space" récupère l'utilisation des espaces disques ("df").
  • répertoire "scripts/services": contient les scripts à exécuter pour chaque service, un script par service.


En premier lieu, on peut s'intéresser au fichier de configuration générale: "logwatch.conf" et spécialement au paramètres suivants:

  • MailTo = root : le message est envoyé à l'utilisateur "root"
  • Detail = Low : le niveau de détail affiché est au plus bas. Je conseille de le laisser à cette valeur. On peut le mettre à la valeur "Med" pour obtenir plus de détails mais on risque d'être submergé avec pour conséquence de ne plus regarder le rapport. Ne parlons pas du niveau maximal "High".


Personnalisation de la configuration

Normalement la configuration fournie est opérationnelle mais en fouillant cette configuration, nous avons été amené à l'adapter.

Voici quelques cas rencontrés. Certains font suite à des modifications personnelles.


PHP

En analysant le fichier "/usr/share/logwatch/default.conf/logfiles/php.conf", nous avons remarqué que les noms des journaux n'étaient pas les bons et en outre, nous avions ajouté le support des divers anciennes versions de PHP provenant les dépôts de Remi.

Nous avons donc créé le fichier de configuration "/etc/logwatch/conf/logfiles/php.conf" dont voici le contenu hors commentaires sur base du fichier "/usr/share/logwatch/default.conf/logfiles/php.conf":


# PHP (8.2) de la distribution
LogFile = php-fpm/error.log
LogFile = php-fpm/www-error.log
# PHP (7.4, 8.0 et 8.1) du dépôt de Remi
LogFile = /var/opt/remi/php74/log/php-fpm/error.log
LogFile = /var/opt/remi/php74/log/php-fpm/www-error.log
LogFile = /var/opt/remi/php80/log/php-fpm/error.log
LogFile = /var/opt/remi/php80/log/php-fpm/www-error.log
LogFile = /var/opt/remi/php81/log/php-fpm/error.log
LogFile = /var/opt/remi/php81/log/php-fpm/www-error.log
 
# PHP (8.2) de la distribution
Archive = php-fpm/error.log-*
Archive = php-fpm/www-error.log-*
# PHP (7.4, 8.0 et 8.1) du dépôt de Remi
Archive = /var/opt/remi/php74/log/php-fpm/error.log-*
Archive = /var/opt/remi/php74/log/php-fpm/www-error.log-*
Archive = /var/opt/remi/php80/log/php-fpm/error.log-*
Archive = /var/opt/remi/php80/log/php-fpm/www-error.log-*
Archive = /var/opt/remi/php81/log/php-fpm/error.log-*
Archive = /var/opt/remi/php81/log/php-fpm/www-error.log-*


IPTABLES

Nous redirigeons les messages venant du FireWakk IPtables vers le fichier "/var/log/iptables" et via le logiciel LogRotate, les archives se retrouvent dans les fichiers "/var/log/iptables-*".

Nous avons donc créé le fichier de configuration "/etc/logwatch/conf/logfiles/php.conf" dont voici le contenu hors commentaires sur base du fichier "/usr/share/logwatch/default.conf/logfiles/iptables.conf":


LogFile = iptables
Archive = iptables-*
*ApplyStdDate


MariaDB

Il existe un service "mysql" mais il est non opérationnel pour MariaDB principalement suite au format de la date précédent tout message.

Dans ce script, le format de la date est '%y%m%d %H:%M:%S', par exemple "230814 12:03:45" alors que nous avons besoin d'un format '%Y-%m-%d %H:%M:%S', par exemple "2023-08-14 12:03:45". En outre, nous souhaitions ne voir apparaître les messages "Note" que dans le cas d'un niveau de détail "High". De plus le nom des journaux étaient autres que ceux de MySQL. L'ordre des types de messages a été modifié. Nous avons donc créé un nouveau service sur base des fichiers du service "mysql".

Nous avons créé le fichier de configuration "/etc/logwatch/conf/logfiles/mariadb.conf" dont voici le contenu hors commentaires:


LogFile = mariadb/mariadb.log
Archive = mariadb/mariadb.log-*
*ExpandRepeats

Nous avons créé aussi le fichier de configuration "/etc/logwatch/conf/services/mariadb.conf" dont voici le contenu hors commentaires:


Title = "MariaDB"
LogFile = mariadb

Et nous avons adapté le script "/etc/logwatch/scripts/services/mariadb" sur base du script "/usr/share/logwatch/scripts/services/mysql" hors commentaires du début et de la fin pour ne pas surcharger la présentation. Il est écrit en Perl. Voici son contenu, en gras et en italique les modifications apportées et les lignes modifiées sont mises en commentaire:


use strict;
use Logwatch ':dates';
use Time::Local;
use POSIX qw(strftime);
 
#my $date_format = '%y%m%d %H:%M:%S';
my $date_format = '%Y-%m-%d %H:%M:%S';
 
my $filter = TimeFilter($date_format);
my $detail = exists $ENV{'LOGWATCH_DETAIL_LEVEL'} ? $ENV{'LOGWATCH_DETAIL_LEVEL'} : 0;
 
# we do not use any Date:: package (or strptime) as they are probably not available
my %month2num = ( Jan => 0, Feb => 1, Mar => 2, Apr => 3,
                  May => 4, Jun => 5, Jul => 6, Aug => 7,
                  Sep => 8, Oct => 9, Nov => 10, Dec => 11 );
 
# array of message categories (we do not use a hash to keep the order)
# first element: category name
# second element: matching regexp ($1 should contain the message)
# third element: anonymous hash ref (stores message  counts)
my @message_categories = (['Note', qr/\[Note\] (.*)$/o, {}],
                          ['Warnings', qr/\[Warning] (.*)$/o, {}],
                          ['Errors', qr/\[ERROR\] (.*)$/o, {}],
                          ['Other', qr/(.*)$/o, {}]);
 
# counting messages
while(<>) {
    my $line = $_;
    # skipping messages that are not within the requested range
    next unless $line =~ /^($filter)/o;  
 
#    $1 =~ /(\d\d)(\d\d)(\d\d)\s+(\d+):(\d+):(\d+)/;
    $1 =~ /(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)/;
 
    my $time;
 
    {
        # timelocal is quite chatty
        local $SIG{'__WARN__'}  = sub {};
        $time = timelocal($6, $5, $4, $3, $2-1, $1);
    }
 
    # Count lines with increasing number as one:
    #  [Warning] Aborted connection 107194 to db: ...
    $line =~ s/(Aborted connection) \d+ (to db)/$1 $2/;
 
    foreach my $cur_cat (@message_categories) {
        if($line =~ /$cur_cat->[1]/) {
            my $msgs = $cur_cat->[2];
            $msgs->{$1} = {count => '0',
                           first_occurrence => $time,
                           sum => 0,
                           sqrsum => 0} unless exists $msgs->{$1};
            $msgs->{$1}->{'count'}++;
            # summing up timestamps and squares of timestamps
            # in order to calculate the rms
            # using first occurrence of message as offset in calculation to
            # prevent an integer overflow
            $msgs->{$1}->{'sum'} += $time - $msgs->{$1}->{'first_occurrence'};
            $msgs->{$1}->{'sqrsum'} += ($time - $msgs->{$1}->{'first_occurrence'}) ** 2;
            last;
        }
    }
}
 
# generating summary
foreach my $cur_cat (@message_categories) {
  # skipping non-requested message types
  next unless keys %{$cur_cat->[2]};
  my ($name, undef, $msgs) = @{$cur_cat};
 
  my $etat = 0;
  if(($detail <= 5) and ($name eq "Note")) {$etat = 1};
  if($etat == 0) {
    print $name, ":\n";
    my $last_count = 0;
 
    # sorting messages by count
    my @sorted_msgs = sort { $msgs->{$b}->{'count'} <=> $msgs->{$a}->{'count'} } keys %{$msgs};
 
    foreach my $msg (@sorted_msgs) {
        # grouping messages by number of occurrence
        print "\n", $msgs->{$msg}->{'count'}, " times:\n" unless $last_count == $msgs->{$msg}->{'count'};
        my $rms = 0;
 
        # printing timestamp
        print '[';
 
        if($msgs->{$msg}->{'count'} > 1) {
            # calculating rms
            $rms = int(sqrt(
                           ($msgs->{$msg}->{'count'} *
                            $msgs->{$msg}->{'sqrsum'} -
                            $msgs->{$msg}->{'sum'}) /
                           ($msgs->{$msg}->{'count'} *
                            ($msgs->{$msg}->{'count'} - 1))));
 
            print strftime($date_format, localtime($msgs->{$msg}->{'first_occurrence'}+int($rms/2)));
 
            print ' +/-';
 
            # printing rms
            if($rms > 86400) {
                print int($rms/86400) , ' day(s)';
            } elsif($rms > 3600) {
                print int($rms/3600) , ' hour(s)';
            } elsif($rms > 60) {
                print int($rms/60) , ' minute(s)';
            } else {
                print $rms, ' seconds';
            }
        } else {
            # we have got this message a single time
            print strftime($date_format, localtime($msgs->{$msg}->{'first_occurrence'}));
        }
 
        print '] ', $msg, "\n";
        $last_count = $msgs->{$msg}->{'count'};
    }
 
    print "\n";
  }
}


Audit

Si on élève le niveau de détail de "Low" à "Med", on est submergé par le très grand nombre de messages d'audit.

Pour y pallier, nous avons créé le fichier de configuration "/etc/logwatch/conf/services/audit.conf" dont voici le contenu:


Detail = Low


Activation de services désactivés

Dans le fichier de fonfiguration générale "/usr/share/logwatch/default.conf/logwatch.conf", les services "zz-network" et "zz-sys" sont désactivés. Nous désirons les réactiver sauf le service "eximstats". Cette opération demande une configuration spéciale.

Dans le fichier de configuration "/etc/logwatch/conf/override.conf", on ajoute les lignes suivantes:


logwatch: Service =
logwatch: Service = All
logwatch: Service = "-eximstats"

La première ligne annule les options "Service" dans le fichier "/usr/share/logwatch/default.conf/logwatch.conf". On les remplace par l'activation de tous les services ("All") sauf le service "eximstats" ("-eximstats").


Exécution

Ce programme s'exécute une fois par jour via le service Cron. Cette commande se trouve dans le fichier "/etc/cron.daily/0logwatch". Il traite les journaux de la veille et envoie un message à l'utilisateur "root" par défaut.


Il est possible de l'exécuter en direct via la commande:

logwatch

Dans ce cas, le résultat s'affiche directement à l'écran et concerne tous les services.

On peut se limiter à un service en le précisant. Par exemple pour le service "postfix, cette commande:

logwatch --service postfix

donne:


################### Logwatch 7.9 (07/22/23) ####################
       Processing Initiated: Fri Aug 18 15:11:28 2023
       Date Range Processed: yesterday
                             ( 2023-Aug-17 )
                             Period is day.
       Detail Level of Output: 0
       Type of Output/Format: stdout / text
       Logfiles for Host: serverdb.home.dom
##################################################################
 
--------------------- Postfix Begin ------------------------
 
   2.419M  Bytes accepted                           2,536,824
   2.419M  Bytes delivered                          2,536,824
========   ==================================================
 
     119   Accepted                                   100.00%
--------   --------------------------------------------------
     119   Total                                      100.00%
========   ==================================================
 
     530   Connections                                    530
     530   Disconnections                                 530
     119   Removed from queue                             119
     119   Delivered                                      119
 
       1   Postfix start                                    1
       1   Postfix stop                                     1
 
---------------------- Postfix End -------------------------
 
###################### Logwatch End #########################

D'autre paramètres sont disponibles; un mérite notre attention: "--detail" suivi du niveau: ("Low", "Med" ou "High"). La commande équivalente à celle ci-dessus devient:

logwatch --service postfix --detail Low

Si le service n'est pas utilisé ou si aucune information n'est retenue, il n'y a pas d'affichage.

Cette commande exécutée en direct est intéressante pour vérifier le bon fonctionnement d'un service suite à toute modification.




retour à la Surveillance