1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
|
'\"
'\" Copyright 1991-1997 by Bell Labs Innovations for Lucent Technologies.
'\"
'\" Permission to use, copy, modify, and distribute this software and its
'\" documentation for any purpose and without fee is hereby granted, provided
'\" that the above copyright notice appear in all copies and that both that the
'\" copyright notice and warranty disclaimer appear in supporting documentation,
'\" and that the names of Lucent Technologies any of their entities not be used
'\" in advertising or publicity pertaining to distribution of the software
'\" without specific, written prior permission.
'\"
'\" Lucent Technologies disclaims all warranties with regard to this software,
'\" including all implied warranties of merchantability and fitness. In no event
'\" shall Lucent Technologies be liable for any special, indirect or
'\" consequential damages or any damages whatsoever resulting from loss of use,
'\" data or profits, whether in an action of contract, negligence or other
'\" tortuous action, arising out of or in connection with the use or performance
'\" of this software.
'\"
'\" Bgexec command created by George Howlett.
'\"
.so man.macros
.HS bgexec BLT
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
bgexec \- Run Unix commands in the background while handling
Tk events.
.SH SYNOPSIS
\fBbgexec \fIvarName\fR ?\fIoption value\fR?... \fIcommand\fR ?\fIarg\fR?...
.BE
.SH DESCRIPTION
.PP
The \fBbgexec\fR command executes Unix commands in the background,
allowing Tk to handle events. A global Tcl variable \fIvarName\fR is
set when the command has completed.
.SH INTRODUCTION
Tcl's \fBexec\fR 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 \f(CWdu\fR to get the summary.
.DS
set out [exec du -s $dir]
puts "Disk usage for $dir is $out"
.DE
While \f(CWdu\fR is running, scrollbars won't respond. None of the Tk
widgets will be redrawn properly. The \fBsend\fR 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 \fIdu\fR
to finish, Tk is not handling X events.
.PP
The \fBbgexec\fR command performs the same functions as \fBexec\fR,
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.
.SH EXAMPLE
This is the disk usage example again, this time using \fBbgexec\fR.
The Unix command syntax is exactly the same as the previous example,
when we used \fBexec\fR.
.DS
global myStatus myOutput
bgexec myStatus -output myOutput du -s $dir
puts "Disk usage for $dir is $myOutput"
.DE
Two global variables, \f(CWmyStatus\fR and \f(CWmyOutput\fR, will be set by
\fBbgexec\fR when the \f(CWdu\fR command has completed. \f(CWMyStatus\fR
will contain the command's exit status. \f(CWMyOutput\fR, specified by the
\fB\-output\fR option, will store the output of the command.
.PP
You can also terminate the command by setting the variable \f(CWmyStatus\fR.
If \f(CWmyStatus\fR is set before \f(CWdu\fR has completed, the process
is killed by sending a configurable Unix signal (by default it's
SIGKILL). It makes no difference what \f(CWmyStatus\fR is set to.
.DS
set myStatus {}
.DE
There are other \fBbgexec\fR options to collect different types of
information.
.DS
global myStatus myOutput myErrs
bgexec myStatus -output myOutput -error myErrs du -s $dir
.DE
The \fB\-error\fR option is similar to \fB\-output\fR. It sets a global
variable when the command completes. The variable will contain
any data written to stderr by the command.
.PP
The \fB\-output\fR and \fB\-error\fR 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 \fB\-onoutput\fR 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.
.DS
proc GetInfo { data } {
puts $data
}
bgexec myStatus -onoutput GetInfo du -s $dir
.DE
When output is available, the procedure \f(CWGetInfo\fR is called.
The \fB\f-onerror\fR option performs a similar function for the stderr
data stream.
.PP
Like \fBexec\fR, \fBbgexec\fR 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 \fBbgexec\fR from within a \fBcatch\fR.
.DS
catch { bgexec myStatus -output myOutput du -s $dir }
.DE
By default, \fBbgexec\fR will wait for the command to finish.
But you can detach the command by adding an ampersand (&) to the
end of the command line.
.DS
global myStatus myOutput
bgexec myStatus -output myOutput du -s $dir &
.DE
\fBBgexec\fR 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 \fBtkwait\fR. When the command
finishes, the variable \f(CWmyStatus\fR will be written to, breaking the
\fBtkwait\fR loop.
.DS
global myStatus myOutput
bgexec myStatus -output myOutput du -s $dir &
...
tkwait variable myStatus
.DE
.SH SYNTAX
The \fBbgexec\fR command takes the following form:
.sp
\fB bgexec \fIvarName\fR ?\fIoption value\fR?... \fIcommand\fR ?\fIarg\fR?...
.sp
\fIVarName\fR 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 \fIvarName\fR. 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 \fIvarName\fR. The command will be sent a signal to
terminate it (by default the signal is a SIGKILL; see the
\fB\-killsignal\fR option).
.PP
\fICommand\fR is the name of the Unix command to be executed and
\fIargs\fR are any extra arguments for \fIcommand\fR. \fICommand\fR
and \fIargs\fR may be in any form accepted by \fBexec\fR. (See the
\fBexec\fR manual for further information.) If the last argument is
an ampersand (&), the command will be run detached, and \fBbgexec\fR
will return immediately. \fIVarName\fR will still be set with the
return status when \fIcommand\fR completes.
.SH OPTIONS
\fIOption\fR is the switch name, always beginning with a dash (\-).
\fIValue\fR 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 \fBbgexec\fR:
.TP
\fB\-error \fIvarName\fR
.br
Specifies that a global variable \fIvarName\fR is to be set with the
contents of stderr after the command has completed.
.TP
\fB\-keepnewline \fIboolean\fR
Specifies that a trailing newline should be retained in the
output. If \fIboolean\fR is true, the trailing newline is truncated
from the output of the \fB\-onoutput\fR and \fB\-output\fR variables.
The default value is \f(CWtrue\fR.
.TP
\fB\-killsignal \fIsignal\fR
Specifies the signal to be sent to the Unix command when
terminating. \fISignal\fR can either be a number (typically 1-32) or
a mnemonic (e.g. SIGINT). If \fIsignal\fR is the empty string,
then no signal is sent. The default signal is \f(CW9\fR (SIGKILL).
.TP
\fB\-lasterror \fIvarName\fR
Specifies a variable \fIvarName\fR that is updated whenever data
becomes available from standard error of the Unix command.
\fIVarName\fR is a global variable. Unlike the \fB\-error\fR option,
data is available as soon as it arrives.
.TP
\fB\-lastoutput \fIvarName\fR
Specifies a variable \fIvarName\fR that is updated whenever data
becomes available from standard output of the Unix command.
\fIVarName\fR is a global variable. Unlike the \fB\-output\fR option,
data is available as soon as it arrives.
.TP
\fB\-output \fIvarName\fR
.br
Specifies that a global variable \fIvarName\fR 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.
.TP
\fB\-onerror \fIcommand\fR
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.
.TP
\fB\-onoutput \fIcommand\fR
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.
.TP
\fB\-update \fIvarName\fR
Deprecated. This option is replaced by \fB\-onerror\fR.
.TP
\fB\-\|\-\fR
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 (\fB\-\fR).
.SH 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 \f(CWdu\fR command is
already running, the user may press the button again. The second
\fBbgexec\fR command will preempt the first. This means that the
first command can not finish until the second command has completed.
.PP
Care must be taken to prevent an application from preempting itself,
by blocking further user-interactions (such as button clicks). The
BLT \fBbusy\fR command is very useful in these situations, temporarily
preventing user interaction. See the \fBbusy\fR manual for
details.
.SH DIFFERENCES WITH FILEEVENT
Some of the functionality of \fBbgexec\fR is now be provided in Tk 4.0
with the \fBfileevent\fR command. The steps for running a command in
the background are:
.PP
Execute the Unix command with the \fBopen\fR command (using the "|"
syntax) and save the file handle.
.DS
global fileId
set fileId [open "|du -s $dir" r]
.DE
Next register a Tcl code snippet with \fBfileevent\fR 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.
.DS
fileevent fileId readable {
if { [gets $fileId line] < 0 } {
close $fileId
set output $temp
unset fileId temp
} else {
append temp $line
}
}
.DE
While this works with the above example, but there are some important
differences.
.PP
The biggest advantage of \fBbgexec\fR 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.
.PP
\fBBgexec\fR also handles things that \fBfileevent\fR 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 \f(CWcompress\fR,
reopen stdout, which fool \fBfileevent\fR. We're also assuming that
the Unix command will write its output line-by-line. Running another
command, your application may block in the \fBgets\fR command, reading
a partial line. Conversely, \fBbgexec\fR handles non-blocking I/O
tranparently for you. Finally, since data collection is handled in C
code, \fBbgexec\fR is faster, getting you back to the Tk event loop
more quickly.
.SH SEE ALSO
busy, exec, tkwait
.SH KEYWORDS
exec, background, busy
|