J'ai besoin de collecter la sortie standard et le journal des erreurs de plusieurs processus dans un seul fichier journal.
Donc, chaque sortie doit ajouter à ce fichier journal.
Je veux appeler tous les emplois avec des lignes comme celle-ci:
$p=start-process myjob.bat -redirectstandardoutput $logfile -redirecterroroutput $logfile -wait
Où dois-je mettre l'information à annexer?
Afin d’ajouter à un fichier, vous devrez utiliser une approche légèrement différente. Vous pouvez toujours rediriger l'erreur standard et la sortie standard d'un processus individuel vers un fichier. Toutefois, pour l'ajouter à un fichier, vous devez effectuer l'une des opérations suivantes:
Start-Process
&
Le premier moyen ressemblerait à ceci:
$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 deuxième façon ressemblerait à ceci:
& myjob.bat 2>&1 >> C:\MyLog.txt
Ou ca:
& myjob.bat 2>&1 | Out-File C:\MyLog.txt -Append
La troisième voie:
$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 m'a donné de bons conseils, mais je voulais le faire d'une manière encore plus propre. Sans parler de cela avec le 2>&1 >>
Méthode PowerShell m’a déploré que le fichier journal soit utilisé par un autre processus, c’est-à-dire que stderr et stdout essaient de verrouiller le fichier pour y accéder, je suppose. Alors, voici comment je me suis débrouillé.
Générons d’abord un nom de fichier Nice, mais c’est juste pour être pédant:
$name = "sync_common"
$currdate = get-date -f yyyy-MM-dd
$logfile = "c:\scripts\$name\log\$name-$currdate.txt"
Et voici où le truc commence:
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
Avec start-transcript
et stop-transcript
vous pouvez rediriger TOUTES les sorties des commandes PowerShell dans un seul fichier, mais cela ne fonctionne pas correctement avec des commandes externes . Nous allons donc simplement rediriger toute la sortie de ceux-ci vers la sortie standard de PS et laisser transcript faire le reste.
En fait, je ne comprends pas pourquoi les ingénieurs de Microsoft ont dit ne pas encore avoir résolu ce problème "en raison des coûts élevés et des complexités techniques impliquées", alors que cela peut être résolu de manière aussi simple.
De toute façon, en exécutant chaque commande avec start-process
est un énorme fouillis IMHO, mais avec cette méthode, tout ce que vous avez à faire est d’ajouter le 2>&1 | Write-Output
code à chaque ligne qui exécute des commandes externes.
Comme les shells Unix, PowerShell prend en charge les redirections >
Avec la plupart des variantes connues sous Unix, y compris 2>&1
(Bien qu'étrangement, l'ordre n'a pas d'importance - 2>&1 > file
Fonctionne exactement comme d'habitude. > file 2>&1
).
Comme la plupart des shells Unix modernes, PowerShell dispose également d’un raccourci permettant de rediriger à la fois les erreurs standard et les sorties standard vers le même périphérique. Toutefois, contrairement à d’autres raccourcis de redirection qui suivent à peu près la convention Unix, le raccourci capturé utilise un nouveau sigil et s'écrit comme suit: *>
.
Donc, votre implémentation pourrait être:
& myjob.bat *>> $logfile
Peut-être que ce n’est pas aussi élégant, mais ce qui suit pourrait aussi marcher. Je soupçonne de manière asynchrone que ce ne serait pas une bonne solution.
$p = Start-Process myjob.bat -redirectstandardoutput $logtempfile -redirecterroroutput $logtempfile -wait
add-content $logfile (get-content $logtempfile)