контролировать файлы (а-ля tail -f) во всем каталоге (даже в новых)


53

Я обычно смотрю много логов в директории делаю tail -f directory/*. Проблема в том, что новый журнал создается после этого, он не будет отображаться на экране (потому что *уже был расширен).

Есть ли способ контролировать каждый файл в каталоге, даже те, которые создаются после запуска процесса?

Ответы:


44

Вы можете создать несколько файлов с помощью ... multitail .

multitail -Q 1 'directory/*'

-Q 1 PATTERNозначает проверять наличие нового содержимого в существующих или новых файлах, соответствующих шаблону, каждую 1 секунду. Строки из всех файлов отображаются в одном и том же окне, используйте -qвместо того, -Qчтобы иметь отдельные окна.


10

xtailтоже альтернатива. Его страница руководства описывает это как:

Xtail контролирует один или несколько файлов и отображает все данные, записанные в файл с момента вызова команды. Это очень полезно для мониторинга нескольких файлов журнала одновременно. Если запись, указанная в командной строке, является каталогом, будут отслеживаться все файлы в этом каталоге, включая файлы, созданные после вызова xtail. Если запись, заданная в командной строке, не существует, xtail будет отслеживать ее и отслеживать после ее создания. При переключении файлов на дисплее печатается баннер с указанием пути к файлу.

Символ прерывания (обычно CTRL / C или DEL) отображает список последних просмотренных измененных файлов. Отправьте сигнал выхода (обычно CTRL / обратный слеш), чтобы остановить xtail.


1
Ссылка не работает, но я думаю, что это то же самое, что и manpages.ubuntu.com/manpages/zesty/man1/xtail.1.html
edpaez

7

Не знаю, как решить проблему с оболочкой, но (предполагая, что Linux 1) inotifyможет стать способом ... посмотрите на этот пример, имитирующийtail -F (использующий pyinotify), может быть, его можно использовать как основу для следования целому каталогу .

В общем, inotifyможно отслеживать каталоги (цитируя man 7 inotify)

Следующие биты могут быть указаны в маске при вызове inotify_add_watch (2) и могут быть возвращены в поле маски, возвращаемом 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 (*).

При мониторинге каталога события, отмеченные звездочкой (*) выше, могут происходить для файлов в каталоге, и в этом случае поле имени в возвращенной структуре inotify_event идентифицирует имя файла в каталоге.

(... и pyinotifyвнимательно следит за этими вариантами)

1У BSD есть похожая вещь kqueue. Возможно, кросс-платформенное решение достижимо, используя GIO ( привязки Python ) в качестве уровня абстракции, так как оно может, кроме того inotify, использоватьkqueue


2

Я написал быстрый, который удовлетворяет потребности.

#!/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
На самом деле, вы можете опустить сон 1 в главном цикле, будет более быстро получать новые файлы. Но мне не нравятся такие занятые ожидания
Итамар

Из-за того, что sleepэто не занятое ожидание, а мягкая загрузка процессора, просто опрос. Можно изменить его на sleep 0.2s(GNU sleep) или что-то еще, чтобы сделать его быстрее, если это необходимо.
Нед64

2

Также вы можете посмотреть каталог с watch

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

Незначительный зазор: watchперерисовывает экран в альтернативном буфере с первыми x строками вывода команды. В нескольких файлах без изменений, если более ранние файлы не изменяются, они tailмогут каждый раз отображать одно и то же, так что у вас не появляется дополнительных записей, так как они отображаются в более поздних файлах «ниже» в нижней части окна. экран. Для короткого файла, тем не менее, это хорошо ...
jimbobmcgee

Это не дает решения исходной проблемы. Это просто выводит (последние несколько строк) список каталогов (многократно, всегда актуальный - спасибо watch) вместо самых последних строк всех файлов (включая новые) в этом каталоге.
trs
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.