windows - qué - stdout linux
Powershell: Capture el programa stdout y stderr para separar las variables (4)
¿Es posible redirigir stdout de un programa externo a una variable y stderr de programas externos a otra variable en una ejecución?
por ejemplo:
$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!";
}
Un ejemplo aburrido, sin embargo, me pregunto si eso es posible.
Debería utilizar las opciones Start-Process con -RedirectStandardError -RedirectStandardOutput. Esta otra publicación tiene un gran ejemplo de cómo hacer esto (tomada de la siguiente publicación):
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "ping.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "localhost"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode
Esta es también una alternativa que he usado para redirigir stdout y stderr de una línea de comando mientras todavía muestra el resultado durante la ejecución de powershell:
$command = "myexecutable.exe my command line params"
Invoke-Expression $command -OutVariable output -ErrorVariable errors
Write-Host "STDOUT"
Write-Host $output
Write-Host "STDERR"
Write-Host $errors
Otra posibilidad más para complementar lo que ya se dio.
Tenga en cuenta que esto no siempre funciona dependiendo de cómo se invoca el script, he tenido problemas con -OutVariable y -ErrorVariable cuando se invoca desde una línea de comandos estándar en lugar de una línea de comandos de PowerShell como esta:
PowerShell -File "./FileName.ps1"
Una alternativa que parece funcionar en la mayoría de las circunstancias es esta:
$stdOutAndError = Invoke-Expression "$command 2>&1"
Desafortunadamente, perderá salida a la línea de comando durante la ejecución del script y tendrá que Write-Host $stdOutAndError
después de que el comando regrese para hacerlo "parte del registro" (como una parte de un archivo por lotes de Jenkins). Y lamentablemente no separa stdout y stderr.
La forma más sencilla de hacerlo es usar un archivo para la salida de stderr, por ejemplo:
$output = & myprogram.exe ''argv[0]'', ''argv[1]'' 2>stderr.txt
$err = get-content stderr.txt
if ($LastExitCode -ne 0) { ... handle error ... }
También usaría $ LastExitCode para verificar si hay errores de las extensiones nativas de la consola.
Una opción es combinar la salida de stdout y stderr en una sola transmisión, luego filtrar.
Los datos de stdout serán cadenas, mientras que stderr produce objetos System.Management.Automation.ErrorRecord.
$allOutput = & myprogram.exe 2>&1
$stderr = $allOutput | ?{ $_ -is [System.Management.Automation.ErrorRecord] }
$stdout = $allOutput | ?{ $_ -isnot [System.Management.Automation.ErrorRecord] }