Logrotate réussi, le fichier d'origine reprend sa taille d'origine

11

Quelqu'un a-t-il déjà rencontré des problèmes avec logrotate qui provoquent la rotation d'un fichier journal, puis le retour à la même taille qu'il était à l'origine? Voici mes conclusions:

Script Logrotate:

/var/log/mylogfile.log {
    tourner 7
    du quotidien
    compresse
    olddir / log_archives
    missingok
    notifempty
    copiertronquer
}

Sortie détaillée de Logrotate:

copie de /var/log/mylogfile.log vers /log_archives/mylogfile.log.1
tronquer /var/log/mylogfile.log
compression du journal avec: / bin / gzip
suppression de l'ancien journal /log_archives/mylogfile.log.8.gz

Le fichier journal après la troncature se produit

[root @ server ~] # ls -lh /var/log/mylogfile.log
-rw-rw-r-- 1 part1 part1 0 jan 11 17:32 /var/log/mylogfile.log

Littéralement quelques secondes plus tard:

[root @ server ~] # ls -lh /var/log/mylogfile.log
-rw-rw-r-- 1 partie1 partie1 3.5G 11 janvier 17:32 /var/log/mylogfile.log

Version RHEL:

[root @ server ~] # cat / etc / redhat-release 
Red Hat Enterprise Linux ES version 4 (Nahant Update 4)

Version de Logrotate:

[root @ DAA21529WWW370 ~] # rpm -qa | grep logrotate
logrotate-3.7.1-10.RHEL4

Quelques notes:

  • Le service ne peut pas être redémarré à la volée, c'est pourquoi j'utilise copytruncate
  • Les journaux tournent chaque nuit, selon le olddirrépertoire contenant les fichiers journaux de chaque nuit.
drewrockshard
la source

Réponses:

18

Cela est probablement dû au fait que même si vous tronquez le fichier, le processus d'écriture dans le fichier continuera à écrire quel que soit le décalage. Donc, ce qui se passe, c'est que logrotate tronque le fichier, la taille est nulle, le processus écrit à nouveau dans le fichier, en continuant le décalage qu'il a laissé, et vous avez maintenant un fichier avec NULL-bytes jusqu'au point où vous l'avez tronqué plus le nouveau entrées écrites dans le journal.

od -c après tronquer + croissance soudaine, a généré une sortie selon:

