如何在TCL中跟踪日志文件

6

假设有一个名为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的等效命令?


也许这个可以帮助 - http://code.activestate.com/recipes/65437-tail-a-file/ - jaypal singh
3个回答

4

只需使用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的输出。

1
虽然利用其他工具通常是做事情的好方法,但您的解决方案需要更多的代码和外部程序,而不仅仅是实现一个纯tcl解决方案。 - Bryan Oakley
@Bryan Oakley,我真诚地邀请您深入研究GNU tail源代码,以了解监视外部追加文件的任务并不像乍一看那么容易。当然,可以使用Tcl来完成此任务(前提是您首先将相关的fcntl()调用拉入脚本级别),但这又何必呢? - kostix
即使您需要-follow=name功能,在Tcl中也不太难实现 - 例如,请参见我的Flog - Colin Macleod

0

你离正确只差一点,只需要修正一些小问题:

  1. 在此代码中,您正在从文件中读取而不是附加到文件中,某些其他过程将执行该操作,因此应以读模式而不是追加模式打开文件,即从打开命令中删除“a”选项。
  2. 在开始阅读之前,您应该只寻找文件的末尾一次,否则您将跳过稍后添加的内容,因此将查找命令移到循环之前。
  3. 在发布的代码中,您没有对读取的文本做任何事情-我将给出一个将其写回stdout的示例。
  4. 只有在循环内部处理涉及更新GUI或其他需要事件循环的内容时,才需要更新命令-对于发布的代码不需要它。 总之:

    set log [open log.txt]
    seek $log 0 end
    
    for { } { true } { after 1000 } {
    
        # 预计得到附加部分
        puts -nonewline [read $log]
    }
    

0

我已经成功地在纯Tcl上编写了tail -f的等效代码。以下是代码:

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

我认为你会发现当你在文件末尾时,该文件始终可读,因此处理程序会不断触发并无用地消耗所有CPU。 - Colin Macleod
好的。那么你可以在处理程序中插入睡眠命令(即 after 1000)来减少CPU开销。 - GrAnd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接