Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

An exec that displays output immediately

48 views
Skip to first unread message

Cecil Westerhof

unread,
Jul 8, 2018, 3:44:05 PM7/8/18
to
I wanted output from a command seen at once. With exec I only get to
see it when the command is finished. For this I created the following
proc:
proc execCmd {cmd {displayOutput True} {returnOutput False}} {
set cmdPipe [open |${cmd} RDONLY]
set output {}

while {-1 != [gets ${cmdPipe} line]} {
if {${displayOutput}} {
puts ${line}
}
if {${returnOutput}} {
lappend output ${line}
}
}
close ${cmdPipe}
return ${output}
}

Default it displays everything as soon as it becomes available and
returns nothing, but both can be overridden.

Is this OK, or should I do it in another way?

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

Rich

unread,
Jul 8, 2018, 4:59:47 PM7/8/18
to
Cecil Westerhof <Ce...@decebal.nl> wrote:
> I wanted output from a command seen at once. With exec I only get to
> see it when the command is finished. For this I created the following
> proc:
> proc execCmd {cmd {displayOutput True} {returnOutput False}} {
> set cmdPipe [open |${cmd} RDONLY]
> set output {}
>
> while {-1 != [gets ${cmdPipe} line]} {
> if {${displayOutput}} {
> puts ${line}
> }
> if {${returnOutput}} {
> lappend output ${line}
> }
> }
> close ${cmdPipe}
> return ${output}
> }
>
> Default it displays everything as soon as it becomes available and
> returns nothing, but both can be overridden.
>
> Is this OK, or should I do it in another way?

Two comments:

1) you are reading input line by line, but when you choose to return
the output, you are returning a list of lines, not a string. So the
return value from your proc is not identical to the return value from a
pure exec. If you want the same return value, change your return to
be: return [join $output \n]\n

The extra \n on the end is to account for the very last \n that was
dropped by the very last gets in the loop.

2) This will work just fine, as long as you do not want to use it as
part of an event loop (either in a GUI or in a CLI that itself makes
use of the event loop). When in an event loop this variant will pause
the event loop until the exec'ed process exits. This may or may not be
what you want, depending on what the code using this proc would be
trying to do when calling it.

Cecil Westerhof

unread,
Jul 8, 2018, 7:28:04 PM7/8/18
to
I have to think about that. I think it is handy to return a list, but
there is merit in what you say.


> 2) This will work just fine, as long as you do not want to use it as
> part of an event loop (either in a GUI or in a CLI that itself makes
> use of the event loop). When in an event loop this variant will pause
> the event loop until the exec'ed process exits. This may or may not be
> what you want, depending on what the code using this proc would be
> trying to do when calling it.

Not at the moment. I just want to be able to do something like:
execCmd "ping -c4 -i5 ping.xs4all.nl"

And see the lines at the moment they are generated and not when the
command is finished.

Should put something in the comment about not using it with an event
loop. ;-)

Rich

unread,
Jul 9, 2018, 7:04:48 AM7/9/18
to
Agreed. A list of lines is much more handy, but that differs from the
standard Tcl 'exec' command's return value enough that you need to be
careful to remember which you are using at a given time.

0 new messages