Запись вывода «tail -f» в другой файл

34

Как продолжение моего последнего поста, где я использовал, grep & tail -fчтобы найти случаи «редких» событий. Я хотел бы записать это в другом файле.

Я пытался повернуть

tail -f log.txt | egrep 'WARN|ERROR'

в

tail -f log.txt | egrep 'WARN|ERROR' | tee filtered_output.txt

Файл создается, но ничего не заполняется, это проблема кэширования или нет? Как бы я мог в реальном времени добавить вывод моего хвоста в новый файл?

Майк
источник

Ответы:

44

Буферизация - это проблема.

Сделай это так,

tail -f log.txt | egrep - line-buffered 'WARN | ERROR' | Tee Filter_output.txt
# ^^^^^^^^^^^^^^^

Подтвердили работу на Cygwin тоже.

Nik
источник
6

Вероятно, это проблема буферизации. Смотрите этот пост об отключении автоматической буферизации при использовании каналов . Вы можете использовать unbufferкоманду из expect:

$ unbuffer tail -f log.txt | egrep 'WARN|ERROR' | tee filtered_output.txt

Изменить : Так как у вас есть более длинный конвейер, вам, вероятно, нужно снять буфер каждой команды (кроме последней):

$ unbuffer tail -f log.txt | unbuffer egrep 'WARN|ERROR' | tee filtered_output.txt

Редактировать 2 : unbufferдоступно на Cygwin из expectпакета с исходным кодом (например, ожидаем-20030128-1-src.tar.bz2 , находится в expect/examplesпапке), но это очень короткий скрипт. Если у вас expectуже установлен пакет, просто поместите его в скрипт, который называется unbufferв вашем /usr/local/binкаталоге:

#!/usr/bin/expect --
# Description: unbuffer stdout of a program
# Author: Don Libes, NIST

eval spawn -noecho $argv
set timeout -1
expect

В Debian unbufferкоманда предоставляется в expect-devпакете и устанавливается как expect_unbuffer.

шарлатан
источник
Есть ли способ сделать это с Cygwin?
Майк
добавлена ​​информация по использованию в cygwin; вам понадобится expectпакет
Quackote Quixote
Спасибо, не могу попробовать до понедельника сейчас, к сожалению. Обновлю потом.
Майк
4

При использовании команды, которая на самом деле не «завершает» (например, tail -f), это на самом деле не очень хорошо работает или не очень хорошо (вообще).

Вы должны быть в состоянии перенаправить вывод в текстовый файл. Попробуй это:

tail -f log.txt | egrep 'WARN|ERROR' > filtered_output.txt
Джош Хант
источник
1
Это не похоже на работу.
Майк
2

Это версия, unbufferкоторую я имею:

#!/usr/bin/expect --
# Description: unbuffer stdout of a program
# Author: Don Libes, NIST

if {[string compare [lindex $argv 0] "-p"] == 0} {
    # pipeline
    set stty_init "-echo"
    eval spawn -noecho [lrange $argv 1 end]
    close_on_eof -i $user_spawn_id 0
    interact {
    eof {
        # flush remaining output from child
        expect -timeout 1 -re .+
        return
    }
    }
} else {
    set stty_init "-opost"
    set timeout -1
    eval spawn -noecho $argv
    expect
}
Приостановлено до дальнейшего уведомления.
источник
+1 спасибо за дополнительную информацию. не знаю, если это дружественный к Cygwin, но это выглядит как более интеллектуальный сценарий.
Квик-кихот
2

Как уже отмечали другие, вы можете использовать unbufferутилиту от Expect.

Тем не менее, обратите внимание, что в зависимости от вашей системы и доступной версии Expect вам может понадобиться использовать -pпереключатель для снятия буфера. Ссылаясь на справочную страницу:

   Normally, unbuffer does not read from stdin.  This simplifies use of unbuffer in some situations.  To use unbuffer in a  pipeline,  use
   the -p flag.  Example:

           process1 | unbuffer -p process2 | process3

Так что вам может понадобиться этот вызов:

unbuffer -p tail -f log.txt | unbuffer -p egrep 'WARN|ERROR' | tee filtered_output.txt

Кстати, см. Эту статью для подробного объяснения проблемы буферизации вывода: http://www.pixelbeat.org/programming/stdio_buffering/

Александр Адамовский
источник