2012-01-19 11 views
31

Necesito recopilar la salida estándar y el registro de errores de varios procesos en un solo archivo de registro.Redirección de la salida estándar y de error que se agrega al mismo archivo de registro

De modo que cada salida debe anexar a este archivo de registro.

Quiero llamar a todos los puestos de trabajo con líneas de este tipo:

$p=start-process myjob.bat -redirectstandardoutput $logfile -redirecterroroutput $logfile -wait 

¿Dónde tengo que poner la información a anexar?

Respuesta

52

Para adjuntar a un archivo deberá utilizar un enfoque ligeramente diferente. Todavía se puede redirigir un error estándar de los procesos individuales y de salida estándar para presentar, pero con el fin de añadir a un archivo que necesita para hacer una de estas cosas:

  1. Leer el contenido del archivo stdout/stderr creados por Start-Process
  2. No utilizar Puesta en proceso y utilizar el operador de llamada &
  3. No utilizar Puesta en proceso e iniciar el proceso con objetos .NET

la primera forma se vería así:

$myLog = "C:\File.log" 
$stdErrLog = "C:\stderr.log" 
$stdOutLog = "C:\stdout.log" 
Start-Process -File myjob.bat -RedirectStandardOutput $stdOutLog -RedirectStandardError $stdErrLog -wait 
Get-Content $stdErrLog, $stdOutLog | Out-File $myLog -Append 

La segunda manera se vería así:

& myjob.bat 2>&1 >> C:\MyLog.txt 

O esto:

& myjob.bat 2>&1 | Out-File C:\MyLog.txt -Append 

La tercera vía:

$pinfo = New-Object System.Diagnostics.ProcessStartInfo 
$pinfo.FileName = "myjob.bat" 
$pinfo.RedirectStandardError = $true 
$pinfo.RedirectStandardOutput = $true 
$pinfo.UseShellExecute = $false 
$pinfo.Arguments = "" 
$p = New-Object System.Diagnostics.Process 
$p.StartInfo = $pinfo 
$p.Start() | Out-Null 
$p.WaitForExit() 
$output = $p.StandardOutput.ReadToEnd() 
$output += $p.StandardError.ReadToEnd() 
$output | Out-File $myLog -Append 
+2

Gran respuesta. Pero me parece que hay un error en la primera forma. En lugar de -redirecterroroutput, creo que debería ser -RedirectStandardError. – Grigory

+3

¡Buena captura! Reparado :-) –

+0

¿Funciona para Powershell Remoting? Tengo pruebas, creo que solo la segunda forma funciona para PS Remoting. – Kiquenet

0

Tal vez no es tan elegante. Pero, ¿esto también funcionaría? Sospecho asincrónicamente que esta no sería una buena solución.

$p=start-process myjob.bat -redirectstandardoutput $logtempfile -redirecterroroutput $logtempfile -wait 
add-content $logfile (get-content $logtempfile) 
+0

En realidad, no funciona porque Powershell no le permite redireccionar la salida estándar y redireccionar la salida del mismo archivo. "Proceso de inicio: este comando no puede ejecutarse porque" RedirectStandardOutput "y" RedirectStandardError "son los mismos. Dé diferentes entradas y ejecute su comando nuevamente". es el error que obtuve cuando intenté esto. – Bob

14

Andy me dio algunos buenos consejos, pero quería hacerlo de una manera aún más limpia. Sin mencionar que con el método 2>&1 >> PowerShell me reclamó sobre el archivo de registro al que accedía otro proceso, es decir, tanto stderr como stdout intentando bloquear el archivo para acceder, supongo. Así que aquí es cómo lo trabajé.

primer lugar vamos a generar un buen nombre, pero que en realidad es sólo por ser pedante:

$name = "sync_common" 
$currdate = get-date -f yyyy-MM-dd 
$logfile = "c:\scripts\$name\log\$name-$currdate.txt" 

Y aquí es donde empieza el truco:

start-transcript -append -path $logfile 

write-output "starting sync" 
robocopy /mir /copyall S:\common \\10.0.0.2\common 2>&1 | Write-Output 
some_other.exe /exeparams 2>&1 | Write-Output 
... 
write-output "ending sync" 

stop-transcript 

Con start-transcript y stop-transcript puede redireccionar toda la salida de Comandos de PowerShell a un solo archivo, pero it doesn't work correctly with external commands. Así que simplemente redirijamos todo el resultado de esos a la salida estándar de PS y dejamos que la transcripción haga el resto.

De hecho, no tengo idea de por qué los ingenieros de MS afirman que aún no han resuelto esto "debido al alto costo y la complejidad técnica que conlleva" cuando se puede solucionar de una manera tan simple.

De cualquier manera, ejecutar cada comando con start-process es un gran desorden en mi humilde opinión, pero con este método, todo lo que tienes que hacer es agregar el código 2>&1 | Write-Output a cada línea que ejecuta comandos externos.

+0

La mejor respuesta al problema. ¡Gracias! –

12

cáscaras como Unix, PowerShell admite > vuelve a dirigir con la mayor parte de las variaciones conocidas de Unix, incluyendo 2>&1 (aunque extrañamente, el orden no importa - 2>&1 > file funciona igual que el normal de > file 2>&1). Como la mayoría de los cartuchos Unix modernos, Powershell también tiene un atajo para redirigir stderr y stdout al mismo dispositivo, aunque a diferencia de otros atajos de redirección que siguen la convención de Unix, el atajo de captura utiliza un sigilo nuevo y está escrito como ese: *>.

Por lo que su aplicación podría ser:

& myjob.bat *>> $logfile 
Cuestiones relacionadas