Un script que j'ai écrit fait quelque chose et, à la fin, ajoute quelques lignes à son propre fichier journal. Je souhaite conserver uniquement les n dernières lignes (disons, 1 000 lignes) du fichier journal. Cela peut être fait à la fin du script de cette façon:
tail -n 1000 myscript.log > myscript.log.tmp
mv -f myscript.log.tmp myscript.log
mais existe-t-il une solution plus propre et élégante? Peut-être accompli via une seule commande?
text-processing
tail
logs
dr01
la source
la source
logrotate
est la solution éléganteRéponses:
C'est possible comme ça, mais comme d'autres l'ont dit, l'option la plus sûre est la génération d'un nouveau fichier puis un déplacement de ce fichier pour écraser l'original.
La méthode ci-dessous charge les lignes dans BASH, donc en fonction du nombre de lignes
tail
, cela va affecter l'utilisation de la mémoire du shell local pour stocker le contenu des lignes de journal.Ce qui suit supprime également les lignes vides si elles existent à la fin du fichier journal (en raison du comportement de l'évaluation BASH
"$(tail -1000 test.log)"
), donc ne donne pas une troncature vraiment 100% précise dans tous les scénarios, mais selon votre situation, peut être suffisant.la source
L'utilitaire
sponge
est conçu uniquement pour ce cas. Si vous l'avez installé, vos deux lignes peuvent s'écrire:Normalement, la lecture d'un fichier en même temps que vous y écrivez n'est pas fiable.
sponge
résout ce problème en n'écrivantmyscript.log
qu'après avoirtail
fini de le lire et terminé le tuyau.Installer
Pour installer
sponge
sur un système de type Debian:Pour installer
sponge
sur un système RHEL / CentOS, ajoutez le référentiel EPEL puis procédez comme suit:Documentation
De
man sponge
:la source
sponge
. Très utile pour tous ceux qui ont appris à la dure ce que vous ne pouvez pas fairesort importantfile.txt > importantfile.txt
:)certainement "tail + mv" est beaucoup mieux! Mais pour gnu sed on peut essayer
la source
Pour mémoire,
ed
vous pourriez faire quelque chose commeCela ouvre
infile
etr
lit la sortie detail -n 1000 infile
(c'est-à-dire qu'il insère cette sortie avant la 1ère ligne) puis supprime de ce qui était initialement la 1ère ligne jusqu'à la fin du fichier. Remplacez,p
parw
pour modifier le fichier sur place.Gardez à l'esprit que les
ed
solutions ne conviennent pas aux fichiers volumineux.la source
Ce que vous pouvez faire dans votre script, c'est implémenter la logique de rotation des journaux. Faites toute la journalisation via une fonction:
Cette fonction, premièrement, fait quelque chose comme:
ensuite, il vérifie la taille du fichier ou décide en quelque sorte que le fichier nécessite une rotation. À ce stade, le fichier
logfile.1
, s'il existe, est supprimé, le fichierlogfile.0
, s'il existe, est renommélogfile.1
etlogfile
est renommé enlogfile.0
.La décision de faire une rotation peut être basée sur un compteur maintenu dans le script lui-même. Lorsqu'il atteint 1000, il est remis à zéro.
S'il est toujours nécessaire de limiter strictement à 1000 lignes, le script peut compter le nombre de lignes dans le fichier journal au démarrage et initialiser le compteur en conséquence (ou si le nombre atteint ou dépasse déjà 1000, effectuez la rotation immédiatement).
Ou vous pouvez obtenir la taille, comme avec
wc -c logfile
et faire la rotation basée sur le dépassement d'une certaine taille. De cette façon, le fichier n'a jamais à être analysé pour déterminer la condition.la source
J'ai utilisé, au lieu de
mv
, lacp
commande pour y parvenir, vous pouvez avoir des fichiers journaux à l'endroit où un logiciel est en cours d'exécution. Peut-être dans le répertoire d'accueil de l'utilisateur différent ou dans le répertoire d'application et que tous les journaux sont regroupés en un seul endroit sous forme de liens physiques. Si vous utilisez lamv
commande, vous perdez le lien dur. Si vous utilisezcp
plutôt la commande, vous conserverez ce lien dur.mon code est quelque chose comme:
Donc, si les fichiers sont sur le même système de fichiers, vous pouvez également accorder des droits différents aux utilisateurs et
${LOGFILE_DIR}
modifier la longueur comme je le fais.Si c'est la
mv
commande, vous perdez le lien dur entre les fichiers et donc votre deuxième fichier n'est plus connecté au premier - peut-être placé quelque part ailleurs.Si à l'autre endroit vous ne permettez pas à quelqu'un d'effacer le fichier, vos journaux restent ensemble et sont bien contrôlés via votre propre script.
logrotate
peut-être plus agréable. Mais je suis satisfait de cette solution.Ne soyez pas dérangé par le "" mais dans mon cas, il y a des fichiers avec des espaces et d'autres lettres spéciales dans et si je ne fais pas le "" autour ou le {} le tout ne fonctionne pas bien.
Par exemple, il existe un répertoire dans lequel les fichiers plus anciens sont automatiquement zippés dans un fichier
OLDFILE.zip
et tout ce qui est compressé est également répertorié dans le fichier, de.zip_log
sorte qu'il se.zip_log
trouve également dans ce répertoire, mais dans le fichierLOGFILE_DIR
que j'ai avec:le fichier égal car il s'agit d'un lien dur.
la source