Les fichiers de logs Linux que vous devez surveiller sur RHEL 9 et 10
Un guide pratique des fichiers de logs qui comptent sur Red Hat Enterprise Linux 9 et 10 et sur les systèmes compatibles (Oracle Linux, AlmaLinux, Rocky Linux) : où se trouve chacun, ce qu'il vous dit, les commandes pour le lire, et comment le conserver et le centraliser.

Chaque problème sur un serveur Linux laisse une trace quelque part : une connexion échouée, un service qui n'a pas démarré, une mise à jour de paquet qui a changé une bibliothèque, un disque qui a commencé à produire des erreurs. Savoir quel log contient quelle trace fait la différence entre un diagnostic de cinq minutes et un après-midi de conjectures. Ce guide couvre les logs qui comptent sur Red Hat Enterprise Linux 9 et 10, et sur les systèmes compatibles comme Oracle Linux, AlmaLinux et Rocky Linux, avec les commandes que nous utilisons pour les lire.
Deux endroits où vivent les logs sur RHEL : le journal et /var/log
Sur RHEL 9 et 10, presque tout est d'abord collecté par systemd-journald. Le journal est un dépôt structuré et indexé que vous lisez avec journalctl. Sur une installation standard, rsyslog lit ensuite le journal et écrit les fichiers texte familiers dans /var/log : messages, secure, cron, maillog et boot.log. Certains services gardent quoi qu'il arrive leurs propres fichiers, notamment le démon d'audit, les serveurs web, les bases de données et dnf.
Vérifiez que rsyslog est présent et en cours d'exécution avant de vous fier aux fichiers texte. Les images minimales et de conteneurs peuvent ne pas l'inclure :
rpm -q rsyslog
systemctl status rsyslog
# if it is missing:
dnf install rsyslog
systemctl enable --now rsyslog
La plupart des fichiers de /var/log ne sont lisibles que par root, donc exécutez les commandes ci-dessous en root ou avec sudo.
Le journal systemd
Le journal est le premier endroit où regarder, parce qu'il contient la sortie de chaque unité systemd, du noyau et de tout ce qui journalise via syslog, le tout avec des horodatages précis et des métadonnées sur lesquelles vous pouvez filtrer.
Des commandes qui valent d'être mémorisées
# everything from one service, newest last
journalctl -u nginx
# follow a service live, like tail -f
journalctl -u sshd -f
# only errors and worse, from the current boot
journalctl -p err -b
# warnings and worse from the previous boot (useful after a crash)
journalctl -p warning -b -1
# a time window
journalctl --since "1 hour ago"
journalctl -u php-fpm --since "2026-10-22 08:00" --until "2026-10-22 09:00"
# kernel messages only (the replacement for reading a dmesg file)
journalctl -k -b
# search message text
journalctl -u sshd -g "Failed password"
# list the boots the journal knows about
journalctl --list-boots
Plusieurs options -u peuvent se combiner, ce qui est pratique quand une requête traverse plus d'un service : journalctl -u nginx -u php-fpm --since "10 min ago".
Rendez le journal persistant
Sur une installation RHEL par défaut, le journal est conservé dans /run/log/journal, en mémoire, et il disparaît après un redémarrage. C'est exactement le moment où vous en avez le plus besoin. Pour le garder sur disque, créez un drop-in et redémarrez journald :
mkdir -p /etc/systemd/journald.conf.d
vi /etc/systemd/journald.conf.d/persistent.conf
[Journal]
Storage=persistent
SystemMaxUse=2G
systemctl restart systemd-journald
journalctl --flush
ls -ld /var/log/journal
journalctl --disk-usage
SystemMaxUse plafonne l'espace que le journal peut utiliser. Choisissez une valeur adaptée au disque. Après le prochain redémarrage, journalctl --list-boots montre plus d'une entrée et journalctl -b -1 fonctionne.
/var/log/messages : le log général du système
C'est le fichier fourre-tout : démarrages et arrêts de services, messages du noyau, avertissements matériel et pilotes, changements réseau et tout ce qui est journalisé au niveau info ou au-dessus et n'appartient pas aux catégories mail, authentification ou cron. C'est l'équivalent texte d'une grande partie du journal, et il est pratique pour grep et pour les outils qui attendent des fichiers plats.
tail -f /var/log/messages
grep -iE "error|fail|oom" /var/log/messages | tail -50
grep -i "out of memory" /var/log/messages
Une ligne comme Out of memory: Killed process signifie que le noyau a terminé un processus parce que le serveur a manqué de RAM. La réponse est de donner plus de mémoire à la charge de travail ou de réduire ce qu'elle utilise (moins de workers PHP-FPM ou de base de données, un cache, la correction d'une fuite), pas de cacher le symptôme.
/var/log/secure : le log de sécurité Linux pour l'authentification et les privilèges
Chaque connexion SSH, chaque mot de passe échoué, chaque sudo et su, et les messages PAM atterrissent ici. Sur RHEL, Oracle Linux, AlmaLinux et Rocky Linux, c'est le fichier à surveiller pour l'accès au serveur.
# failed SSH passwords and the addresses they came from
grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
# successful logins
grep "Accepted" /var/log/secure
# who used sudo, and for what
grep "COMMAND=" /var/log/secure
Deux outils apparentés complètent le tableau. last liste les connexions réussies depuis /var/log/wtmp, et lastb les connexions échouées depuis /var/log/btmp. Si les comptes se verrouillent après des tentatives échouées, faillock --user alice montre les tentatives et faillock --user alice --reset les efface.
/var/log/audit/audit.log : la piste d'audit
Le système d'audit Linux enregistre les événements liés à la sécurité au niveau du noyau : connexions, changements de privilèges, décisions SELinux et tout fichier ou appel système que vous choisissez de surveiller. Il est écrit par auditd et se lit avec ausearch et aureport plutôt qu'avec grep, parce que ces outils comprennent son format.
# summary of everything in the log
aureport --summary
# failed logins
aureport --login --failed
# authentication attempts
aureport -au
# today's events, with numeric IDs turned into names
ausearch -ts today -i
# failed login events only
ausearch -m USER_LOGIN -sv no -i
Surveillez les fichiers qui comptent
Les règles d'audit vous permettent d'enregistrer chaque modification d'un fichier sensible. Placez-les dans un fichier sous /etc/audit/rules.d/, par exemple /etc/audit/rules.d/50-watch.rules :
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
augenrules --load
auditctl -l
ausearch -k sshd_config -i
La dernière commande montre qui a modifié la configuration SSH, quand, et avec quel programme.
Refus SELinux
RHEL tourne avec SELinux en mode enforcing, et il doit le rester. Quand SELinux bloque quelque chose, le refus est enregistré comme un enregistrement AVC dans le log d'audit. Regardez-y avant de changer quoi que ce soit d'autre :
getenforce
ausearch -m AVC,USER_AVC -ts recent -i
ausearch -m AVC -ts today | audit2why
Pour une explication en langage clair avec des corrections suggérées, installez setroubleshoot et exécutez sealert sur le log :
dnf install setroubleshoot-server
sealert -a /var/log/audit/audit.log
La plupart des refus ont une cause simple : un fichier avec la mauvaise étiquette (corrigez avec restorecon -Rv <path>), du contenu placé dans un répertoire non standard (étiquetez-le avec semanage fcontext), ou une fonctionnalité qui a besoin d'un booléen activé (getsebool -a | grep httpd, puis setsebool -P). Épuisez ces pistes avant d'envisager un module de politique personnalisé.
/var/log/cron : les tâches planifiées
Chaque tâche lancée par crond et anacron est journalisée ici, avec l'utilisateur et la commande. Quand un backup ou un rapport « n'a pas tourné », ce fichier vous dit s'il a seulement été lancé.
grep CROND /var/log/cron | tail -20
grep "(root) CMD" /var/log/cron | tail -20
Beaucoup de tâches d'entretien de RHEL tournent désormais comme timers systemd au lieu de tâches cron. Listez-les avec systemctl list-timers et lisez leur sortie avec journalctl -u <name>.service, par exemple journalctl -u logrotate.service.
/var/log/maillog : la distribution du courrier
Postfix et les autres logiciels de messagerie journalisent ici chaque message qu'ils acceptent, relaient, diffèrent ou renvoient. Si une application web dit avoir envoyé un e-mail et que personne ne l'a reçu, la réponse est généralement dans ce fichier.
# the full path of one message, by recipient
grep "user@example.org" /var/log/maillog
# bounces and deferrals
grep -E "status=(bounced|deferred)" /var/log/maillog | tail -20
# what is still waiting in the queue
postqueue -p
Chaque message Postfix a un queue ID (par exemple 4F2A81C0B3E). Faites un grep sur cet ID pour voir chaque étape de sa distribution, y compris la réponse du serveur destinataire.
/var/log/dnf.log et dnf history : ce qui a changé
Quand quelque chose casse après une maintenance, la première question est ce qui a changé. Sur RHEL 9 et 10, les opérations sur les paquets sont gérées par dnf, qui écrit /var/log/dnf.log (l'exécution de dnf elle-même), /var/log/dnf.rpm.log (chaque paquet installé, mis à niveau ou supprimé) et /var/log/dnf.librepo.log (les téléchargements depuis les dépôts). La vue la plus rapide est la base d'historique :
# every transaction, newest first
dnf history
# exactly what one transaction did
dnf history info last
dnf history info 42
# every transaction that touched a package
dnf history list nginx
# packages changed recently, from the log file
grep -E "Install|Upgrade|Erase" /var/log/dnf.rpm.log | tail -30
# does anything need a restart after updates (dnf-plugins-core)
dnf needs-restarting -r
Si une mise à jour doit être annulée, dnf history undo <id> annule une seule transaction, à condition que les paquets plus anciens soient encore disponibles dans les dépôts.
/var/log/boot.log et le journal de démarrage
/var/log/boot.log contient les messages d'état du démarrage que vous verriez sur la console. Il est utile pour un coup d'œil rapide, mais l'enregistrement complet d'un démarrage est dans le journal :
cat /var/log/boot.log
journalctl -b -p err
journalctl -b -1 -p err # previous boot, needs the persistent journal
systemctl --failed # units that did not start
systemd-analyze blame | head # what took longest
Logs du serveur web et de PHP
Chaque serveur web garde ses propres logs d'accès et d'erreurs :
- nginx :
/var/log/nginx/access.loget/var/log/nginx/error.log, plus les fichiers par site que vous définissez avecaccess_logeterror_log. - Apache httpd :
/var/log/httpd/access_log,/var/log/httpd/error_log, etssl_access_logetssl_error_logquand mod_ssl est installé. - PHP-FPM :
/var/log/php-fpm/error.logpour le master FPM et/var/log/php-fpm/www-error.logpour les erreurs PHP du pool par défaut. Le pool peut aussi écrire un slow log avec une stack trace de chaque requête lente une foisrequest_slowlog_timeoutdéfini.
# top client addresses (default nginx log format)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# count of server errors (5xx) by URL
awk '$9 ~ /^5/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# the latest errors
tail -50 /var/log/nginx/error.log
tail -50 /var/log/php-fpm/www-error.log
Une rafale de réponses 502 ou 504 dans le log d'accès, accompagnée de « upstream timed out » ou « connect() failed » dans le log d'erreurs de nginx, désigne PHP-FPM : soit tous les workers étaient occupés, soit un script a tourné trop longtemps.
Logs des bases de données
- MariaDB (la base de données des dépôts RHEL) :
/var/log/mariadb/mariadb.log, défini parlog-errordans/etc/my.cnf.d/mariadb-server.cnf. - MySQL des dépôts RHEL :
/var/log/mysql/mysqld.log. - PostgreSQL :
/var/lib/pgsql/data/log/, un fichier par jour de la semaine par défaut.
Le log d'erreurs montre les problèmes de démarrage, les plantages, les tables corrompues et les erreurs de réplication. Pour les performances, activez le slow query log. Pour MariaDB, ajoutez à la section [mysqld] de /etc/my.cnf.d/mariadb-server.cnf et redémarrez :
slow_query_log = 1
slow_query_log_file = /var/log/mariadb/mariadb-slow.log
long_query_time = 1
Résumez-le ensuite avec mysqldumpslow -s t /var/log/mariadb/mariadb-slow.log | head -40 pour voir quelles requêtes coûtent le plus de temps total.
Garder les logs sous contrôle avec logrotate
RHEL fait tourner les fichiers de logs avec logrotate, exécuté une fois par jour par un timer systemd (logrotate.timer). Les valeurs par défaut globales sont dans /etc/logrotate.conf (hebdomadaire, quatre rotations, noms de fichiers datés comme messages-20261018), et chaque paquet ajoute ses propres règles sous /etc/logrotate.d/. Les fichiers système (messages, secure, cron, maillog) sont couverts par /etc/logrotate.d/rsyslog.
systemctl list-timers logrotate.timer
cat /etc/logrotate.d/nginx
# dry run: show what would happen, change nothing
logrotate -d /etc/logrotate.d/nginx
# force a rotation now, verbosely
logrotate -vf /etc/logrotate.d/nginx
Pour votre propre application, ajoutez un fichier comme /etc/logrotate.d/myapp :
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 myapp myapp
postrotate
/usr/bin/systemctl reload myapp.service >/dev/null 2>&1 || true
endscript
}
Gardez les logs applicatifs sous /var/log : les fichiers qui s'y trouvent reçoivent l'étiquette SELinux que logrotate est autorisé à gérer. Si le répertoire de logs est accessible en écriture à un utilisateur autre que root, ajoutez une ligne su myapp myapp pour que logrotate puisse le faire tourner en toute sécurité.
Le journal tourne tout seul dans la limite SystemMaxUse. Pour le réduire à la main, utilisez journalctl --vacuum-time=30d ou journalctl --vacuum-size=1G.
Centraliser les logs avec rsyslog
Les logs qui ne vivent que sur le serveur qu'ils décrivent ont deux faiblesses : vous devez vous connecter à chaque machine pour les lire, et un attaquant qui obtient root peut les modifier. Transférer les logs de chaque serveur vers un collecteur central résout les deux, et vous permet de chercher à un seul endroit pendant un incident. Le collecteur peut être un autre serveur RHEL sous rsyslog, ou une plateforme de logs comme Graylog.
Sur le collecteur
Créez /etc/rsyslog.d/10-collector.conf. Il écoute sur le port TCP 20514, que la politique SELinux étiquette déjà comme port syslog (vérifiez avec semanage port -l | grep syslogd), et écrit un fichier par hôte et par programme :
module(load="imtcp")
template(name="RemotePerHost" type="string"
string="/var/log/remote/%HOSTNAME:::secpath-replace%/%PROGRAMNAME:::secpath-replace%.log")
ruleset(name="remote") {
action(type="omfile" dynaFile="RemotePerHost")
}
input(type="imtcp" port="20514" ruleset="remote")
Ouvrez le port uniquement à vos serveurs, ici via la zone internal de firewalld, puis validez et redémarrez :
firewall-cmd --permanent --zone=internal --add-source=10.0.10.0/24
firewall-cmd --permanent --zone=internal --add-port=20514/tcp
firewall-cmd --reload
rsyslogd -N1
systemctl restart rsyslog
ss -tlnp | grep 20514
Si vous choisissez un port qui n'est pas déjà étiqueté, ajoutez-le d'abord avec semanage port -a -t syslogd_port_t -p tcp <port>, sur le collecteur et sur les émetteurs. Ajoutez une règle logrotate pour /var/log/remote//.log comme montré plus haut.
Sur chaque serveur
Créez /etc/rsyslog.d/90-central.conf. TCP avec une file assistée par disque signifie qu'un redémarrage du collecteur ou une coupure réseau retarde les messages au lieu de les perdre :
*.* action(type="omfwd" target="logs.example.net" port="20514" protocol="tcp"
template="RSYSLOG_SyslogProtocol23Format"
queue.type="LinkedList" queue.filename="fwd_central"
queue.maxDiskSpace="1g" queue.saveOnShutdown="on"
action.resumeRetryCount="-1")
rsyslogd -N1
systemctl restart rsyslog
Pour expédier aussi les événements d'audit, définissez active = yes dans /etc/audit/plugins.d/syslog.conf et redémarrez auditd avec service auditd restart (auditd n'accepte pas de redémarrage via systemctl).
Prouvez qu'ils arrivent
Envoyez un message de test et retrouvez-le sur le collecteur :
# on the server
logger -t logtest "central logging test from $(hostname)"
# on the collector
tail /var/log/remote/*/logtest.log
Répétez le test après chaque changement sur le collecteur ou le firewall, et alertez sur le silence : un serveur qui a cessé d'envoyer des logs est facile à manquer, parce que rien dans les logs ne vous le dit.
Une checklist quotidienne rapide
journalctl -p err -b: quelque chose de nouveau au niveau erreur depuis le démarrage ?aureport --login --failedetlastb | head: des connexions échouées inhabituelles ?ausearch -m AVC -ts today: des refus SELinux ?dnf history: quelque chose a changé que vous n'aviez pas prévu ?tail /var/log/nginx/error.loget le log d'erreurs de la base de données : des problèmes applicatifs ?journalctl --disk-usageetdf -h /var/log: de la place pour continuer à journaliser ?
Lire tout cela prend quelques minutes. L'automatiser, via un collecteur central et des alertes sur les motifs qui comptent, est ce qui transforme les logs d'une archive en alerte précoce.
Les ingénieurs d'EuroVPS construisent, exploitent et surveillent des chaînes de logs comme celle-ci pour des clients sur nos serveurs infogérés.
Extrait des archives du blog EuroVPS, publié pour la première fois le 19 avril 2020.
Toutes les notes de terrain