'\" '\" 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. '\" '\" The definitions below are for supplemental macros used in Tcl/Tk '\" manual entries. '\" '\" .AP type name in/out ?indent? '\" Start paragraph describing an argument to a library procedure. '\" type is type of argument (int, etc.), in/out is either "in", "out", '\" or "in/out" to describe whether procedure reads or modifies arg, '\" and indent is equivalent to second arg of .IP (shouldn't ever be '\" needed; use .AS below instead) '\" '\" .AS ?type? ?name? '\" Give maximum sizes of arguments for setting tab stops. Type and '\" name are examples of largest possible arguments that will be passed '\" to .AP later. If args are omitted, default tab stops are used. '\" '\" .BS '\" Start box enclosure. From here until next .BE, everything will be '\" enclosed in one large box. '\" '\" .BE '\" End of box enclosure. '\" '\" .CS '\" Begin code excerpt. '\" '\" .CE '\" End code excerpt. '\" '\" .VS ?version? ?br? '\" Begin vertical sidebar, for use in marking newly-changed parts '\" of man pages. The first argument is ignored and used for recording '\" the version when the .VS was added, so that the sidebars can be '\" found and removed when they reach a certain age. If another argument '\" is present, then a line break is forced before starting the sidebar. '\" '\" .VE '\" End of vertical sidebar. '\" '\" .DS '\" Begin an indented unfilled display. '\" '\" .DE '\" End of indented unfilled display. '\" '\" .SO '\" Start of list of standard options for a Tk widget. The '\" options follow on successive lines, in four columns separated '\" by tabs. '\" '\" .SE '\" End of list of standard options for a Tk widget. '\" '\" .OP cmdName dbName dbClass '\" Start of description of a specific option. cmdName gives the '\" option's name as specified in the class command, dbName gives '\" the option's name in the option database, and dbClass gives '\" the option's class in the option database. '\" '\" .UL arg1 arg2 '\" Print arg1 underlined, then print arg2 normally. '\" '\" RCS: @(#) $Id: man.macros,v 1.1.1.1 2009/05/09 16:27:42 pcmacdon Exp $ '\" '\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. .if t .wh -1.3i ^B .nr ^l \n(.l .ad b '\" # Start an argument description .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. '\" # define tabbing values for .AP .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out '\" # BS - start boxed text '\" # ^y = starting y location '\" # ^b = 1 .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. '\" # BE - end boxed text (draw box now) .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. '\" # VS - start vertical sidebar '\" # ^Y = starting y location '\" # ^v = 1 (for troff; for nroff this doesn't matter) .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. '\" # VE - end of vertical sidebar .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. '\" # Special macro to handle page bottom: finish off current '\" # box/sidebar if in box/sidebar mode, then invoked standard '\" # page bottom macro. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. '\" # DS - begin display .de DS .RS .nf .sp .. '\" # DE - end display .de DE .fi .RE .sp .. '\" # SO - start of list of standard options .de SO .SH "STANDARD OPTIONS" .LP .nf .ta 4c 8c 12c .ft B .. '\" # SE - end of list of standard options .de SE .fi .ft R .LP See the \\fBoptions\\fR manual entry for details on the standard options. .. '\" # OP - start of full description for a single option .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. '\" # CS - begin code excerpt .de CS .RS .nf .ta .25i .5i .75i 1i .ft CW .sp .. '\" # CE - end code excerpt .de CE .fi .RE .ft R .sp .. .de UL \\$1\l'|0\(ul'\\$2 .. .TH blt::bgexec 3tcl 2.5 BLT "BLT Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME bgexec \- Run programs in the background while handling Tk events. kill \- Terminate program or send signal. .SH SYNOPSIS \fBblt::bgexec \fIvarName\fR ?\fIswitches\fR? \fIprogram\fR ?\fIarg\fR?... .br \fBblt::kill \fIprocessid\fR ?\fIsignal\fR? .BE .SH DESCRIPTION .PP The \fBkill\fR command terminates a \fIprocessid\fR or under unix sends a signal. .PP The \fBbgexec\fR command executes a \fIprogram\fR pipleline using the \fBTcl\fR event-loop allowing other events to continue to be serviced. Upon completion it sets the global variable \fIvarName\fR with a list of 4 status values: a text token, the process-id, the exit code, and a text message. \fBBgexec\fR provides capabilities similar to the \fBexec\fR command, but with added support for callbacks, output to variables and termination. .PP When used with no options, the returned value from \fBbgexec\fR is the output from the \fIprogram\fR. But when the last \fIarg\fR is an ampersand (&) the \fIprogram\fR runs detached, and \fBbgexec\fR immediately returns with a list of the process ids created in the command pipeline. Detached processes can be interrupted and terminated simply by setting \fIvarName\fR. .PP The valid \fIswitches\fR are as follows: .TP \fB\-check \fInum\fR Interval in ms to poll for the exiting processes. The default is 1000. .TP \fB\-closeonkill \fImillisecs\fR Force close of stdin/stdout on kill after the given interval. This lets kill finalize processes, even uninterruptably sleeping ones unable to receive signals. The default is \fB0\fR for do not force close. .TP \fB\-command \fIscript\fR Specifies a command to call upon command completion/termination. Two extra arguments are appended before the call. The data output from the command, and the status info as set into \fIvarName\fR. .TP \fB\-decodeerror \fIencodingName\fR Specifies the encoding of the stderr channel. This affects only data returned to the Tcl interpreter. No translation is done on file redirection. For example if data is to be converted from Unicode for use in Tcl, you would use the "unicode" encoding. The default is that no tranlation is performed. .TP \fB\-decodeoutput \fIencodingName\fR Specifies the encoding of the stdout channels. This affects only data returned to the Tcl interpreter. No translation is done on file redirection. For example if data is to be converted from Unicode for use in Tcl, you would use the "unicode" encoding. The default is that no tranlation is performed. .TP \fB\-echo \fIboolean\fR Indicates if the pipeline's stderr stream should be echoed. \fINote: this option is deprecated.\fR .TP \fB\-error \fIvarName\fR Specifies that a global variable \fIvarName\fR is to be set with the contents of stderr after the program 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 \fBtrue\fR. .TP \fB\-killsignal \fIsignal\fR Specifies the signal to be sent to the program when terminating. This option is available only on Unix. \fISignal\fR can either be a number (typically 1-32) or a mnemonic (such as SIGINT). If \fIsignal\fR is the empty string, then no signal is sent. The default signal is \fB9\fR (SIGKILL). .TP \fB\-lasterror \fIvarName\fR Specifies a variable \fIvarName\fR that is updated whenever data becomes available from standard error of the program. \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 program. \fIVarName\fR is a global variable. Unlike the \fB\-output\fR option, data is available as soon as it arrives. .TP \fB\-limit \fInumBytes\fR Limit the size of the returned data to \fInumBytes\fR, terminating the program if exceeded. The limit applies to both stdout and stderr. .TP \fB\-linebuffered \fIboolean\fR Specifies that updates should be made on a line-by-line basis. Normally when new data is available \fBbgexec\fR will set the variable (\fB\-lastoutput\fR and \fB\-lasterror\fR options) or invoke the command (\fB\-onoutput\fR and \fB\-onerror\fR options) delivering all the new data currently available. If \fIboolean\fR is true, only one line at a time will be delivered. This can be useful when you want to process the output on a line-by-line basis. The default value is \fBfalse\fR. .TP \fB\-local \fIboolean\fR When \fIboolean\fR is true, any unqualified variables or command options are treated as local to the current namespace. This is mostly useful for non-detaching (no ampersand) commands. Note that using this flag with a detached command will use variables from the current namespace, not from the current proc stack-frame. .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\-output \fIvarName\fR Specifies a global variable \fIvarName\fR to be set with the output of the program, upon completion. .TP \fB\-raise \fIboolean\fR When \fIboolean\fR is \fBtrue\fR, a non-zero return code from a non-detached command will raise an error (.ie emulates \fBexec\fR). The default is \fBfalse\fR an error is generated only if one of the following occurs: invalid options are given, a redirection error, or process creation failure (eg. executable program not found). Detached commands, of course, never raise an error on a non-zero return code. .TP \fB\-\|\-\fR This marks the end of the options. The following argument will be considered the name of a program even if it starts with a dash (\fB\-\fR). .SH USAGE Invoking \fBbgexec\fR without a trailing ampersand will block and wait for result. However, other Tcl events continue to be serviced. This prevents Tcl from hanging, eg: .PP .CS pack [text .t] set val [blt::bgexec myStatus du -s] .CE .PP Note that text widget .t continues to respond to events. .SH CALLBACKS Here is an example that invokes the Unix \fBdu\fR program with a \fB-command\fR callback. .PP .CS proc Done {data status} { puts "Done($status)\\n$data" } blt::bgexec myStatus -command Done du -s $dir & .CE .PP When \fBdu\fR has completed, the handler \fBDone\fR is called with data and status. Also, the global variable \fImyStatus\fR is set to contain the program's exit status, eg: .PP .CS EXITED 26811 0 {child completed normally} .CE .PP If \fImyStatus\fR is set before \fBdu\fR has completed, the process will be killed. Under Unix, this sends a signal (SIGKILL by default). Under Win32, \fBTerminateProcess\fR is called. .PP .SH VARIABLE Here is another example, this time using the \fB-output\fR option to direct output to a variable. .PP .CS global myStatus myOutput blt::bgexec myStatus -output myOutput du -s $dir puts "Disk usage for $dir is $myOutput" .CE .PP Upon completion, \fBMyOutput\fR will contain the output of the program. .SH STDERR Various \fBbgexec\fR options can be used to capture \fBstderr\fR separately from \fBstdout\fR. .PP .CS global myStatus myOutput myErrs blt::bgexec myStatus -output myOutput -error myErrs du -s $dir .CE .PP The \fB\-error\fR option is similar to \fB\-output\fR in that it sets a variable when the program completes with data written to stderr. .PP .SH LOCAL By default, \fBbgexec\fR treats variable or command options as being in the global namespace. The \fB-local\fR option can change this to use the current namespace. Thus data can be collected to namespace-local variables even those inside of procs, eg. .CS proc Work {} { blt::bgexec myStatus -local 1 -output val -error err du -s puts "VAL=$val" puts "ERR=$err" } .CE which collects data to local variables. .PP For detached processes, \fB-local\fR will cause data to aggregate to namespace variables, ie. outside the proc, eg. .CS namespace eval ::Ns { set pval {} set perr {} proc Work {} { blt::bgexec myStatus -local 1 -output pval -error perr du -s & } } .CE This collects data to \fB::Ns::pval\fR and stderr to \fB::Ns::perr\fR. Similarly, proc names (eg \fB-onoutput\fR) will be relative to the current namespace. .PP .SH PROGRESS The \fB\-output\fR and \fB\-error\fR variables are set only after the program completes. But if a program runs for a long time, you can gather data as it becomes available using the \fB\-onoutput\fR option. As new data becomes available, this command is executed, with data appended as an argument. .PP .CS proc GetInfo { data } { puts $data } blt::bgexec myStatus -onoutput GetInfo du -s $dir .CE .PP The \fB\-onerror\fR option performs a similar function for the stderr data stream. .PP .SH ERROR HANDLING Like \fBexec\fR, \fBbgexec\fR returns an error if the exit code of the program is non-zero. To handle this invoke \fBbgexec\fR from within a \fBcatch\fR. .PP .CS catch { blt::bgexec myStatus -output myOutput du -s $dir } .CE .PP Detached jobs will generate an error only if the program startup failed. Otherwise the only indication is the status code set in \fImyStatus\fR. .SH TKWAIT By default, \fBbgexec\fR waits for a program to finish and returns the resulting output. To detach a program simply append an ampersand (&) as the last argument on the command line, eg. .PP .CS global myStatus myOutput blt::bgexec myStatus -output myOutput du -s $dir & .CE .PP \fBBgexec\fR will then return immediately with the spawned process ids as the result. If needed \fBtkwait\fR can be used to wait for the program to finish: .PP .CS global myStatus myOutput blt::bgexec myStatus -output myOutput du -s $dir & ... tkwait variable myStatus .CE .PP Note however that using \fBtkwait\fR can be dangerous. Multiple \fBtkwait\fR/\fBvwait\fR calls must complete in the reverse order called. The BLT \fBbusy\fR command can be used to try and enforce this, but a better alternative is to just use \fB-command\fR instead. .SH DIFFERENCES WITH EXEC Using \fBbgexec\fR without an ampersand will not hang Tcl: events continue to be serviced by the event handler while the call blocks. Also unlike \fBexec\fR, an error will not be generated if output is appears on \fBstderr\fR. And output from \fBstderr\fR can be separately managed and collected (without having to redirect to files). Finally, \fBbgexec\fR ensures that invoked processes get properly cleaned up at termination. .SH DIFFERENCES WITH FILEEVENT Since Tk 4.0, a subset of \fBbgexec\fR can be achieved using the \fBfileevent\fR command. The steps for running a program in the background are: .PP Execute the program with the \fBopen\fR command (using the "|" syntax) and save the file handle. .CS global fileId set fileId [open "|du -s $dir" r] .CE 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. .CS fileevent fileId readable { if { [gets $fileId line] < 0 } { close $fileId set output $temp unset fileId temp } else { append temp $line } } .CE .PP However, \fBBgexec\fR is simpler and less error prone than using \fBopen\fR + \fBfileevent\fR. You don't have to worry about non-blocking I/O. Everything is handled for you automatically. .PP Moreover, \fBbgexec\fR can run programs that \fBfileevent\fR can not. \fBFileevent\fR assumes that the when stdout is closed the program has completed. But some programs, like the Unix \fBcompress\fR program, reopen stdout, fooling \fBfileevent\fR into thinking the program has terminated. In the example above, we assume that the program will write and flush its output line-by-line. However when running another program, your application can block in the \fBgets\fR command reading a partial line. .PP \fBBgexec\fR gives you get back the exit status of the program. It also lets you reliably kill detached processes and allows you to collect data from both stdout and stderr individually. Finally, since data collection is handled in C code, \fBbgexec\fR is faster and more efficient. .SH SEE ALSO busy, exec, tkwait, vwait .SH KEYWORDS exec, background, busy