NAME
bgexec - Run Unix commands in the background while handling Tk events.

SYNOPSIS
bgexec varName ?option value?... command ?arg?...

DESCRIPTION

The bgexec command executes Unix commands in the background, allowing Tk to handle events. A global Tcl variable varName is set when the command has completed.

INTRODUCTION
Tcl's exec command is very useful for gathering information from the Unix system. It runs a Unix command and returns the output of the command as its result. This works well for Tcl-only applications. But in Tk applications, a problem occurs when a Unix command takes time to process. For example, let's say we want the get the disk usage of a directory. We'll use the Unix command du to get the summary. set out [exec du -s $dir] puts "Disk usage for $dir is $out" While du is running, scrollbars won't respond. None of the Tk widgets will be redrawn properly. The send command won't work. And the worst part is that the application appears hung up or dead. The problem is that while the application is waiting for du to finish, Tk is not handling X events.

The bgexec command performs the same functions as exec, but also allows Tk to handle events. You can execute a long-running Unix command and the Tk widgets will behave normally. When the command finishes, its output and the exit status are written to Tcl variables. This makes it easy to monitor and save the output of a command.

EXAMPLE
This is the disk usage example again, this time using bgexec. The Unix command syntax is exactly the same as the previous example, when we used exec. global myStatus myOutput bgexec myStatus -output myOutput du -s $dir puts "Disk usage for $dir is $myOutput" Two global variables, myStatus and myOutput, will be set by bgexec when the du command has completed. MyStatus will contain the command's exit status. MyOutput, specified by the -output option, will store the output of the command.

You can also terminate the command by setting the variable myStatus. If myStatus is set before du has completed, the process is killed by sending a configurable Unix signal (by default it's SIGKILL). It makes no difference what myStatus is set to. set myStatus {} There are other bgexec options to collect different types of information. global myStatus myOutput myErrs bgexec myStatus -output myOutput -error myErrs du -s $dir The -error option is similar to -output. It sets a global variable when the command completes. The variable will contain any data written to stderr by the command.

The -output and -error variables are written to only after the command completes. If the command takes a long time, you may want to receive its partial output. You can gather data as it becomes available using the -onoutput option. It specifies a Tcl command prefix. Whenever new data is available, this command is executed, with the data appended as an argument to the command. proc GetInfo { data } {
    puts $data } bgexec myStatus -onoutput GetInfo du -s $dir When output is available, the procedure GetInfo is called. The onerror option performs a similar function for the stderr data stream.

Like exec, bgexec returns an error if the exit code of the Unix command is not zero. If you think you may get a non-zero exit code, you might want to invoke bgexec from within a catch. catch { bgexec myStatus -output myOutput du -s $dir } By default, bgexec will wait for the command to finish. But you can detach the command by adding an ampersand (&) to the end of the command line. global myStatus myOutput bgexec myStatus -output myOutput du -s $dir & Bgexec will return immediately and its result will be a list of the spawned process ids. If at some point, you need to wait for the command to finish, you can use tkwait. When the command finishes, the variable myStatus will be written to, breaking the tkwait loop. global myStatus myOutput bgexec myStatus -output myOutput du -s $dir &
    ... tkwait variable myStatus

SYNTAX
The bgexec command takes the following form:

    bgexec varName ?option value?... command ?arg?...

VarName is the name of a global variable which is set when the designated Unix command has finished executing. The exit status of the command will be stored in varName. The exit status is a list of a status token, the process-id of the command, the exit code, and a status message. You can also prematurely terminate the command by setting varName. The command will be sent a signal to terminate it (by default the signal is a SIGKILL; see the -killsignal option).

Command is the name of the Unix command to be executed and args are any extra arguments for command. Command and args may be in any form accepted by exec. (See the exec manual for further information.) If the last argument is an ampersand (&), the command will be run detached, and bgexec will return immediately. VarName will still be set with the return status when command completes.

OPTIONS
Option is the switch name, always beginning with a dash (-). Value is the value of the option. Option-value pairs are terminated either by the Unix command name, or double dashes (--). The following options are available for bgexec:

-error varName
    Specifies that a global variable varName is to be set with the contents of stderr after the command has completed.

-keepnewline boolean
    Specifies that a trailing newline should be retained in the output. If boolean is true, the trailing newline is truncated from the output of the -onoutput and -output variables. The default value is true.

-killsignal signal
    Specifies the signal to be sent to the Unix command when terminating. Signal can either be a number (typically 1-32) or a mnemonic (e.g. SIGINT). If signal is the empty string, then no signal is sent. The default signal is 9 (SIGKILL).

-lasterror varName
    Specifies a variable varName that is updated whenever data becomes available from standard error of the Unix command. VarName is a global variable. Unlike the -error option, data is available as soon as it arrives.

-lastoutput varName
    Specifies a variable varName that is updated whenever data becomes available from standard output of the Unix command. VarName is a global variable. Unlike the -output option, data is available as soon as it arrives.

-output varName
    Specifies that a global variable varName is to be set with the output of the command, after the commmand has completed. If this option is not set, no output will be accumulated.

-onerror command
    Specifies the start of a Tcl command that will be executed whenever new data is available from standard error. The data is appended to the command as an extra argument before it is executed.

-onoutput command
    Specifies the start of a Tcl command that will be executed whenever new data is available from standard output. The data is appended to the command as an extra argument before it is executed.

-update varName
    Deprecated. This option is replaced by -onerror.

--  This marks the end of the options. The following argument will be considered the name of a Unix command even if it starts with a dash (-).

PREEMPTION
Because Tk events are handled while a Unix command is running, it's possible for an application to preempt itself with further user-interactions. Let's say your application has a button, that when pressed runs the disk usage example. While the du command is already running, the user may press the button again. The second bgexec command will preempt the first. This means that the first command can not finish until the second command has completed.

Care must be taken to prevent an application from preempting itself, by blocking further user-interactions (such as button clicks). The BLT busy command is very useful in these situations, temporarily preventing user interaction. See the busy manual for details.

DIFFERENCES WITH FILEEVENT
Some of the functionality of bgexec is now be provided in Tk 4.0 with the fileevent command. The steps for running a command in the background are:

Execute the Unix command with the open command (using the "|" syntax) and save the file handle. global fileId set fileId [open "|du -s $dir" r] Next register a Tcl code snippet with fileevent to be run whenever output is available on the file handle. The code snippet will read from the file handle and save the output in a variable. fileevent fileId readable {
    if { [gets $fileId line] < 0 } {
    close $fileId
    set output $temp
    unset fileId temp
    } else {
    append temp $line
    } } While this works with the above example, but there are some important differences.

The biggest advantage of bgexec is that it requires no additional Tcl code to run a Unix command. It's simpler, and therefore there's less chance of errors being introduced.

Bgexec also handles things that fileevent can not. For example, you can't get back the exit status of the command. In the code above, we're assuming that the command has completed once stdout is closed. The problem is that some commands, like compress, reopen stdout, which fool fileevent. We're also assuming that the Unix command will write its output line-by-line. Running another command, your application may block in the gets command, reading a partial line. Conversely, bgexec handles non-blocking I/O tranparently for you. Finally, since data collection is handled in C code, bgexec is faster, getting you back to the Tk event loop more quickly.

SEE ALSO
busy, exec, tkwait

KEYWORDS
exec, background, busy