Posted to tcl by patthoyts at Tue Aug 31 10:41:30 GMT 2010view pretty

#!/usr/bin/env tclsh
#
# Run a job and restart it if it dies.
#
# Probably needs much better signal handling. The shell 'trap' command is useful there.
#

variable jobs
variable restart_timeout

proc Read {chan cmd} {
    variable jobs
    variable restart_timeout

    set data [read $chan]
    if {[eof $chan]} {
        fileevent $chan readable {}
        close $chan
        if {[set ndx [lsearch -exact $jobs $chan]] != -1} {
            set jobs [lreplace $jobs $ndx $ndx]
        }
        puts "EOF $chan $cmd"
        after $restart_timeout [list Start $cmd]
    } else {
        puts [list $chan [string length $data] [string range $data 0 40]]
    }
}

proc Start {cmd} {
    variable jobs
    set f [open |$cmd r]
    fconfigure $f -blocking 0 -buffering line
    lappend jobs $f
    fileevent $f readable [list Read $f $cmd]
}

proc main {} {
    variable jobs {}
    variable restart_timeout 5000

    Start [list tail -f /var/log/messages]
    Start [list tail -f /var/log/syslog]
    vwait ::forever
    foreach job $jobs {
        catch {
            fileevent $job readable {}
            close $job
        }
    }
    return 0
}

if {!$tcl_interactive} {
    set r [catch [linsert $argv 0 main] err]
    if {$r} {puts stderr $::errorInfo}
    exit $r
}