0000000  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
33255657600  \0   C   K   B   -   s   e   r   v   e   r       [   h   t   t
33255657620 <more log output>

Ce que cela indique, c'est du décalage 0 à 33255657600, votre fichier se compose d'octets nuls, puis de données lisibles. Arriver à cet état ne prend pas le même temps qu'il faudrait pour écrire réellement tous ces octets nuls. Les systèmes de fichiers ext {2,3,4} prennent en charge quelque chose appelé fichiers épars, donc si vous recherchez au-delà d'une région d'un fichier qui ne contient rien, cette région sera supposée contenir des octets nuls et ne prendra pas d'espace sur le disque. Ces octets nuls ne seront pas réellement écrits, juste supposés être là, donc le temps nécessaire pour passer de 0 à 3,5 Go ne prend pas beaucoup de temps. (Vous pouvez tester le temps qu'il faut en faisant quelque chose comme dd if=${HOME}/.bashrc of=largefile.bin seek=3432343264 bs=1, cela devrait générer un fichier de plus de 3 Go en quelques millisecondes).

Si vous exécutez ls -lsvos fichiers journaux après qu'ils ont été tronqués et ont connu une croissance soudaine, il devrait maintenant signaler un nombre au début de la ligne qui représente la taille réelle (en blocs occupés sur le disque), qui est probablement un ordre de grandeur plus petit que la taille rapportée par juste ls -l.

Kjetil Joergensen
la source
Je ne pense pas - en quelques secondes, le fichier journal passe de 0 octet à 3,5 Go. Le temps total nécessaire pour terminer le logrotate est d'environ 5 minutes. Les fichiers journaux ne sont pas écrits à cette vitesse ET la taille est toujours la taille d'origine, ce qui semble trop fortuit.
drewrockshard
Il devrait y avoir un moyen simple de le vérifier, d'inspecter le fichier et de voir s'il contient réellement quelque chose. Commencez par exécuter od -c filename | head -n 100. Il y a de fortes chances que cela vous indique en quelques lignes qu'il y a un chargement de camions de zéro octet, plus les dernières entrées de journal.
Kjetil Joergensen
Si tel est le cas, pouvons-nous tester si cat / dev / null> /var/log/mylogfile.log tronque le fichier d'une manière qui résout ce problème, plutôt que d'utiliser logrotate intégré dans copytruncate?
mtinberg
2
Le problème ne réside pas dans la façon dont le fichier est tronqué, le problème réside dans la façon dont le programme écrit le fichier journal. Pour tronquer le fichier journal pour être une approche viable, vous devrez obtenir que le programme écrivant dans le fichier journal cherche en quelque sorte à se positionner 0. Il est possible qu'un système de fichiers qui ne prend pas en charge les fichiers épars n'ait pas ce problème, bien que je ne 'ai aucun moyen de tester cela en ce moment.
Kjetil Joergensen
1
Cette réponse finale avait en fait plus de sens et le correctif finira probablement par redémarrer l'application.
drewrockshard
2

Je suis extrêmement confiant que Kjetil l'a atteint. Drew, vous n'êtes peut-être pas encore convaincu par son explication, mais je vous invite à lire attentivement ce qu'il a dit.

Si vous l'acceptez, le correctif consiste soit à arrêter et à redémarrer votre application lorsque les journaux sont tournés, soit à utiliser un outil comme les "rotatelogs" d'Apache, où vous alimentez la sortie du journal vers l'outil via un tuyau, et l'outil prend soin de faire tourner le fichier journal de temps en temps. Par exemple, une de mes instances Apache se connecte avec

ErrorLog "|/usr/sbin/rotatelogs /www/logs/error_log 604800"

ce qui provoque beaucoup de fichiers journaux avec des noms comme

-rw-r--r--    1 root     root         4078 Dec 21 01:04 error_log.1292457600
-rw-r--r--    1 root     root         4472 Dec 29 08:41 error_log.1293062400
-rw-r--r--    1 root     root        78630 Jan  4 12:57 error_log.1293667200
-rw-r--r--    1 root     root        15753 Jan 12 01:10 error_log.1294272000

apparaître sans redémarrer apache; Je peux ensuite les compresser manuellement après coup. Notez comment la rotation est effectuée chaque semaine, c'est-à-dire toutes les 604800 secondes, cet argument étant transmis à rotatelogs.

Si vous ne pouvez pas arrêter et redémarrer l'application, et qu'elle ne peut pas se connecter via un canal, alors je pense que vous avez un vrai problème. Peut-être que d'autres auront des suggestions.

Chapelier Fou
la source
0

ce serait vraiment génial si vous pouviez envoyer la totalité du logrotate.

Pourquoi essayer d'utiliser kill -HUP? (Rechargement classique ne redémarre pas ).

Vérifiez également lsof qui accède au fichier.

Nikolaidis Fotis
la source
Je ne peux pas l'utiliser kill -HUPcar cette application ne peut pas être touchée de quelque façon que ce soit - c'est une application sensible que je ne possède pas (je ne la gère même pas - je ne gère que le côté OS), donc je dois pouvoir faire les logrotations cette façon.
drewrockshard
1
Désolé, le message d'origine a été envoyé tôt, voici le reste de mon message d'origine: je me suis connecté au système ce matin et le fichier est maintenant revenu à la normale après le début de la connexion prévue /etc/cron.daily. Question à tous: Y a-t-il quelque chose que le script logrotate fait différemment de l'exécution manuelle de logrotate? Mon script logrotate ressemble littéralement /usr/sbin/logrotate /etc/logrotate.conf. C'est assez déroutant.
drewrockshard
-1

Utilisez simplement ">>" qui signifie ajouter au lieu de ">" qui signifie créer à partir de vos scripts qui écrivent dans ce fichier. J'ai eu exactement le même problème et je l'ai résolu en utilisant append dans mon script.

SomeScript.sh >> output.txt

J'espère que c'est plus clair.

user578558
la source
Rien n'indique que l'écriture dans le fichier journal s'effectue à l'aide >d'un script. De plus, cette réponse prête à confusion car il existe une différence majeure entre >et >( )dans les scripts. Enfin, si le code faisant l'écriture est mis à jour, il vaudrait beaucoup mieux qu'il commence simplement à écrire dans le nouveau fichier journal après logrotateavoir fait son travail.
kasperd
Je modifie ma réponse pour que ce soit plus clair.
user578558