Ubuntu 24.04 : logrotate ne tourne pas — l’erreur de configuration qui continue de piéger les gens

Cet article vous a aidé ?

Rien ne dit « vendredi soir » comme un disque qui se remplit parce qu’un fichier de logs a décidé qu’il est en fait une base de données maintenant. Vous vérifiez /etc/logrotate.d/, vous voyez une section pour le service, et pourtant le fichier continue de grossir. Pas de rotations, pas de compression, aucune pitié.

Sur Ubuntu 24.04, la raison la plus courante pour laquelle logrotate « ne tourne pas » n’est pas systemd, pas un bug du noyau, pas les rayons cosmiques. C’est une seule erreur de configuration : vous avez oublié de spécifier un déclencheur de rotation (daily/weekly/monthly/hourly ou size) et vous avez supposé qu’un paramètre global par défaut vous sauverait. Il ne le fera pas. Logrotate lira votre section, haussera les épaules poliment et ne fera rien — pour toujours.

La seule erreur : pas de déclencheur, pas de rotation

Logrotate ne fait pas de rotation « parce qu’un fichier existe » ou « parce que j’ai écrit un fichier de configuration ». Il effectue la rotation quand une section lui dit quand tourner. Ce « quand » est un déclencheur de rotation :

  • daily, weekly, monthly, yearly, ou (sur beaucoup de distributions) hourly
  • size (et compagnons comme minsize, maxsize)

Si votre fichier par service dans /etc/logrotate.d/ ne spécifie pas de déclencheur, vous dépendez de l’héritage. Et c’est là que les gens se font piéger : les valeurs globales d’Ubuntu peuvent ne pas fournir un calendrier d’une manière qui s’applique à votre section (ou le fichier n’est pas lu, ou vous le remplacez involontairement). Résultat net : logrotate s’exécute, ne voit aucune raison de tourner, n’actualise rien, et sort avec 0 comme si c’était un service rendu.

À quoi ressemble la configuration cassée

Ceci est la section classique « ça a l’air correct en revue de code, ça échoue en production ». Remarquez ce qui manque :

cr0x@server:~$ sudo sed -n '1,120p' /etc/logrotate.d/myapp
/var/log/myapp/myapp.log {
  rotate 7
  compress
  missingok
  notifempty
  create 0640 myapp adm
  postrotate
    systemctl kill -s HUP myapp.service
  endscript
}

Cette config contient rotate 7, qui dit seulement « garder sept anciens logs » si une rotation a lieu. Elle ne dit pas quand la rotation doit avoir lieu. Si vous ne spécifiez pas daily (ou similaire) ou size, logrotate ne peut pas prendre de décision de rotation.

À quoi ressemble la configuration corrigée

Ajoutez un déclencheur explicite. Choisissez-en un. Ne laissez pas le lecteur deviner.

cr0x@server:~$ sudo sed -n '1,120p' /etc/logrotate.d/myapp
/var/log/myapp/myapp.log {
  daily
  rotate 7
  compress
  missingok
  notifempty
  create 0640 myapp adm
  postrotate
    systemctl kill -s HUP myapp.service
  endscript
}

Si vous préférez une rotation basée sur la taille (souvent mieux pour les applications bavardes) :

cr0x@server:~$ sudo sed -n '1,120p' /etc/logrotate.d/myapp
/var/log/myapp/myapp.log {
  size 200M
  rotate 10
  compress
  delaycompress
  missingok
  notifempty
  create 0640 myapp adm
}

Rendez le déclencheur explicite même si vous pensez qu’il est « évident ». En production, les suppositions évidentes passent à la caisse.

Mode opératoire de diagnostic rapide (premier/deuxième/troisième)

Quand logrotate « ne tourne pas », vous voulez localiser rapidement le goulot : s’agit-il de la planification, de l’analyse, de l’éligibilité, des permissions ou d’un échec postrotate ?

Premier : confirmer que logrotate est bien invoqué

  • Vérifiez le statut du timer/service systemd et l’heure du dernier lancement.
  • Consultez le journal pour trouver les exécutions et les erreurs de logrotate.

Second : exécuter logrotate en mode debug pour la configuration spécifique

  • Utilisez -d (debug) et -v (verbose) pour voir l’arbre de décision.
  • Cherchez des lignes comme « log does not need rotating » et pourquoi.

