La rotation des logs chez les démons
J’ai dû récemment travailler sur une rotation de fichier de logs. Donc forcement : logrotate. Si c’est plutôt simple pour les logs d’une application web, ça l’est un peu moins vis-à-vis des démons, genre consommateur ou serveur web.
En effet, suite à une rotation, un démon garde le descripteur de l’ancien fichier en mémoire. Le démon ne log donc pas dans le nouveau fichier créé par logrotate
.
J'ai rencontré le problème pour Nginx et des services Supervisor.
Mais alors, comment le lui dire ?
En fouillant un peu, j’ai trouvé plusieurs solutions :
- Utiliser la directive
copytruncate
. - Utiliser la directive
postrotate
pour redémarrer le démon en question. - Toujours avec
postrotate
, utiliser les signauxSIGUSR1
etSIGUSR2
.
Copytruncate
Truncate the original log file in place after creating a copy, instead of moving the old log file and optionally creating a new one. It can be used when some program cannot be told to close its logfile and thus might continue writing (appending) to the previous log file forever. Note that there is a very small time slice between copying the file and truncating it, so some logging data might be lost.
—
man logrotate
Pas grand-chose d’autre à ajouter, la potentielle perte de données me gêne.
Postrotate : redémarrer le démon
postrotate
service nginx restart
C’est vrai que c’est tentant, mais là encore, me dire que l’on va accepter la coupure d’un nginx le temps de la rotation me gêne encore plus.
Postrotate : SIGUSR1 & SIGUSR2
Les signaux sont des moyens de communication interprocessus. Les usages les plus communs :
- Le
ctrl+c
pour terminer un processus, envoi unSIGINT
au processus - Quand vous voulez stopper un processus avec un
kill <pid>
, par défaut c’est unSIGTERM
- Et quand vous en avez marre :
kill -9 <pid>
, c’est unSIGKILL
que vous envoyez au processus
Il se trouve que la norme Posix définit 2 signaux, réservés à l’utilisateur. L’OS ne les enverra jamais. Certains outils déclenchent des comportements spécifiques à leur réception.
No Name Default Action Description 30 SIGUSR1 terminate process User defined signal 1 31 SIGUSR2 terminate process User defined signal 2
—
man signal
Je pense que vous me voyez venir, dans mon cas, Nginx et Supervisor, implémentent ces signaux :
SIGUSR2 supervisord will close and reopen the main activity log and all child log files.
USR2 upgrading an executable file
Le tout, traduit dans un fichier logrotate :
/var/log/<app_name>/*.log {
compress
daily
rotate 365
missingok
create
sharedscripts
postrotate
[ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`; \
[ ! -f /var/run/supervisord.pid ] || kill -USR2 `cat /var/run/supervisord.pid`; \
endscript
}
Je n’ai pas eu besoin de chercher pour d’autre outils, mais à priori la pratique est courante 🙂