supervisar archivos (a la cola -f) en un directorio completo (incluso los nuevos)


53

Normalmente veo muchos registros en un directorio haciendo tail -f directory/*. El problema es que se crea un nuevo registro después de eso, no se mostrará en la pantalla (porque ya *se expandió).

¿Hay alguna forma de monitorear cada archivo en un directorio, incluso aquellos que se crean después de que el proceso ha comenzado?

Respuestas:


44

Puede cola múltiples archivos con PLE ... multitail .

multitail -Q 1 'directory/*'

-Q 1 PATTERNsignifica buscar nuevo contenido en archivos existentes o nuevos que coincidan con PATTERN cada 1 segundo. Las líneas de todos los archivos se muestran en la misma ventana, use en -qlugar de -Qtener ventanas separadas.


10

xtailTambién es una alternativa. Su página de manual lo describe como:

Xtail monitorea uno o más archivos y muestra todos los datos escritos en un archivo desde la invocación del comando. Es muy útil para monitorear múltiples archivos de registro simultáneamente. Si una entrada dada en la línea de comando es un directorio, todos los archivos en ese directorio serán monitoreados, incluidos los creados después de la invocación de xtail. Si no existe una entrada dada en la línea de comando, xtail la buscará y la monitoreará una vez creada. Al cambiar archivos en la pantalla, se imprime un banner que muestra el nombre de la ruta del archivo.

Un carácter de interrupción (generalmente CTRL / C o DEL) mostrará una lista de los archivos modificados más recientemente que se están viendo. Envíe una señal de salida (generalmente CTRL / barra invertida) para detener xtail.


1
El enlace está roto, pero creo que es lo mismo que: manpages.ubuntu.com/manpages/zesty/man1/xtail.1.html
edpaez

7

No tengo idea de una solución de shell, pero (suponiendo que Linux 1) inotifypodría ser el camino a seguir ... vea este ejemplo imitandotail -F (usando pyinotify), tal vez pueda usarse como base para seguir un directorio completo .

En general, inotifypuede monitorear directorios (citando man 7 inotify)

Los siguientes bits pueden especificarse en la máscara al llamar a inotify_add_watch (2) y pueden devolverse en el campo de máscara devuelto por 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 (*).

Al monitorear un directorio , los eventos marcados con un asterisco (*) arriba pueden ocurrir para los archivos en el directorio, en cuyo caso el campo de nombre en la estructura devuelta inotify_event identifica el nombre del archivo dentro del directorio.

(... y pyinotifysigue de cerca estas opciones)

1: BSD tienen una cosa similar, kqueue. Tal vez se pueda lograr una solución multiplataforma usando GIO ( enlaces de Python ) como capa de abstracción ya que, además inotify, también puede usarkqueue


2

Escribí uno rápido que satisface la necesidad.

#!/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
En realidad, puede omitir el sueño 1 en el bucle principal, será más rápido para obtener nuevos archivos. Pero no me gusta ese tipo de esperas ocupadas
Itamar

Debido a sleepesto, no es una espera ocupada, sino suave en la CPU, solo sondeo. Se podría cambiar a sleep 0.2s(suspensión GNU) o lo que sea para hacerlo más rápido si es necesario.
Ned64

2

También puedes mirar el directorio con watch

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

Nitpick menor: watchvuelve a dibujar la pantalla en el búfer alternativo, con las primeras x líneas de salida del comando. En varios archivos sin cambios, si los archivos anteriores no cambian, es tailposible que se muestre lo mismo cada vez, por lo que no aparecen entradas adicionales, ya que se dibujan en archivos posteriores 'debajo' de la parte inferior de pantalla. Sin embargo, para un archivo corto, está bien ...
jimbobmcgee

Esto no da una solución al problema original. Esto solo genera (las últimas líneas de) una lista de directorios (repetidamente, siempre actualizada, gracias a watch), en lugar de las últimas líneas de todos los archivos (incluidos los nuevos) en ese directorio.
trs
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.