Getting Cleaned Up Output from a Command

Created by CecilWesterhof.

Sometimes I need the output from a command. But not all commands return 0 on success. For example when you ask the status of a systemd service that is not running systemctl returns 3. But the command is still successful. Also the following line can be appended to the output:

child process exited abnormally

That is why I created the following proc:

proc getCleanOutput {command nonerrors} {
    try {
        set status [exec {*}$command]
    } trap CHILDSTATUS {status opts} {
        set   errorStr "\nchild process exited abnormally"
        set   length   [string length $errorStr]
        set   retCode  [lindex $::errorCode 2]
        if {[regexp "$errorStr\$" $status]} {
            set status [string range $status 0 end-${length}]
        }
        if {! ($retCode in $nonerrors)} {
            error "'$command' returned $retCode\n$status"
        }
    } on error msg {
        error [format "'%s' gave unexpected error:\n%s" $command $msg]
    }
    return $status
}

When the program returns a value other as 0 the trap handles what needs to be done. It removes the extra line if it is appended and then checks if the return code is an acceptable one. If not an error is raised, otherwise the output from the program is returned.

If another error happens an error is raised.


As always: comments, tips and questions are appreciated.


KPV Another annoyance you may want to handle is that exec treats any output to stderr as an error case. The old way of handling this was to append 2>@1 but now there's a -ignorestderr switch.

CecilWesterhof The commands that I use at the moment do not do that, but it is certainly something I want to take into account. Probably with an extra optional parameter that defaults to False.


AMG: You can use my async package, or pieces thereof, to separately obtain stdout and stderr, as well as feed the command input while it runs, and run multiple commands simultaneously in a single thread and interpreter.