Troisième : vérifier le fichier d’état et la logique du déclencheur

  • Inspectez /var/lib/logrotate/status (ou variante distro) pour voir ce que logrotate pense avoir fait la dernière fois.
  • Validez que votre section contient un déclencheur (daily/weekly/size, etc.).
  • Confirmez que les chemins de fichiers correspondent à la réalité (y compris les jokers) et que les permissions permettent la rotation.

Si vous ne faites qu’une seule chose : exécutez logrotate avec -d -v et lisez-le comme un enregistreur de vol. Il est généralement embarrassant d’honnêteté.

Comment logrotate décide réellement de tourner (réalité Ubuntu 24.04)

Le travail de logrotate est simple : pour chaque fichier de logs, décider si une rotation est nécessaire ; si oui, renommer/tronquer/copier, éventuellement compresser, et exécuter des scripts. Le diable se cache dans le fichier d’état et les déclencheurs.

Planification sur Ubuntu 24.04 : timers systemd, pas cron

Sur les Ubuntu modernes, logrotate est généralement lancé via un timer systemd (et non via un job cron.daily classique). Cela change l’endroit où vous regardez quand vous déboguez un « ça ne s’exécute jamais ». Cela change aussi la façon dont les exécutions « manquées » se comportent : les timers peuvent rattraper selon la configuration.

Le fichier d’état est la mémoire sur laquelle logrotate s’appuie

Logrotate n’est pas un démon en continu. Il s’exécute, prend des décisions et s’arrête. Pour éviter de tout faire tourner à chaque fois, il stocke les horodatages de dernière rotation dans un fichier d’état (souvent /var/lib/logrotate/status). Si ce fichier indique qu’un log a été tourné « aujourd’hui », une section daily ne tournera pas juste parce que vous êtes inquiet.

Les déclencheurs ne sont pas optionnels

Logrotate n’infère pas un calendrier de rotation à partir de rotate N, compress ou create. Ce sont des actions. Les déclencheurs sont séparés. L’absence de déclencheur est le mode d’échec silencieux parce que ce n’est pas une « erreur de syntaxe ». C’est juste « aucune condition satisfaite ».

Idée paraphrasée de Richard Cook : « Le succès cache les arêtes vives du système ; l’échec révèle comment le travail est réellement fait. » Voilà le débogage de logrotate en une phrase.

Blague #1 : Logrotate est comme une rotation de vigile : si vous ne définissez jamais l’horaire, quelqu’un en souffrira toujours — juste pas le logiciel.

Tâches pratiques : commandes, sorties, décisions (12+)

Voici des tâches concrètes que j’utilise en réponse à incident. Chacune inclut : la commande, ce que signifie la sortie, et la décision à en tirer.

Tâche 1 : Confirmer que le timer existe et est activé

cr0x@server:~$ systemctl status logrotate.timer
● logrotate.timer - Daily rotation of log files
     Loaded: loaded (/usr/lib/systemd/system/logrotate.timer; enabled; preset: enabled)
     Active: active (waiting) since Sat 2025-12-28 07:10:22 UTC; 2h 14min ago
    Trigger: Sun 2025-12-29 00:00:00 UTC; 14h left
   Triggers: ● logrotate.service

Signification : S’il est activé et « Active (waiting) », la planification est probablement correcte.

Décision : S’il est désactivé/manquant, corrigez la planification d’abord. S’il est activé, passez aux vérifications d’exécution/service et de journal.

Tâche 2 : Confirmer la dernière exécution du service et le code de sortie

cr0x@server:~$ systemctl status logrotate.service
● logrotate.service - Rotate log files
     Loaded: loaded (/usr/lib/systemd/system/logrotate.service; static)
     Active: inactive (dead) since Sat 2025-12-28 00:00:04 UTC; 9h ago
    Process: 1042 ExecStart=/usr/sbin/logrotate /etc/logrotate.conf (code=exited, status=0/SUCCESS)

Signification : Le statut 0 signifie que logrotate n’a pas planté ; il se peut qu’il n’ait tout simplement rien tourné.

Décision : Si le statut est non nul, inspectez les logs ; si succès, passez en mode debug pour comprendre pourquoi il a ignoré la rotation.

Tâche 3 : Inspecter le journal pour les messages de logrotate

cr0x@server:~$ journalctl -u logrotate.service -n 50 --no-pager
Dec 28 00:00:01 server systemd[1]: Starting logrotate.service - Rotate log files...
Dec 28 00:00:04 server systemd[1]: logrotate.service: Deactivated successfully.
Dec 28 00:00:04 server systemd[1]: Finished logrotate.service - Rotate log files.

