GNU/Linux >> Znalost Linux >  >> Linux

Jak ukončit linuxový příkaz tee bez zabití aplikace, ze které je přijímán

Když tee ukončí, příkaz, který jej nabíjí, bude pokračovat, dokud se nepokusí zapsat další výstup. Pak dostane SIGPIPE (13 na většině systémů) za pokus o zápis do roury bez čteček.

Pokud upravíte svůj skript tak, aby zachytil SIGPIPE a provedete nějakou vhodnou akci (např. zastavíte zápis výstupu), pak byste měli být schopni nechat jej pokračovat i po ukončení tee.

Ještě lepší, než zabíjet tee vůbec použijte logrotate s copytruncate možnost pro jednoduchost.

Chcete-li citovat logrotate(8) :

copytruncate

Po vytvoření kopie zkraťte původní soubor protokolu na místě, místo přesouvání starého souboru protokolu a volitelně vytvoření nového. Lze jej použít, když některému programu nelze říci, aby zavřel svůj soubor protokolu, a tak by mohl pokračovat v zápisu (připojování) k předchozímu souboru protokolu navždy. Všimněte si, že mezi zkopírováním souboru a jeho zkrácením je velmi malý časový úsek, takže některá data protokolování mohou být ztracena. Při použití této možnosti nebude mít možnost vytvořit žádný účinek, protože starý soubor protokolu zůstane na svém místě.


Vysvětlení „Proč“

Stručně řečeno:Pokud selhávají zápisy nestaly způsobit ukončení programu (ve výchozím nastavení), měli bychom nepořádek. Zvažte find . | head -n 10 -- nechcete find Chcete-li pokračovat v běhu, prohledejte zbytek pevného disku po head již zabral 10 řádků, které potřeboval, a pokračoval.

Dělat to lépe:Otočte se v loggeru

Zvažte následující, které nepoužívá tee vůbec, jako demonstrativní příklad:

#!/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

Pokud spustíte jako:

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

...toto začne připojením k /tmp/nginx/debug_log , přejmenováním souboru na /tmp/nginx/debug_log.old když je k dispozici více než 100 kB obsahu. Protože rotaci provádí samotný logger, nedochází při rotaci k žádnému prasknutí potrubí, žádné chybě a žádnému oknu ztráty dat – každý řádek bude zapsán do jednoho nebo druhého souboru.

Implementace tohoto v nativním bash je samozřejmě neefektivní, ale výše uvedené je ilustrativní příklad. Existuje mnoho dostupných programů, které za vás implementují výše uvedenou logiku. Zvažte:

  • svlogd , záznamník služeb ze sady Runit.
  • s6-log , aktivně udržovaná alternativa ze sady skanet.
  • multilog od DJB Daemontools, dědečka této rodiny nástrojů pro dohled a monitorování procesů.

Linux
  1. Jak odstranit soubory a adresáře v Linuxu z příkazového řádku

  2. Jak rozdělit a kombinovat soubory z příkazového řádku v Linuxu

  3. Jak vytvořit soubor v Linuxu z okna terminálu?

  1. Linux File Command:Jak určit typ souboru v Linuxu

  2. Jak uložit výstup příkazu do souboru v Linuxu

  3. Příkaz SCP Linux – Jak přenášet soubory SSH ze vzdáleného do místního

  1. Jak odstranit (smazat) soubor nebo adresář v Linuxu

  2. Jak extrahovat nebo rozbalit soubory tar.gz z příkazového řádku Linuxu

  3. Jak používat příkaz md5sum v Linuxu