monitorare i file (à la tail -f) in un'intera directory (anche nuovi)


53

Normalmente guardo molti registri in una directory facendo tail -f directory/*. Il problema è che in seguito viene creato un nuovo registro, che non verrà visualizzato nella schermata (perché è *stato già espanso).

Esiste un modo per monitorare tutti i file in una directory, anche quelli creati dopo l'avvio del processo?

Risposte:


44

È possibile coda multi- file PLE con ... multtail .

multitail -Q 1 'directory/*'

-Q 1 PATTERNsignifica verificare la presenza di nuovi contenuti in file esistenti o nuovi corrispondenti a PATTERN ogni 1 secondo. Linee da tutti i file sono visualizzabili nella stessa finestra, utilizzare -qinvece di -Qavere finestre separate.


10

xtailè anche un'alternativa. La sua pagina man lo descrive come:

Xtail monitora uno o più file e visualizza tutti i dati scritti in un file dall'invocazione del comando. È molto utile per monitorare più file di registro contemporaneamente. Se una voce fornita nella riga di comando è una directory, verranno monitorati tutti i file in quella directory, inclusi quelli creati dopo l'invocazione di xtail. Se non esiste una voce fornita dalla riga di comando, xtail la cercherà e la monitorerà una volta creata. Quando si cambiano i file sul display, viene stampato un banner che mostra il percorso del file.

Un carattere di interruzione (di solito CTRL / C o DEL) visualizzerà un elenco degli ultimi file modificati osservati. Invia un segnale di uscita (di solito CTRL / barra rovesciata) per interrompere xtail.


1
Link è rotto, ma penso che è la stessa: manpages.ubuntu.com/manpages/zesty/man1/xtail.1.html
edpaez

7

Nessuna idea di una soluzione shell, ma (supponendo che Linux 1) inotifypotrebbe essere la strada da percorrere ... vedi questo esempio imitandotail -F (usando pyinotify), forse può essere usato come base per seguire un'intera directory .

In generale, inotifypuò monitorare le directory (citando man 7 inotify)

I seguenti bit possono essere specificati in maschera quando si chiama inotify_add_watch (2) e possono essere restituiti nel campo maschera restituito da read (2):

IN_ACCESS         File was accessed (read) (*).
IN_ATTRIB         Metadata changed, e.g., permissions, timestamps,
                    extended attributes, link count (since Linux 2.6.25),
                    UID, GID, etc. (*).
IN_CLOSE_WRITE    File opened for writing was closed (*).
IN_CLOSE_NOWRITE  File not opened for writing was closed (*).
IN_CREATE         File/directory created in watched directory (*).
IN_DELETE         File/directory deleted from watched directory (*).
IN_DELETE_SELF    Watched file/directory was itself deleted.
IN_MODIFY         File was modified (*).
IN_MOVE_SELF      Watched file/directory was itself moved.
IN_MOVED_FROM     File moved out of watched directory (*).
IN_MOVED_TO       File moved into watched directory (*).
IN_OPEN           File was opened (*).

Durante il monitoraggio di una directory , gli eventi contrassegnati con un asterisco (*) sopra possono verificarsi per i file nella directory, nel qual caso il campo del nome nella struttura inotify_event restituita identifica il nome del file all'interno della directory.

(... e pyinotifysegue da vicino queste opzioni)

1: BSD hanno una cosa simile, kqueue. Forse una soluzione multipiattaforma è realizzabile usando GIO ( attacchi Python ) come strato di astrazione poiché può, accanto inotify, anche usarekqueue


2

Ne ho scritto uno veloce che soddisfa l'esigenza.

#!/bin/bash
LOG_PATTERN=$1
BASE_DIR=$(dirname $LOG_PATTERN* | head -1)

run_thread (){
    echo Running thread
    tail -F $LOG_PATTERN* &
    THREAD_PID=$!
}

# When someone decides to stop the script - killall children
cleanup () {
    pgrep -P $$ | xargs -i kill {}
    exit
}

trap cleanup SIGHUP SIGINT SIGTERM

if [ $# -ne 1 ]; then
    echo "usage: $0 <directory/pattern without * in the end>"
    exit 1
fi

# Wait for the directory to be created
if [ ! -d $BASE_DIR ] ; then
    echo DIR $BASE_DIR does not exist, waiting for it...
    while [ ! -d $BASE_DIR ] ; do
        sleep 2
    done
    echo DIR $BASE_DIR is now online
fi

# count current number of files
OLD_NUM_OF_FILES=$(ls -l $LOG_PATTERN* 2>/dev/null | wc -l)

# Start Tailing
run_thread

while [ 1 ]; do
    # If files are added - retail
    NUM_FILES=$(ls -l $LOG_PATTERN* 2>/dev/null | wc -l)
    if [ $NUM_FILES -ne $OLD_NUM_OF_FILES ]; then
        OLD_NUM_OF_FILES=$NUM_FILES
        kill $THREAD_PID
        run_thread
    fi
    sleep 1
done

1
In realtà, puoi ommettere il sonno 1 nel ciclo principale, sarà più scattante per ottenere nuovi file. Ma non mi piace quel tipo di attese impegnative
Itamar,

A causa di sleepquesto non è un'attesa impegnata ma soft sulla CPU, solo il polling. Si potrebbe cambiarlo in sleep 0.2s(GNU sleep) o altro per renderlo più veloce se necessario.
Ned64,

2

Inoltre puoi guardare la directory con watch

watch -n0,1 "ls -lrt /directory/ | tail"

Minore nitpick: watchridisegna lo schermo nel buffer alternativo, con le prime x righe di output dal comando. In un certo numero di file senza modifiche, se i file precedenti non cambiano, è tailpossibile che vengano visualizzate le stesse cose ogni volta, quindi si ottiene l'aspetto di nessuna voce aggiuntiva, poiché vengono disegnati nei file successivi "sotto" nella parte inferiore della schermo. Per un breve file, però, va bene ...
jimbobmcgee,

Ciò non fornisce una soluzione al problema originale. Questo genera solo (le ultime righe di) un elenco di directory (ripetutamente, sempre aggiornato - grazie a watch), invece delle ultime righe di tutti i file (inclusi quelli nuovi) in quella directory.
trs
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.