[RBR] - I recently found myself needed to use subprocesses in Tcl in a non-trivial way, i.e., more than just running a process and grabbing its output. What I started looking for was something that gave me the power and flexibility I was accustomed to in C programs but I did not want to have to write the code in C. It took a bit of digging, but Tcl is perfectly capable of doing this. '''The Tcl Core Way''' The first way to do this is using the Tcl Core. Here is a short example showing event-oriented output handling from a subprocess: #! /usr/bin/tclsh proc logWrite {fh} { global forever pid errorCode; if {[gets $fh line] > 0} { puts "[clock format [clock seconds] -format {%b %d %T}] $line"; } elseif {[eof $fh]} { # capturing the exit status of the piped "child"-process # # without blocking, the close command won't wait until the # client finished and won't be able to tell if the client # cause an error while closing the pipe! # # so the close command has to wait until the child process # decides to exit - there is no way to force the exit of the # child process - only with a platform specific kill command # fconfigure $fh -blocking 1; if {[catch {close $fh;} result]} { if {($errorCode != {}) && ($errorCode != "NONE")} { puts stderr [format \ "\apiped child process %d exited abnormaly:\n\n%s\n" \ $pid \ $errorCode \ ]; } } set forever 1; } } set fh [open "|ls -l /tmp 2>@ stdout" r]; set pid [pid $fh]; puts "subprocess pid $pid" fconfigure $fh -buffering line -blocking 0; fileevent $fh readable [list logWrite $fh]; vwait forever; The major points of the above are that the process is started with stderr redirected into stdout, the pid is captured, an output handler captures data as available leaving the script to free to handle any other events. [RBR] - If you know how to capture the exit status of the above, please add that, and feel free to remove this comment afterwards. Also, do I need to do line buffering or turn off blocking to insure I don't block on [gets] and that I only get full lines? [male] - 2004/01/13: I added the code for capturing the exit status. [DLR] To avoid blocking forever in case process does not exits. Maybe add an "after $timeout timeoutWhileClosing" Where timeoutWhileClosing is a proc that will close the pipe, maybe log a message somewhere about it and set ::forever to 1