web-dev-qa-db-fra.com

Comment mettre fin à la commande Linux Tee sans tuer l'application, il reçoit de

J'ai un script Bash qui fonctionne tant que la machine Linux est alimentée. Je commence comme indiqué ci-dessous:

( /mnt/apps/start.sh 2>&1 | tee /tmp/nginx/debug_log.log ) &

Après cela Lauche, je peux voir la commande TEE dans mon PS Sortie, comme indiqué ci-dessous:

$ ps | grep tee
  418 root       0:02 tee /tmp/nginx/debug_log.log
3557 root       0:00 grep tee

J'ai une fonction qui surveille la taille du journal qui tee produit et tue la commande TEE lorsque le journal atteint une certaine taille:

monitor_debug_log_size() {
                ## Monitor the file size of the debug log to make sure it does not get too big
                while true; do
                                cecho r "CHECKING DEBUG LOG SIZE... "
                                debugLogSizeBytes=$(stat -c%s "/tmp/nginx/debug_log.log")
                                cecho r "DEBUG LOG SIZE: $debugLogSizeBytes"
                                if [ $((debugLogSizeBytes)) -gt 100000 ]; then
                                                cecho r "DEBUG LOG HAS GROWN TO LARGE... "
                                                sleep 3
                                                #rm -rf /tmp/nginx/debug_log.log 1>/dev/null 2>/dev/null
                                                kill -9 `pgrep -f tee`
                                fi
                                sleep 30
                done
}

À ma grande surprise, tuer la commande tee tue également par instance start.sh. Pourquoi est-ce? Comment puis-je mettre fin à la commande TEE MAIS AVEZ-VOUS MON START.SH Continuer à courir? Merci.

19
PhilBot

Expliquer le "pourquoi"

En bref: Si écrit échouer N'a pas Cause Un programme de sortie (par défaut), nous aurions un gâchis. Envisager find . | head -n 10 - Vous ne voulez pas find pour continuer à courir, numériser le reste de votre disque dur, après head a déjà pris les 10 lignes dont il était nécessaire et poursuivi.

Le faire mieux: tournez à l'intérieur de votre enregistreur

Considérez ce qui suit, qui n'utilise pas tee du tout, comme 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 courez comme suit:

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

... cela commencera en ajoutant à /tmp/nginx/debug_log, renommer le fichier à /tmp/nginx/debug_log.old Lorsque plus de 100 kb de contenus sont présents. Étant donné que l'enregistreur lui-même fait la rotation, il n'y a pas de tuyau brisé, sans erreur et aucune fenêtre de perte de données lorsque la rotation a lieu - chaque ligne sera écrite sur un fichier ou une autre.

Bien sûr, la mise en œuvre de cela dans Native Bash 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. Envisager:

  • svlogd , l'enregistreur de service de la suite Runit.
  • s6-log , une alternative activement entretenue de la suite Skanet.
  • multilog de DJB Daemontools, le grand -adaddy de cette famille d'outils de surveillance et de surveillance des processus.
3
Charles Duffy