Как отследить файл журнала в TCL - PullRequest
6 голосов
/ 29 ноября 2011

Скажем, есть файл 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?

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

Ответы [ 3 ]

4 голосов
/ 29 ноября 2011

Просто используйте 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 построчно.

0 голосов
/ 29 ноября 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
0 голосов
/ 29 ноября 2011

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

  1. В этом коде вы читаете из файла, а не добавляете его, это будет делать другой процесс, поэтомуследует открыть файл в режиме чтения, а не в режиме добавления, т.е.удалите опцию «a» из команды open.
  2. Вы должны искать в конце файла только один раз, прежде чем начнете читать, иначе вы пропустите материал, который будет добавлен позже, поэтому переместите команду поискавпереди цикла.
  3. В опубликованном коде вы ничего не делаете с текстом, который вы читаете - я приведу пример простой записи его обратно на стандартный вывод.
  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]
    }
    
...