proc setup filename {
text .t -width 60 -height 10 -yscrollcommand ".scroll set"
scrollbar .scroll -command ".t yview"
pack .scroll -side right -fill y
pack .t -side left
set ::fp [open $filename]
seek $::fp 0 end
}
proc read_more {} {
set new [read $::fp]
if {$new ne ""} {
.t insert end $new
.t see end
}
after 1000 read_more
}
setup logfile
read_more
# Notice this is portable code.
# An industrial-strength version would probably exploit
# namespaces ...See also tail and tailf
Arjen Markus What is not so obvious from the above code, is that there is no easy way to tell whether the process responsible for writing the file that is tailed has finished or not. So, it is not a solution (alas) for monitoring the output of a program that writes to file and then finishes.DKF 11Dec02 - There's no way to tell that anyway. And in any case, the process writing the file might not be on the same computer either.
People often ask for a way to 'pipe' from an external process into a text widget.
[MJ] The version below will allow more tail windows per interpreter.
proc tailf filename {
# if toplevel already exists wait 2 seconds before retrying
set now [clock seconds]
set tl .$now
if {[info commands $tl]!=""} {
after 2000 [list tailf $filename]
return
}
toplevel $tl
wm title $tl $filename
text $tl.t -width 60 -height 10 -yscrollcommand "$tl.scroll set"
scrollbar $tl.scroll -command "$tl.t yview"
pack $tl.scroll -side right -fill y
pack $tl.t -side left -expand 1 -fill both
set fp [open $filename]
seek $fp 0 end
set currpos [tell $fp]
close $fp
set mtime [file mtime $filename]
read_more ${tl}.t $filename $mtime $currpos
}
proc read_more {widget filename oldmtime oldpos } {
# check if the tail widget is not closed
if {![winfo exists $widget]} {
# tail window closed
return
}
set mtime [file mtime $filename]
set currpos $oldpos
if {$mtime != $oldmtime} {
set fd [open $filename r]
seek $fd $oldpos start
while {![eof $fd]} {
$widget insert end [read $fd]
}
$widget see end
set currpos [tell $fd]
close $fd
}
after 1000 [list read_more $widget $filename $mtime $currpos]
}
# example usage
tailf c:/test.log
tailf c:/test2.log
