Rotation du journal de stdout?

53

J'ai un programme Linux capable d'écrire des informations sur stdout et stderr.

J'ai un script shell qui redirige cette sortie vers un fichier /var/log. (Via >>et 2>&1.)

Existe-t-il un moyen de faire pivoter ce fichier journal? (taille maximale, puis passer à un autre fichier, ne conserver qu'un nombre limité de fichiers)

J'ai vu quelques réponses qui parlent du logrotateprogramme, ce qui semble bien, mais elles semblent également se concentrer sur des programmes qui génèrent des fichiers journaux en interne et gèrent les signaux HUP. Existe-t-il un moyen de faire fonctionner cela avec un script de redirection de sortie de base?

Miral
la source
1
Pourquoi ne pouvez-vous pas simplement modifier le script qui redirige la sortie afin de contenir la logique de la rotation?
MaQleod
Je pourrais, si quelqu'un pouvait me dire comment détecter la taille d'un fichier journal et le faire basculer sous la sortie standard d'un processus sans perturber ce processus. Je ne dois utiliser logrotates'il y a une meilleure option, qui sonnait comme un bon point de départ pour la discussion.
Miral
2
Vous n’êtes pas obligé d’utiliser logrotate, mais l’utilisation de logrotate vous fait gagner du temps… Il n’ya généralement aucun intérêt à réinventer la roue.
bubu
Exactement mon point. Alors, y a-t-il un moyen de faire fonctionner logrotate avec la sortie standard redirigée d'un processus en cours?
Miral

Réponses:

44

Vous pouvez également acheminer la sortie via des outils conçus dans le but principal de gérer des ensembles de fichiers journaux de taille maximale, avec rotation automatique, tels que:

Les outils permettant ensuite de traiter multilogles ensembles de fichiers journaux de format comprennent, entre autres:

Lectures complémentaires

JdeBP
la source
1
Merci, multilogressemble à ce dont j'avais besoin.
Miral
multilog semble être la seule solution plug-and-play de debian (daemontools a un paquet officiel). Mais dans mon cas particulier, où je voulais stocker les journaux sur une partition fat32, la rotation ne fonctionnait pas, car multilog souhaitait utiliser un lien symbolique. Pas de plug and play pour moi :)
Arnout
Cela ne peut être vrai, car multilognulle part ne crée ou n'exige des liens symboliques. C'est totalement neutre à leur égard.
JdeBP
L’URL de "Ne pas utiliser logrotate ou newsyslog en ce siècle" a un point supplémentaire
duyue
15

l' rotatelogsoutil fourni avec apache (dans le binrépertoire) (voir la documentation ) utilise les entrées de stdin et fait pivoter le journal après un certain temps

BertNase
la source
14

Si vous pouvez le faire accéder à l'un des flux de journaux standard (syslog, démon, cron, utilisateur, sécurité, messagerie, etc.), vous pouvez utiliser la loggercommande et y accéder à la place.

echo "Hello." | logger -p daemon.info

Sinon, vous feriez mieux de rediriger votre contenu enregistré vers un programme personnalisé ou un script, ou de logrotateconfigurer la configuration.

EDIT: La réponse de JdeBP semble avoir ce que vous pourriez rechercher.

Lara Dougan
la source
2
+1 pour la simplicité. BTW, vous pouvez également configurer une installation personnalisée (local0) au lieu de celles standard (démon dans votre exemple)
Roger Keays
14

J’avais un problème similaire et j’avais initialement rejeté Logrotate, mais il s’est avéré que Logrotate peut réellement le faire correctement. La directive clé est " copytruncate ". Pour une raison quelconque, ce terme n’a été mentionné dans aucune des recherches que j’ai faites sur Google. J’ajoute donc cette réponse pour préciser comment l’utiliser dans ce cas.

L'astuce est que cela ne fonctionne que si la redirection est faite avec " >> " (ajouter) au lieu de " > " (créer).

Fichier de configuration (truncate.cfg):

/tmp/temp.log {
    size 10M
    copytruncate
    rotate 4
    maxage 100
}

