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

  1. #!/usr/bin/env tclsh
  2. #
  3. # Run a job and restart it if it dies.
  4. #
  5. # Probably needs much better signal handling. The shell 'trap' command is useful there.
  6. #
  7.  
  8. variable jobs
  9. variable restart_timeout
  10.  
  11. proc Read {chan cmd} {
  12. variable jobs
  13. variable restart_timeout
  14.  
  15. set data [read $chan]
  16. if {[eof $chan]} {
  17. fileevent $chan readable {}
  18. close $chan
  19. if {[set ndx [lsearch -exact $jobs $chan]] != -1} {
  20. set jobs [lreplace $jobs $ndx $ndx]
  21. }
  22. puts "EOF $chan $cmd"
  23. after $restart_timeout [list Start $cmd]
  24. } else {
  25. puts [list $chan [string length $data] [string range $data 0 40]]
  26. }
  27. }
  28.  
  29. proc Start {cmd} {
  30. variable jobs
  31. set f [open |$cmd r]
  32. fconfigure $f -blocking 0 -buffering line
  33. lappend jobs $f
  34. fileevent $f readable [list Read $f $cmd]
  35. }
  36.  
  37. proc main {} {
  38. variable jobs {}
  39. variable restart_timeout 5000
  40.  
  41. Start [list tail -f /var/log/messages]
  42. Start [list tail -f /var/log/syslog]
  43. vwait ::forever
  44. foreach job $jobs {
  45. catch {
  46. fileevent $job readable {}
  47. close $job
  48. }
  49. }
  50. return 0
  51. }
  52.  
  53. if {!$tcl_interactive} {
  54. set r [catch [linsert $argv 0 main] err]
  55. if {$r} {puts stderr $::errorInfo}
  56. exit $r
  57. }
  58.