Ich muss die Standardausgabe und das Fehlerprotokoll von mehreren Prozessen in einer einzigen Protokolldatei zusammenfassen.
Daher muss jede Ausgabe anhängen an diese Protokolldatei.
Ich möchte alle Jobs mit folgenden Zeilen aufrufen:
$p=start-process myjob.bat -redirectstandardoutput $logfile -redirecterroroutput $logfile -wait
Wo muss ich die Informationen anhängen?
Um an eine Datei anzuhängen, müssen Sie einen etwas anderen Ansatz verwenden. Sie können den Standardfehler und die Standardausgabe eines einzelnen Prozesses weiterhin in eine Datei umleiten. Um ihn jedoch an eine Datei anzuhängen, müssen Sie eine der folgenden Aktionen ausführen:
Start-Process
Erstellt wurde.&
Der erste Weg würde so aussehen:
$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
Der zweite Weg würde so aussehen:
& myjob.bat 2>&1 >> C:\MyLog.txt
Oder dieses:
& myjob.bat 2>&1 | Out-File C:\MyLog.txt -Append
Der dritte Weg:
$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
Andy gab mir ein paar gute Hinweise, aber ich wollte es noch sauberer machen. Ganz zu schweigen davon, dass sich PowerShell bei der Methode 2>&1 >>
Bei mir beschwert hat, dass auf die Protokolldatei von einem anderen Prozess zugegriffen wird, d. Also hier ist, wie ich es herumgearbeitet habe.
Lassen Sie uns zuerst einen netten Dateinamen generieren, aber das ist wirklich nur um pedantisch zu sein:
$name = "sync_common"
$currdate = get-date -f yyyy-MM-dd
$logfile = "c:\scripts\$name\log\$name-$currdate.txt"
Und hier beginnt der Trick:
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
Mit start-transcript
Und stop-transcript
Können Sie ALLE Ausgaben von PowerShell-Befehlen in eine einzelne Datei umleiten, aber bei externen Befehlen funktioniert dies nicht richtig . Lasst uns also einfach alle Ausgaben auf die Standardausgabe von PS umleiten und Transkription den Rest erledigen lassen.
Tatsächlich habe ich keine Ahnung, warum die MS-Ingenieure sagen, dass sie dies "aufgrund der hohen Kosten und der damit verbundenen technischen Komplexität" noch nicht behoben haben, wenn es auf solch einfache Weise umgangen werden kann.
In jedem Fall ist das Ausführen jedes einzelnen Befehls mit start-process
Ein großes Durcheinander, aber mit dieser Methode müssen Sie nur den 2>&1 | Write-Output
- Code an jede Zeile anhängen, in der externe Befehle ausgeführt werden.
Wie Unix-Shells unterstützt PowerShell >
leitet mit den meisten von Unix bekannten Variationen weiter, einschließlich 2>&1
(obwohl seltsam, Reihenfolge spielt keine Rolle - 2>&1 > file
funktioniert genauso wie das normale > file 2>&1
).
Wie die meisten modernen Unix-Shells verfügt auch PowerShell über eine Verknüpfung zum Umleiten von Standardfehlern und Standardausgaben auf dasselbe Gerät. Im Gegensatz zu anderen Umleitungsverknüpfungen, die weitgehend der Unix-Konvention entsprechen, wird für die Verknüpfung zum Erfassen aller Dateien eine neue sigil und wie folgt geschrieben: *>
.
Ihre Implementierung könnte also sein:
& myjob.bat *>> $logfile
Vielleicht ist es nicht ganz so elegant, aber das Folgende könnte auch funktionieren. Ich vermute asynchron wäre das keine gute Lösung.
$p = Start-Process myjob.bat -redirectstandardoutput $logtempfile -redirecterroroutput $logtempfile -wait
add-content $logfile (get-content $logtempfile)