Signification : Pas d’erreurs ici, mais pas non plus beaucoup de détails. C’est normal ; logrotate n’écrit sur stdout que lorsqu’il est en verbose/debug.

Décision : Lancez un debug manuel ensuite.

Tâche 4 : Simulation (dry-run) de logrotate en verbose + debug

cr0x@server:~$ sudo logrotate -d -v /etc/logrotate.conf
reading config file /etc/logrotate.conf
including /etc/logrotate.d
reading config file /etc/logrotate.d/myapp
Handling 1 logs
rotating pattern: /var/log/myapp/myapp.log  after 1 days (7 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/myapp/myapp.log
  log does not need rotating (log has been already rotated)

Signification : Cela vous dit ce que logrotate pense être le déclencheur (« after 1 days ») et pourquoi il saute (« already rotated »).

Décision : Si la ligne de déclenchement manque ou semble étrange, inspectez la section. Si « already rotated », vérifiez le fichier d’état.

Tâche 5 : Debug pour un fichier unique (scope réduit)

cr0x@server:~$ sudo logrotate -d -v /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
error: /etc/logrotate.d/myapp:2 unknown option 'rotato'

Signification : Le debug par fichier attrape rapidement les fautes de frappe et erreurs de parsing.

Décision : Corrigez les erreurs de syntaxe avant de poursuivre le comportement runtime.

Tâche 6 : Valider que la section inclut un déclencheur (le contrôle « une erreur »)

cr0x@server:~$ sudo egrep -n 'daily|weekly|monthly|yearly|hourly|size|minsize|maxsize' /etc/logrotate.d/myapp || echo "NO TRIGGER FOUND"
NO TRIGGER FOUND

Signification : Aucun mot-clé de déclencheur trouvé. C’est le classique « rotate mais ne tourne jamais ».

Décision : Ajoutez daily ou size explicitement et relancez le debug.

Tâche 7 : Inspecter l’entrée du fichier d’état pour votre log

cr0x@server:~$ sudo grep -F '/var/log/myapp/myapp.log' /var/lib/logrotate/status
"/var/log/myapp/myapp.log" 2025-12-28-0:0:0

Signification : Logrotate croit l’avoir tourné à minuit aujourd’hui. Si vous vous attendez à ce qu’il tourne maintenant, votre attente est le bug.

Décision : Si l’horodatage semble faux, investiguez les changements d’heure, la corruption d’état ou les chemins dupliqués. Ne supprimez pas le fichier d’état à la légère en production.

Tâche 8 : Confirmer la taille réelle du fichier et son heure de modification

cr0x@server:~$ ls -lh --time-style=long-iso /var/log/myapp/myapp.log
-rw-r----- 1 myapp adm 12G 2025-12-28 09:19 /var/log/myapp/myapp.log

Signification : Le fichier est énorme et est encore écrit. Si vous utilisez uniquement une rotation basée sur le temps, vous pouvez avoir raison mais vous êtes opérationnellement condamné.

Décision : Envisagez size ou maxsize en plus des déclencheurs temporels.

Tâche 9 : Vérifier le propriétaire du log et les permissions du répertoire

cr0x@server:~$ namei -l /var/log/myapp/myapp.log
f: /var/log/myapp/myapp.log
drwxr-xr-x root root /
drwxr-xr-x root root var
drwxrwxr-x root syslog log
drwxr-x--- myapp adm myapp
-rw-r----- myapp adm myapp.log

Signification : Le répertoire de logs n’est pas lisible par « others » ; logrotate s’exécute en root (habituellement), donc ça va. Mais si vous avez mal configuré su, les permissions peuvent bloquer la rotation.

Décision : Si les permissions empêchent le renommage/la création, corrigez la propriété/le mode ou utilisez la directive su user group appropriée.

Tâche 10 : Détecter les échecs du script postrotate (la raison cachée pour laquelle rien ne change)

cr0x@server:~$ sudo logrotate -v /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
rotating pattern: /var/log/myapp/myapp.log  after 1 days (7 rotations)
considering log /var/log/myapp/myapp.log
  log needs rotating
rotating log /var/log/myapp/myapp.log, log->rotateCount is 7
renaming /var/log/myapp/myapp.log to /var/log/myapp/myapp.log.1
creating new /var/log/myapp/myapp.log mode = 0640 uid = 123 gid = 4
running postrotate script
error: error running shared postrotate script for '/var/log/myapp/myapp.log '

Signification : La rotation a peut-être eu lieu, mais votre étape de signal/reload a échoué. Certaines applis continuent d’écrire sur l’ancien inode ; d’autres ont besoin d’un HUP pour rouvrir les logs.

Décision : Corrigez le postrotate ; sinon vous « tournerez » et continuerez de remplir le disque car le processus écrit dans un descripteur de fichier non référencé.

Tâche 11 : Rechercher la situation redoutée « supprimé mais encore ouvert »

cr0x@server:~$ sudo lsof +L1 | head
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NLINK     NODE NAME
myapp    2210 myapp   7w   REG  252,0 12884901888     0  393502 /var/log/myapp/myapp.log (deleted)

Signification : Le fichier est supprimé/roté, mais le processus écrit encore sur l’ancien descripteur. L’usage disque ne diminuera pas.

Décision : Corrigez votre stratégie de réouverture : HUP, reload, ou utilisez copytruncate en dernier recours (avec prudence).

Tâche 12 : Vérifier que le timer s’est réellement déclenché quand vous le pensez

cr0x@server:~$ systemctl list-timers --all | grep -F logrotate
Sun 2025-12-29 00:00:00 UTC 14h left Sat 2025-12-28 00:00:01 UTC 9h ago logrotate.timer logrotate.service

Signification : La dernière exécution était à minuit ; la prochaine aussi. Si votre log a explosé à 09:00, une rotation quotidienne basée sur le temps ne vous sauvera pas.

Décision : Ajoutez des seuils de taille ou augmentez la fréquence d’exécution (avec prudence).

Tâche 13 : Forcer une rotation ponctuelle (en sécurité) pour valider le mécanisme

cr0x@server:~$ sudo logrotate -f -v /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
rotating pattern: /var/log/myapp/myapp.log  forced from command line (7 rotations)
considering log /var/log/myapp/myapp.log
  log needs rotating
renaming /var/log/myapp/myapp.log to /var/log/myapp/myapp.log.1
creating new /var/log/myapp/myapp.log mode = 0640 uid = 123 gid = 4

Signification : Les mécanismes fonctionnent : renommage/création/permissions sont corrects.

Décision : Si la rotation forcée fonctionne mais la planifiée non, c’est un problème de déclencheur/état/planification, pas de permissions.

Tâche 14 : Vérifier l’ordre d’inclusion et si votre fichier est lu

cr0x@server:~$ sudo grep -nE '^(include|#include)|/etc/logrotate\.d' /etc/logrotate.conf
12:include /etc/logrotate.d

Signification : Si l’include manque, rien dans /etc/logrotate.d n’a d’effet.

Décision : Restaurez la ligne d’include si quelqu’un a « simplifié » la configuration globale.

Tâche 15 : Tester le parsing de la config sans exécuter de rotations (sanity check)

cr0x@server:~$ sudo logrotate -d /etc/logrotate.conf | tail -n 20
considering log /var/log/myapp/myapp.log
  Now: 2025-12-28 09:24
  Last rotated at 2025-12-28 00:00
  log does not need rotating

Signification : Le mode debug affiche « Now » et « Last rotated ». Si ceux-ci sont incohérents, suivez la piste temps/état.

Décision : Si « Last rotated » est dans le futur, vous avez probablement un décalage horaire, un snapshot VM restauré, ou un fichier d’état copié.

Erreurs courantes : symptômes → cause → correction

1) « J’ai mis rotate 30 mais ça ne tourne jamais »

