Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture program stdout and stderr to separate variables

Is it possible to redirect stdout from an external program to a variable and stderr from external programs to another variable in one run?

For example:

$global:ERRORS = @();
$global:PROGERR = @();

function test() {
    # Can we redirect errors to $PROGERR here, leaving stdout for $OUTPUT?
    $OUTPUT = (& myprogram.exe 'argv[0]', 'argv[1]');

    if ( $OUTPUT | select-string -Pattern "foo" ) {
        # do stuff
    } else {
        $global:ERRORS += "test(): oh noes! 'foo' missing!";
    }
}

test;
if ( @($global:ERRORS).length -gt 0 ) {
    Write-Host "Script specific error occurred";
    foreach ( $err in $global:ERRORS ) {
        $host.ui.WriteErrorLine("err: $err");
    }
} else {
    Write-Host "Script ran fine!";
}

if ( @($global:PROGERR).length -gt 0 ) {
    # do stuff
} else {
    Write-Host "External program ran fine!";
}

A dull example however I am wondering if that is possible?

like image 540
dusz Avatar asked Jun 14 '14 16:06

dusz


People also ask

How can I redirect stdout and stderr to separate files?

By default, both standard error messages and standard output messages of interactive tasks are written to stdout on the submission host. To separate stdout and stderr and redirect to separate files, set LSF_INTERACTIVE_STDERR=y in lsf.

How do I redirect stdout and stderr to the same location?

Solution. Use the shell syntax to redirect standard error messages to the same place as standard output. where both is just our (imaginary) program that is going to generate output to both STDERR and STDOUT.

Can you redirect stdout and stderr to the same file?

When saving the program's output to a file, it is quite common to redirect stderr to stdout so that you can have everything in a single file. > file redirect the stdout to file , and 2>&1 redirect the stderr to the current location of stdout .


2 Answers

One option is to combine the output of stdout and stderr into a single stream, then filter.

Data from stdout will be strings, while stderr produces System.Management.Automation.ErrorRecord objects.

$allOutput = & myprogram.exe 2>&1
$stderr = $allOutput | ?{ $_ -is [System.Management.Automation.ErrorRecord] }
$stdout = $allOutput | ?{ $_ -isnot [System.Management.Automation.ErrorRecord] }
like image 161
Aaron Schultz Avatar answered Nov 03 '22 15:11

Aaron Schultz


The easiest way to do this is to use a file for the stderr output, e.g.:

$output = & myprogram.exe 'argv[0]', 'argv[1]' 2>stderr.txt
$err = get-content stderr.txt
if ($LastExitCode -ne 0) { ... handle error ... }

I would also use $LastExitCode to check for errors from native console EXE files.

like image 20
Keith Hill Avatar answered Nov 03 '22 13:11

Keith Hill