Programme de test (n'abandonne jamais le fichier). Vous pouvez le regarder remplir le disque et bien que la suppression du fichier journal semble fonctionner, elle ne libérera aucun espace sur le disque:

cat /dev/urandom >> /tmp/temp.log

Journal tournant en rotation:

logrotate truncate.cfg
Sam Hendley
la source
C'est une théorie intéressante, mais elle ne fonctionne en réalité sur aucun des systèmes sur lesquels je l'ai essayée. Le fichier n'est pas tronqué et le programme continue de l'ajouter comme auparavant. (Et oui, c'est même avec la redirection effectuée via >>.) ((En passant, cette réponse a déjà été donnée précédemment.))
Miral
1
… Comme indiqué dans logrotate ne tronque pas le fichier d'origine (sur nos sites Unix et Linux). En outre, echo /dev/urandom >> /tmp/temp.logécrira 13 caractères déterministes à /tmp/temp.loget puis immédiatement quitter. Vouliez-vous dire cat /dev/urandom?
G-Man dit 'Réintégrez Monica'
2
Juste testé ici, et cela semble fonctionner. Le contenu du fichier est copié dans un nouveau fichier journal. Le fichier d'origine est maintenu ouvert par le processus et est tronqué (la taille indique maintenant 0).
Philipp
1
Faites attention à la perte de données possible avec copytruncate.
Wang
1
+1 bien que "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 risquent d'être perdues."
Tagar
3

Existe-t-il un moyen de faire fonctionner logrotate avec la sortie standard redirigée d'un processus en cours?

Oui! Découvrez la directive "copytruncate" proposée par logrotate. Spécifier cela indique à logrotate de gérer cette situation: un programme simple qui garde son fichier journal ouvert indéfiniment.

Une mise en garde peut ou peut ne pas être un problème dans votre situation:

Notez qu'il y a très peu de temps entre la copie du fichier et sa troncature, de sorte que certaines données de journalisation risquent d'être perdues.

De manière anecdotique, j'ai vu des sources de journalisation du "monde réel" qui encouragent les utilisateurs à appliquer cette directive. Il y a quelques discussions sur cette option ici .

Natevw
la source
3

Utilisez split, cela fait partie des coreutils. Il peut prendre stdin et le scinder en morceaux (en fonction de la taille, du nombre de lignes, etc.).

Exemple:

app | split --bytes 1G - /var/logs/put-prefix-here

Note dash (-) indique à "split" d'utiliser stdin au lieu de fichier.

Nazar
la source
Pouvez-vous développer votre réponse pour décrire comment faire cela? Merci.
fixer1234
vient de mettre à jour ma réponse avec exemple.
Nazar
Le 1G est une taille arbitraire, après quoi il commence un nouveau fichier?
fixer1234
1
Ce n'est pas une bonne solution au problème car cela signifie que vous pouvez vous retrouver avec la moitié d'un message dans un fichier et l'autre dans l'autre. Il existe également un risque de perte de données si la machine tombe en panne alors que splitdes données sont stockées dans ce qui pourrait être un tampon important. Étant donné que de nombreux outils permettent de résoudre ce problème correctement, je ne pense pas que ce type de solution personnalisée puisse être recommandé.
David Richerby
1
@ David Richerby- que diriez-vous d'ajouter -u pour les mémoires sans tampon?
Nick
3

J'aime multilogmon cas d'utilisation, mais mon cas d'utilisation est tellement simple / trivial qu'il n'est pas présenté très simplement dans la documentation / les exemples que j'ai trouvés. Voici un exemple simple de rotation multilog:

mkdir /tmp/myapp
./myapp | multilog t s10000 n5 '!tai64nlocal' /tmp/myapp 2>&1

Quelques notes:

  • cela vide les journaux dans ce répertoire / tmp / myapp /
  • le s10000 représente 10 000 octets *
  • le n5 représente 5 fichiers. * Le journal "actuel" compte pour l'un des fichiers; il comprend donc 4 journaux plus anciens + "en cours".
  • ceci est basé sur, adapté des exemples fournis par François Beausoleil à l'adresse: http://blog.teksol.info/pages/daemontools/best-practices
  • Je ne comprends pas beaucoup des options - je vous renvoie à la documentation pour étendre ceci ...
  • Les docs avertissent que: "Note that running processor may block any program feeding input to multilog."où 'processeur' est la '!tai64nlocal'partie de la commande

* Pour de nombreuses applications, ce sont de mauvais choix pour une utilisation à long terme. Ils vous permettent d’observer le comportement de remplissage et de rotation des journaux plus rapidement que les journaux de grande taille.

Enfin, n'oubliez pas de nohup si nécessaire! Avec nohup, vous n’avez pas besoin du 2>&1(s = 10e6 et n = 30 ici):

mkdir -p /tmp/myapp
nohup ./myapp | multilog t s10000000 n30 '!tai64nlocal' /tmp/myapp &

Cette commande devrait vous aider à démarrer.

sauge
la source
1

Je voulais juste ajouter au commentaire de Sam Hendley ci-dessus:

L'astuce est que cela ne fonctionne que si la redirection est faite avec >>(ajouter) au lieu de >(créer).

J'ai rencontré le même problème où le fichier d'origine ne cesse de croître si vous utilisez >(créez) mais si vous utilisez >>(ajoutez) Logrotate copytruncate fonctionne à merveille et comme prévu. Le fichier d'origine redescend à zéro octet et le programme continue à écrire.

Redirige STDOUT et STDERR vers un fichier journal en rotation:

  1. some-program.sh >> /tmp/output.txt 2>&1 &
  2. Créez un fichier de configuration logrotate sous le /etc/logrotate.dnom que vous voulez, output_roll dans mon cas.

    Exemple de configuration pour mon cas:

    /tmp/output.txt {
        notifempty
        missingok
        size 1G
        copytruncate
        start 0
        rotate 15
        compress
    }
    
  3. Configurez votre travail cron dans le /etc/crontabfichier

    *  *  *  *  * root /usr/sbin/logrotate /etc/logrotate.d/output_roll
    

    Cela vérifiera le fichier toutes les minutes. Vous pouvez vous adapter à vos besoins.

  4. Le démarrer:

    $> service crond restart
    
  5. C'est ça

Remarque: J'ai également eu un problème avec SELinux étant défini sur SELINUX=enforcing, je l'ai donc défini sur SELINUX=disabled.

utilisateur578558
la source
1

J'ai écrit un logrotee ce week-end. Je ne le ferais probablement pas si j'avais lu l'excellente réponse de @JdeBP et multilog.

Je me suis concentré sur sa légèreté et sa capacité à bzip2 ses morceaux de sortie comme:

verbosecommand | logrotee \
  --compress "bzip2 {}" --compress-suffix .bz2 \
  /var/log/verbosecommand.log

Cependant, il reste encore beaucoup à faire et à tester.

Victor Sergienko
la source