Symptôme : Le fichier grossit sans fin ; logrotate rapporte le succès ; aucun fichier tourné n’existe.

Cause : Pas de directive de déclenchement (daily/weekly/size).

Correction : Ajoutez un déclencheur explicitement. Préférez size pour les logs à fort volume ; conservez le temps pour l’alignement de rétention.

2) « Logrotate s’exécute, mais affiche ‘log does not need rotating’ alors que le fichier est énorme »

Symptôme : Un fichier de 20G ; le debug dit qu’il ne faut pas tourner.

Cause : Vous avez configuré uniquement daily et il a déjà tourné aujourd’hui ; ou le fichier d’état indique qu’il a déjà été tourné.

Correction : Ajoutez maxsize ou size. Ou augmentez la fréquence de rotation. Ne combattez pas le fichier d’état ; concevez autour.

3) « Des fichiers tournés existent, mais l’usage disque ne baisse jamais »

Symptôme : Vous voyez myapp.log.1, pourtant df reste mauvais.

Cause : Le processus garde l’ancien inode ouvert ; les logs vont vers un descripteur marqué (deleted).

Correction : Assurez-vous que le processus rouvre les logs (HUP/reload) ou utilisez copytruncate si l’appli ne peut pas rouvrir (en acceptant la perte/le risque de course).

