【问题标题】:How to track a log file in TCL如何在 TCL 中跟踪日志文件
【发布时间】:2011-11-28 21:16:56
【问题描述】:

假设有一个文件 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/

标签: linux logging tcl tail


【解决方案1】:

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

【讨论】:

  • 虽然利用其他工具通常是做事的好方法,但您的解决方案需要更多的代码,并且需要一个外部程序,而不仅仅是实现一个纯 tcl 解决方案。
  • @Bryan Oakley,我真诚地邀请您查看 GNU 尾部源代码,以发现观看外部附加文件的任务并不像乍一看那样容易.当然可以使用 Tcl 来完成(前提是您首先将相关的 fcntl() 调用拉入脚本级别),但是为什么呢?
  • 即使您需要 -follow=name 功能,在 Tcl 中也不会太难 - 例如。见我的Flog
【解决方案2】:

您已经不远了,只需解决一些问题:

  1. 在这段代码中,您是从文件中读取,而不是附加到它,其他一些进程会这样做,因此应该以读取模式打开文件,而不是附加模式,即。从 open 命令中删除“a”选项。
  2. 在开始阅读之前,您应该只查找文件末尾一次,否则您将跳过稍后添加的内容,因此将查找命令移到循环之前。
  3. 在发布的代码中,您没有对阅读的文本做任何事情 - 我将举一个例子,将其写回标准输出。
  4. 如果您在循环中的处理涉及更新 gui 或其他需要事件循环的东西,您只需要 update 命令 - 发布的代码不需要它。 总而言之:

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

【讨论】:

    【解决方案3】:

    我已经设法在纯 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。
    • 好的。然后你总是可以在处理程序中插入睡眠命令(即after 1000)以减少CPU开销。
    猜你喜欢
    • 2012-03-11
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多