Как отслеживать файл журнала в TCL

Скажем, есть файл log.txt, и к нему постоянно добавляется какой-то журнал.

Я хочу отслеживать этот файл в среде TCL.

Я пробовал это, но это не сработало.

set log [open log.txt a]

for { } { true } { update; after 1000 } {

    # expected to get here the appended part
    read $log

    seek $log 0 end

}

Можно ли прочитать измененный файл с помощью того же дескриптора файла log, или мне придется закрыть и снова открыть файл log.txt?

Есть ли что-то вроде эквивалента Linux-команды tail -f в TCL?


person Vahagn    schedule 28.11.2011    source источник
comment
Может это поможет - http://code.activestate.com/recipes/65437-tail-a-file/   -  person jaypal singh    schedule 29.11.2011


Ответы (3)


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

В одном из моих проектов у меня есть что-то вроде этого для отслеживания файла трассировки, созданного проприетарным инструментом:

set fd [open [list | tail --follow=name --retry --lines 0 $opt(trace) 2>@1]]
chan event $fd readable [list FollowTrace $fd]

proc FollowTrace fd {
  if {[gets $fd line] < 0} {
    set code [catch {close $fd} err]
    if {$code == 0} {
      set ::result 0
    } else {
      puts stderr $err
      set ::result 1
    }
    return
  }

  switch -regexp -matchvar parts -- $line {
    {Tm_Session::Open.*FileName=([^,]+)} {
       TryMakeLock [FullPathname [lindex $parts 1]]
     }
     {Tm_Session::Close.*FileName=([^,]+)} {
        StartUpload [lindex $parts 1]
     }
  }
}

Общая идея состоит в том, что вы создаете tail в данном файле, затем входите в цикл обработки событий и обрабатываете вывод tail построчно.

person kostix    schedule 28.11.2011
comment
Хотя использование других инструментов, как правило, является отличным способом решения задач, ваше решение требует больше кода и требует внешней программы, чем просто реализация чистого решения tcl. - person Bryan Oakley; 29.11.2011
comment
@Bryan Oakley, я искренне приглашаю вас заглянуть в исходники хвоста GNU, чтобы узнать, что задача наблюдения за файлом, добавляемым извне, не такая простая задача, как кажется на первый взгляд. Конечно, это можно сделать с помощью Tcl (при условии, что вы сначала перенаправите соответствующий вызов fcntl () на уровень скрипта), но тогда почему? - person kostix; 29.11.2011
comment
Даже если вам нужна функция -follow = name, это не так уж сложно сделать в Tcl - например. см. мой Flog. - person Colin Macleod; 05.12.2011

Вы не за горами, нужно кое-что исправить:

  1. В этом коде вы читаете из файла, а не добавляете его, это будет делать какой-то другой процесс, поэтому файл должен открываться в режиме чтения, а не в режиме добавления, т.е. Отбросьте опцию «a» в команде открытия.
  2. Вам следует выполнить поиск до конца файла только один раз, прежде чем начать чтение, иначе вы пропустите то, что будет добавлено позже, поэтому переместите команду поиска перед циклом.
  3. В опубликованном коде вы ничего не делаете с прочитанным текстом - я приведу пример простой записи его обратно в stdout.
  4. Вам нужна только команда обновления, если ваша обработка в цикле включает обновление графического интерфейса или чего-то еще, для чего требуется цикл событий - это не требуется для опубликованного кода. В целом это дает:

    set log [open log.txt]
    seek $log 0 end
    
    for { } { true } { after 1000 } {
    
        # expected to get here the appended part
        puts -nonewline [read $log]
    }
    
person Colin Macleod    schedule 28.11.2011

Мне удалось написать tail -f эквивалент на чистом Tcl. Код ниже:

proc readHandler {handle} {
    puts -nonewline [read $handle]
    flush stdout
    # to reduce CPU overhead...
    after 1000
}

set hFile [open "file.log" "r"]
# seek to the end of file if needed
# seek $hFile 0 end 

fconfigure $hFile -buffering none -eofchar "" -blocking no
fileevent $hFile readable [subst {readHandler $hFile}]

#just for exiting into main event loop
vwait forever
person GrAnd    schedule 29.11.2011
comment
Я думаю, вы обнаружите, что файл всегда кажется читаемым, когда вы находитесь в его конце, поэтому обработчик запускается постоянно и бесполезно проглатывает весь ваш процессор. - person Colin Macleod; 29.11.2011
comment
Ok. Затем вы всегда можете вставить команду сна (например, after 1000) в обработчик, чтобы уменьшить накладные расходы ЦП. - person GrAnd; 30.11.2011