GNU/Linux >> Tutoriels Linux >  >> Linux

Comment mettre fin à la commande Linux tee sans tuer l'application qu'il reçoit

Quand tee se termine, la commande qui l'alimente continuera à s'exécuter jusqu'à ce qu'il tente d'écrire plus de sortie. Ensuite, il obtiendra un SIGPIPE (13 sur la plupart des systèmes) pour avoir essayé d'écrire dans un tube sans lecteur.

Si vous modifiez votre script pour piéger SIGPIPE et prendre des mesures appropriées (par exemple, arrêter d'écrire la sortie), vous devriez pouvoir le faire continuer après la fin de tee.

Mieux encore, plutôt que de tuer tee du tout, utilisez logrotate avec le copytruncate option pour plus de simplicité.

Pour citer logrotate(8) :

copytruncate

Tronquez le fichier journal d'origine 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 à écrire (ajouter) au fichier journal précédent pour toujours. Notez qu'il y a une très petite tranche de temps entre la copie du fichier et sa troncature, donc 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.


Expliquer le "pourquoi"

En bref :si les écritures échouent, ne l'ont pas fait provoquer la fermeture d'un programme (par défaut), nous aurions un gâchis. Considérez find . | head -n 10 -- vous ne voulez pas find pour continuer à fonctionner, en analysant le reste de votre disque dur, après head a déjà pris les 10 lignes dont il avait besoin et a continué.

Faire mieux :faire pivoter l'intérieur de votre enregistreur

Considérez ce qui suit, qui n'utilise pas tee du tout, à titre d'exemple démonstratif :

#!/usr/bin/env bash

file=${1:-debug.log}                     # filename as 1st argument
max_size=${2:-100000}                    # max size as 2nd argument
size=$(stat --format=%s -- "$file") || exit  # Use GNU stat to retrieve size
exec >>"$file"                           # Open file for append

while IFS= read -r line; do              # read a line from stdin
  size=$(( size + ${#line} + 1 ))        # add line's length + 1 to our counter
  if (( size > max_size )); then         # and if it exceeds our maximum...
    mv -- "$file" "$file.old"            # ...rename the file away...
    exec >"$file"                        # ...and reopen a new file as stdout
    size=0                               # ...resetting our size counter
  fi
  printf '%s\n' "$line"                  # regardless, append to our current stdout
done

Si exécuté en tant que :

/mnt/apps/start.sh 2>&1 | above-script /tmp/nginx/debug_log

... cela commencera par ajouter à /tmp/nginx/debug_log , en renommant le fichier en /tmp/nginx/debug_log.old lorsque plus de 100 Ko de contenu sont présents. Étant donné que l'enregistreur effectue lui-même la rotation, il n'y a pas de tuyau cassé, pas d'erreur et pas de fenêtre de perte de données lors de la rotation ; chaque ligne sera écrite dans un fichier ou un autre.

Bien sûr, implémenter cela dans bash natif est inefficace, mais ce qui précède est un exemple illustratif. Il existe de nombreux programmes disponibles qui mettront en œuvre la logique ci-dessus pour vous. Considérez :

  • svlogd , le service logger de la suite Runit.
  • s6-log , une alternative activement maintenue de la suite skanet.
  • multilog de DJB Daemontools, l'ancêtre de cette famille d'outils de supervision et de surveillance des processus.

Linux
  1. Comment enregistrer la sortie de la commande dans un fichier sous Linux

  2. Comment supprimer des fichiers et des répertoires sous Linux à partir de la ligne de commande

  3. Comment diviser et combiner des fichiers à partir de la ligne de commande sous Linux

  4. Commande SCP Linux - Comment transférer un fichier SSH de distant à local

  5. Comment créer un fichier sous Linux à partir de la fenêtre du terminal ?

Comment utiliser la commande Truncate sous Linux

Comment mélanger les lignes dans un fichier sous Linux

Comment supprimer une commande de l'historique sous Linux

Comment supprimer les caractères (^M) d'un fichier sous Linux

Comment utiliser la commande lsof sous Linux

Comment utiliser la commande shred Linux