4) « logrotate -f marche manuellement, la rotation planifiée non »

Symptôme : La rotation forcée fonctionne ; le timer quotidien ne fait rien.

Cause : Planification qui ne se déclenche pas, timer désactivé, include manquant, ou fichier d’état disant que c’était déjà fait.

Correction : Vérifiez systemctl list-timers, assurez-vous que /etc/logrotate.conf inclut /etc/logrotate.d, inspectez /var/lib/logrotate/status.

5) « Erreurs de rotation : permission denied »

Symptôme : Le mode debug/verbose montre des échecs de rename/create.

Cause : Propriétaire/mode incorrect ; répertoire de logs non inscriptible ; mauvaise utilisation de su ; ou logs sur un montage aux restrictions spéciales.

Correction : Corrigez les permissions du système de fichiers. Si vous utilisez su, assurez-vous que user/group correspondent au propriétaire du fichier et que le répertoire permet la rotation.

6) « Ça tourne, mais l’appli arrête de logger »

Symptôme : Après rotation, le fichier de logs reste vide et l’application tourne toujours.

Cause : L’appli continue d’écrire sur l’ancien fd ; le nouveau fichier existe mais n’est pas utilisé ; postrotate ne signale pas correctement.

Correction : Utilisez l’action postrotate correcte : HUP, reload, ou commande spécifique au service. Validez avec lsof.

7) « J’ai utilisé des jokers et rien ne se passe »

