Подтвердить что ты не робот

Чтение файлов журналов по мере их обновления в Go

Я пытаюсь разобрать некоторые файлы журналов, поскольку они записываются в Go, но я не уверен, как бы это сделать, не перечитывая файл снова и снова при проверке изменений.

Я хотел бы иметь возможность читать EOF, ждать, пока следующая строка будет записана и снова прочитана в EOF и т.д. Это немного похоже на то, как выглядит tail -f.

4b9b3361

Ответ 1

Я написал пакет Go - github.com/ActiveState/tail - чтобы сделать именно это.

t, err := tail.TailFile("/var/log/nginx.log", tail.Config{Follow: true})
for line := range t.Lines {
    fmt.Println(line.Text)
}

...

Цитата ответа kostix:

в реальной жизни файлы могут быть усечены, заменены или переименованы (поскольку предполагается, что такие инструменты, как logrotate).

Если файл обрезается, он будет автоматически повторно открыт. Чтобы поддерживать повторное открытие переименованных файлов (из-за logrotate и т.д.), Вы можете установить Config.ReOpen, а именно:

t, err := tail.TailFile("/var/log/nginx.log", tail.Config{
    Follow: true,
    ReOpen: true})
for line := range t.Lines {
    fmt.Println(line.Text)
}

Config.ReOpen аналогичен tail -F (столица F):

 -F      The -F option implies the -f option, but tail will also check to see if the file being followed has been
         renamed or rotated.  The file is closed and reopened when tail detects that the filename being read from
         has a new inode number.  The -F option is ignored if reading from standard input rather than a file.

Ответ 2

Вам нужно либо просмотреть файл для изменений (используя подсистему, специфичную для ОС, для выполнения этого), либо периодически опросить его на посмотреть, будет ли время его модификации ( и размер). В любом случае, прочитав еще один фрагмент данных, вы запомните смещение файла и восстановите его перед чтением другого фрагмента после обнаружения изменения.

Но обратите внимание, что это кажется легким только на бумаге: в реальной жизни файлы могут быть усечены, заменены или переименованы (поскольку предполагается, что такие инструменты, как logrotate).

См. этот вопрос для более подробного обсуждения этой проблемы.

Ответ 3

Я также заинтересован в этом, но пока у меня еще не было времени заняться этим. Один из подходов, который приходил мне в голову, - позволить "хвосту" сделать тяжелый подъем. Это, скорее всего, сделает ваш инструмент специфичным для платформы, но это может быть хорошо. Основная идея заключалась бы в использовании Cmd из пакета "os/exec", чтобы следить за файлом. Вы могли бы развить процесс, который был бы эквивалентен "tail -retry --follow = name prog.log", а затем прослушивать его Stdout с помощью устройства Stdout на объекте Cmd.

Извините, я знаю, что это просто эскиз, но, возможно, это полезно.

Ответ 4

Есть много способов сделать это. В современных POSIX-операционных системах для этого можно использовать интерфейс inotify.

Можно использовать этот пакет: https://github.com/fsnotify/fsnotify

Пример кода:

watcher, err := fsnotify.NewWatcher()
if err != nil {
    log.Fatal(err)
}

done := make(chan bool)

err = watcher.Add(fileName)
if err != nil {
    log.Fatal(err)
}
for {
    select {
    case event := <-watcher.Events:
        if event.Op&fsnotify.Write == fsnotify.Write {
            log.Println("modified file:", event.Name)

        }
}

Надеюсь, это поможет!