Comment continuer à rediriger stdout vers un fichier après que logrotate l'ait déplacé?

22

J'ai un script simple qui génère un tas de journaux à filtrer et j'ai canalisé le STDOUT dans un fichier pour stocker les journaux. Étant donné que ce script s'exécute depuis longtemps, j'avais besoin de faire pivoter les fichiers journaux afin qu'ils soient regroupés dans des fichiers plus petits et plus faciles à gérer.

Le problème que j'ai rencontré était qu'une fois que le logrotatefichier journal actuel est déplacé dans un nouveau, le fichier journal nouvellement créé n'est plus rempli avec les journaux. Il semble qu'une fois le fichier journal d'origine supprimé, son gestionnaire de fichiers est perdu et la redirection ne fonctionnera plus.

J'ai également trouvé ce message qui avait le même problème que moi et prétend qu'il peut être résolu en utilisant >>au lieu de >rediriger la sortie. J'ai testé sa solution mais cela n'a pas fonctionné pour moi. Quelqu'un a-t-il une idée de la façon de continuer à travailler la redirection?

Mehran
la source
4
Je recommanderais toujours, dans votre cas, d'utiliser ">>" au lieu de ">" si vous avez l'intention d'écrire dans un fichier tronqué: comme ">>" ouvert en mode ajout, il cherchera jusqu'à la fin du fichier à chaque fois qu'il écrit. De cette façon, lorsque vous tronquerez le fichier (en le faisant passer de XXXX octets à 0 octet), il "cherchera jusqu'à la fin", il saura donc qu'il doit maintenant écrire après l'octet 0. Sinon, il peut écrire après l'octet XXXX, et ainsi créer un fichier clairsemé avec XXXX octets nuls devant lui (c'est-à-dire, quand ">", le fd peut simplement se rappeler où il était dans ce fichier, et écrire à partir de là, sans se rendre compte que la taille du fichier a diminué!)
Olivier Dulac

Réponses:

25

Vous devez utiliser la directive copytruncate dans votre configuration logrotate pour ce fichier journal.

copytruncate Tronque le fichier journal d'origine en place après avoir créé une copie, au lieu de déplacer l'ancien fichier journal et éventuellement d'en créer un nouveau. Il peut être utilisé lorsqu'un programme ne peut pas être invité à fermer son fichier journal et peut donc continuer d'écrire (ajouter) dans le fichier journal précédent pour toujours. Notez qu'il existe un très petit intervalle de temps entre la copie du fichier et sa troncature, de sorte que certaines données de journalisation peuvent être perdues. Lorsque cette option est utilisée, l'option de création n'aura aucun effet, car l'ancien fichier journal reste en place

user9517 prend en charge GoFundMonica
la source
2
Il convient de mentionner: pendant une courte période, avant l' compressopération, les données sont dupliquées. Cela nous a causé un problème une fois, mais c'était notre pire, car nous n'aurions pas dû être aussi près de la lvlimite d'espace. En outre, comme indiqué dans l' manextrait de code, vous risquez de perdre certaines données de journal entre les opérations de copie et de troncature.
Belmin Fernandez
6

Comme alternative, vous pouvez également:

  • utilisez l'utilitaire de journalisation dans votre script au lieu de la tuyauterie, avec une fonction dédiée (par exemple local5), par exemple:

    logger -p local5.info -t myscriptname "this is some log data"

  • configurez syslog pour écrire cette fonction dans le fichier journal voulu, exemple (rsyslog.conf):

    local5.* /var/log/mylogfile

  • configurez la règle logrotate pour ce journal.

tonioc
la source
Cela ne fonctionne que si vous avez des commandes de sortie explicites comme echo. La sortie des outils tiers qui sont appelés à partir du script et qui produisent également quelque chose ne peut pas être redirigée vers l'enregistreur de cette façon
Daniel Alder
4

Une autre alternative à la solution Iain est d'utiliser un postrotatescript pour relancer votre script une fois la rotation effectuée. Cela se fait pour beaucoup de démons (redémarrer ou recharger le démon), mais ne connaissant pas votre script, je ne sais pas si cette solution vous conviendra ou non (votre script dépend-il d'un état généré il y a quelque temps?).

Contenu de /etc/logrotate.d/your-script-name:

/var/log/your-script-name.log {
    # your current logrotate options
    ...
    postrotate
        # this supposing you have the current pid stored
        cat /run/your-script-name.pid | xargs -r kill
        #relaunch it again
        /usr/local/bin/your-script-name
    endscript
}
Carlos Campderrós
la source
0

Vous pouvez diriger stdout vers "split" (partie de coreutils sous linux). Il vous permet de diviser le fichier / stdin en morceaux en fonction de la taille, du nombre de lignes, etc. Une fois que vous l'avez divisé, vous pouvez le gérer avec logrotate si nécessaire.

Nazar
la source