Symptôme : La section référence /var/log/myapp/*.log ; aucune rotation.

Cause : Le motif ne matche rien ; les permissions empêchent l’expansion du glob ; ou les logs sont dans un chemin différent de celui attendu.

Correction : Confirmez les correspondances avec ls. Utilisez des chemins explicites pour les logs critiques.

8) « Après une restauration d’image, logrotate ne tourne plus pendant des jours »

Symptôme : Le debug dit que la dernière rotation est dans le futur.

Cause : Fichier d’état copié d’une autre machine/temps ; snapshot VM restauré ; changements d’horloge.

Correction : Corrigez d’abord l’heure. Puis ajustez l’entrée d’état avec précaution (éditez seulement la ligne affectée), ou forcez une rotation unique avec -f et vérifiez la mise à jour de l’état.

Trois mini-récits d’entreprise depuis le terrain

Incident #1 : la mauvaise hypothèse (« rotate 14 signifie tous les 14 jours, non ? »)

Une entreprise SaaS de taille moyenne avait un petit service interne qui émettait des logs JSON. Il a tourné des mois sans problème parce que personne ne regardait l’utilisation de l’espace disque racine du nœud sauf en cas d’alerte. Le service a reçu une fonctionnalité qui a doublé le volume des logs — rien de dramatique, juste plus de champs contextuels.

Deux semaines plus tard, un ingénieur on-call a vu l’utilisation disque d’un nœud de production à 97 %. Ils ont trouvé /var/log/internal/worker.log à plusieurs dizaines de gigaoctets. Il y avait une section logrotate avec rotate 14, compress, create, et notifempty. Ça semblait « configuré ». Tout le monde a supposé que « rotate 14 » signifiait « tourner tous les 14 jours ». Ce n’est pas le cas.

Le timer tournait. Logrotate sortait 0. Aucune rotation. La configuration n’avait ni daily, ni weekly, ni size. C’était une politique sans déclencheur — comme écrire « garder 14 sauvegardes » sans jamais exécuter la sauvegarde.

Ils ont ajouté daily et maxsize 500M, forcé une rotation pour respirer, puis corrigé leurs seuils de monitoring pour alerter sur la croissance des logs avant la panique du système de fichiers.

Le postmortem fut poli mais tranchant : « Nous avons supposé que logrotate avait un planning par défaut. Nous n’avons pas testé le comportement de rotation en staging avec un volume réaliste de logs. » C’est toute l’histoire, et elle se répète partout.

Incident #2 : l’optimisation qui s’est retournée contre eux (copytruncate partout)

Une entreprise régulée avait une appli Java legacy qui ne rouvrait pas proprement les logs sur HUP. Quelqu’un « a résolu » ça il y a des années avec copytruncate. Ça a assez bien marché pour devenir le pattern par défaut pour les nouveaux services — copytruncate pour tout, toujours.

Puis la société a migré les charges vers des NVMe plus rapides et augmenté le débit. Leur service le plus chargé écrivait plusieurs gigaoctets par heure. La rotation a commencé à durer assez longtemps pour que la fenêtre de troncature ait de l’impact, et ils ont commencé à perdre des lignes de log. Pas « peut-être » ; prouvé. Leur piste d’audit avait des lacunes précisément aux frontières de rotation.

Pire : la compression s’exécutait immédiatement, écrasant le CPU pendant les heures de pointe. L’« optimisation » a créé une falaise de performance : pendant la rotation, le CPU montait en flèche, augmentant la latence des requêtes, entraînant des retries, produisant davantage de logs, ce qui augmentait encore la rotation. Une jolie boucle de rétroaction auto-infligée.

Ils sont revenus en arrière : passage à la rotation par renommage (pas de copytruncate) et correction de l’appli pour qu’elle rouvre les logs correctement sur signal. Ils ont aussi ajouté delaycompress pour éloigner la compression du moment critique. Ce n’était pas du travail glamour. C’était du travail correct.

Blague #2 : « Nous avons utilisé copytruncate pour éviter de toucher à l’appli » est l’équivalent logging de réparer une fuite en achetant une serpillière plus grande.

Incident #3 : la pratique ennuyeuse qui a sauvé la mise (déclencheurs explicites + tests forcés)

Une petite équipe plateforme gérait des dizaines de services internes, surtout Go et Python, sur Ubuntu. Ils avaient une habitude qu’on trouvait péniblement pointilleuse : chaque section logrotate avait un déclencheur explicite et un commentaire expliquant pourquoi. Pas d’héritage. Pas de dépendance à /etc/logrotate.conf. Chaque section : daily ou size (souvent les deux via maxsize), toujours intentionnel.

Ils avaient aussi dans la checklist de déploiement : après le déploiement d’un nouveau service, exécuter logrotate -d -v sur sa section et coller l’extrait de sortie dans le dossier de changement. Ça ressemblait à de la bureaucratie jusqu’à ce qu’un changement d’image de base modifie quelques valeurs globales et que certains services atterrissent sur de nouveaux nœuds.

Les services avec déclencheurs explicites ont tourné normalement. Ceux qui dépendaient de l’héritage (des configs d’autres équipes) sont devenus étranges : certains tournaient hebdomadairement alors qu’on attendait quotidiennement ; d’autres ne tournaient que quand la taille atteignait un seuil par défaut que personne ne se rappelait avoir défini. L’équipe plateforme n’a pas eu d’incident. Ils ont eu un mardi légèrement pénible.

La différence n’était pas magique. C’était la pratique ennuyeuse de rendre « quand tourner » explicite, puis de tester le comportement une fois, comme vous testeriez une règle de firewall ou une sauvegarde. C’est ça le professionnalisme en ops : prévenir les surprises, pas y réagir héroïquement.

Faits intéressants et contexte (pourquoi ça revient)

  1. Logrotate date d’avant systemd. Il a grandi dans un monde piloté par cron, et le passage aux timers systemd a changé l’endroit où on cherche quand il échoue.
  2. Le fichier d’état est le cœur de la « mémoire » de logrotate. Sans lui, la rotation basée sur le temps tournerait soit tout le temps, soit il faudrait des heuristiques sur les métadonnées du système de fichiers.
  3. rotate N est la rétention, pas la planification. C’est l’erreur conceptuelle la plus courante — parce que le mot « rotate » porte trop de sens.
  4. Beaucoup de distros livrent une config globale qui semble définir des valeurs par défaut. Les gens supposent que ces défauts incluent un déclencheur. Parfois oui ; parfois non ; parfois votre section les remplace ; parfois votre fichier n’est pas inclus du tout.
  5. Journald a réduit la dépendance aux logs fichiers pour certains services. Mais beaucoup d’applis écrivent encore dans des fichiers (compatibilité, conformité, ou parce que l’image conteneur vient de 2016 et que personne ne veut y toucher).
  6. Copytruncate s’est popularisé parce que « ça marche » avec des applis réticentes. Il introduit aussi des races et des pertes potentielles sous charge car on peut écrire pendant la copie.
  7. La compression était autrefois assez coûteuse pour être planifiée. Sur les CPU modernes c’est moins cher, mais ça compte encore quand vous compressez des logs de plusieurs gigaoctets en heure de pointe.
  8. Renommer des logs est atomique ; la troncature ne l’est pas. L’approche par renommage s’aligne avec le comportement des descripteurs Unix et est généralement plus sûre quand les applis rouvrent correctement les logs.
  9. Les configurations logrotate sont trompeusement permissives. Beaucoup de mauvaises configurations ne sont pas des erreurs de syntaxe ; ce sont des erreurs de logique qui résultent en « ne rien faire avec succès ».

Listes de contrôle / plan étape par étape

Étape par étape : faire marcher la rotation pour un log problématique

  1. Confirmer que la planification existe.

    cr0x@server:~$ systemctl status logrotate.timer
    ● logrotate.timer - Daily rotation of log files
         Loaded: loaded (/usr/lib/systemd/system/logrotate.timer; enabled; preset: enabled)
         Active: active (waiting) since Sat 2025-12-28 07:10:22 UTC; 2h 14min ago
        Trigger: Sun 2025-12-29 00:00:00 UTC; 14h left
       Triggers: ● logrotate.service

    Décision : Si désactivé, activez-le. Si activé, continuez.

  2. Vérifier que votre config est incluse.

    cr0x@server:~$ sudo grep -n 'include /etc/logrotate.d' /etc/logrotate.conf
    12:include /etc/logrotate.d

    Décision : Si manquant, restaurez l’include et retestez.

  3. Exécuter le debug pour cette section.

    cr0x@server:~$ sudo logrotate -d -v /etc/logrotate.d/myapp | sed -n '1,120p'
    reading config file /etc/logrotate.d/myapp
    Handling 1 logs
    considering log /var/log/myapp/myapp.log
      log does not need rotating

    Décision : S’il ne mentionne pas de calendrier/taille, vous n’avez probablement pas de déclencheur.

  4. Ajouter un déclencheur explicite.

    Choisissez : temporel (daily) ou basé sur le volume (size / maxsize). Pour les logs à fort volume, la rotation basée sur la taille est souvent le choix mature.

  5. Forcer une rotation une fois pour valider le mécanisme.

    cr0x@server:~$ sudo logrotate -f -v /etc/logrotate.d/myapp | tail -n 30
    considering log /var/log/myapp/myapp.log
      log needs rotating
    renaming /var/log/myapp/myapp.log to /var/log/myapp/myapp.log.1
    creating new /var/log/myapp/myapp.log mode = 0640 uid = 123 gid = 4

    Décision : Si la rotation forcée échoue, corrigez permissions/chemins avant d’accuser la planification.

  6. Vérifier que l’application écrit bien dans le nouveau log.

    cr0x@server:~$ sudo lsof /var/log/myapp/myapp.log | head
    COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    myapp   2210 myapp   7w   REG  252,0   123456  401 /var/log/myapp/myapp.log

    Décision : Si elle écrit toujours dans un inode supprimé, corrigez le postrotate ou le comportement de réouverture de l’appli.

Checklist opérationnelle : ce que j’attends dans une section prête pour la production

  • Un déclencheur explicite : daily ou size/maxsize.
  • Une rétention explicite : rotate N plus compress et généralement delaycompress.
  • Création correcte : create MODE USER GROUP ou compter sur l’appli pour créer en connaissance de cause.
  • Stratégie de réouverture sûre : postrotate signal/reload, validée avec lsof.
  • Ne pas dépendre de l’héritage sauf si vous l’avez testé et que vous pouvez l’expliquer à quelqu’un à moitié réveillé.
  • Garde-fous de taille pour les services bavards : maxsize empêche qu’une rotation quotidienne arrive trop tard.

FAQ

1) Pourquoi logrotate sort-il avec succès même lorsqu’il ne tourne rien ?

Parce que « aucun log nécessitant une rotation » est un résultat valide. Logrotate est un moteur de politique, pas un job « doit tourner quelque chose ». Le problème survient quand vous vous attendiez à une rotation mais que vous n’avez pas fourni de déclencheur ou que votre état/critères disent « pas encore ».

2) L’« une erreur de config » est-ce vraiment juste l’absence de daily ou size ?

Oui, dans le sens pratique : l’absence d’un déclencheur (ou penser que rotate N est un déclencheur) est la cause la plus fréquente de non-rotation silencieuse. Les erreurs de syntaxe crient ; les déclencheurs manquants chuchotent.

3) Devrais-je utiliser une rotation temporelle ou basée sur la taille ?

Pour un volume faible à modéré, daily suffit. Pour un fort volume, utilisez size ou maxsize (souvent en complément de daily) pour ne pas attendre minuit pour arrêter un log qui s’emballe.

4) Quelle est la différence entre size, minsize et maxsize ?

size tourne quand le fichier dépasse cette taille (indépendamment du calendrier). minsize ajoute un seuil minimal de taille à une rotation basée sur le temps. maxsize force la rotation quand la taille dépasse une limite même si les critères temporels ne sont pas encore remplis.

5) Quand devrais-je utiliser copytruncate ?

Lorsque l’application ne peut pas rouvrir les logs et que vous ne pouvez pas la corriger rapidement. C’est un hack de compatibilité avec des compromis : perte possible aux frontières de rotation et IO supplémentaire. Préférez renommage + signal/réouverture pour la justesse.

6) Pourquoi l’usage disque reste-t-il élevé après rotation ?

Parce que le processus peut continuer d’écrire dans un descripteur de fichier supprimé. Le système de fichiers ne libère l’espace que lorsque le dernier handle est fermé. Utilisez lsof +L1 pour le détecter et corrigez la stratégie de réouverture.

7) Puis-je supprimer /var/lib/logrotate/status pour « réinitialiser » les choses ?

Vous pouvez, mais c’est brutal. Cela peut provoquer des rotations inattendues sur de nombreux logs au prochain run. Plus sûr : éditez seulement l’entrée affectée, ou forcez la rotation pour une configuration spécifique avec logrotate -f et vérifiez le comportement.

8) Pourquoi ma section logrotate fonctionne dans un environnement mais pas dans un autre ?

Différents défauts globaux, comportement d’inclusion différent, timers différents, propriété de fichiers différente, et comportement de réouverture d’appli différent. La correction est ennuyeuse : rendre les déclencheurs explicites, tester avec -d -v, et valider avec lsof.

9) J’ai ajouté daily mais ça ne tourne toujours pas. Et maintenant ?

Vérifiez l’entrée du fichier d’état et la sortie debug. Si elle dit « already rotated », vous attendez le prochain jour. Si le timer ne se déclenche pas, corrigez la planification systemd. Si les permissions échouent, corrigez la propriété/le mode ou le su.

10) Devrais-je faire une rotation horaire sur Ubuntu 24.04 ?

Seulement si c’est vraiment nécessaire. Une rotation horaire augmente le churn (plus de fichiers, plus de compression, plus de métadonnées). Si votre problème est que le disque se remplit avant minuit, maxsize est souvent le levier préférable.

Prochaines étapes (quoi changer lundi matin)

Si vous êtes confronté à logrotate qui ne tourne pas sur Ubuntu 24.04, faites ceci dans l’ordre :

  1. Rendez le déclencheur explicite dans chaque section personnalisée : ajoutez daily ou size/maxsize. Cessez de compter sur l’héritage.
  2. Exécutez logrotate -d -v sur le fichier exact qui vous préoccupe et lisez les lignes de justification. Ne devinez pas.
  3. Vérifiez l’entrée du fichier d’état pour le log et confirmez qu’elle correspond à votre attente de « dernière rotation ». Corrigez le décalage horaire avant tout.
  4. Validez le comportement de réouverture avec lsof +L1. Si vous voyez (deleted), vos rotations sont cosmétiques.
  5. Ajoutez des garde-fous de taille pour les services bavards. La rotation quotidienne n’est pas un système de sécurité ; c’est un événement calendaire.

L’objectif n’est pas « que les logs tournent ». L’objectif est « que les logs tournent de manière prévisible, sans perte d’événements, sans pics CPU surprises, et sans vous réveiller ». Voilà le standard.

← Précédent
MySQL vs MariaDB : tables temporaires sur disque — comment les arrêter vraiment
Suivant →
ZFS zpool iostat -w : Comprendre les schémas de charge en temps réel

Laisser un commentaire