Перенаправление стандартного и ошибочного вывода при добавлении в тот же файл журнала - PullRequest
49 голосов
/ 19 января 2012

Мне нужно собрать стандартный вывод и журнал ошибок из нескольких процессов в один файл журнала.

Таким образом, каждый вывод должен добавлять к этому файлу журнала.

Я хочу назвать все задания такими строками:

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

Где я должен разместить информацию для добавления?

Ответы [ 4 ]

70 голосов
/ 20 января 2012

Чтобы добавить файл, вам нужно использовать немного другой подход.Вы все еще можете перенаправить стандартную ошибку отдельного процесса и стандартный вывод в файл, но чтобы добавить его в файл, вам необходимо выполнить одно из следующих действий:

  1. Чтение stdout /Содержимое файла stderr, созданное Start-Process
  2. Не использовать Start-Process и использовать оператор вызова, &
  3. Не использовать Start-Process и запустить процесс с.NET объекты

Первый способ будет выглядеть следующим образом:

$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

Второй способ будет выглядеть следующим образом:

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

Или это:

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

Третий способ:

$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
18 голосов
/ 23 октября 2013

Энди дал мне несколько хороших советов, но я хотел сделать это еще чище.Не говоря уже о том, что с помощью метода 2>&1 >> PowerShell жаловался мне на доступ к файлу журнала другим процессом, т. Е. И stderr, и stdout, пытающимися заблокировать файл для доступа, я полагаю.Итак, вот как я с этим справился.

Сначала давайте сгенерируем красивое имя файла, но это на самом деле просто для педантизма:

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

И вот тут начинается трюк:

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

С помощью start-transcript и stop-transcript вы можете перенаправить ВСЕ выходные команды PowerShell в один файл, но не работает правильно с внешними командами .Так что давайте просто перенаправим все выходные данные на стандартный вывод PS и позволим транскрипту делать все остальное.

На самом деле, я понятия не имею, почему инженеры MS говорят, что они еще не исправили это "из-завысокая стоимость и технические сложности, связанные с «когда это можно обойти таким простым способом.

В любом случае, выполнение каждой отдельной команды с start-process - это громоздкий ИМХО, но с этим методом все, что вам нужноdo добавляет код 2>&1 | Write-Output к каждой строке, в которой выполняются внешние команды.

17 голосов
/ 26 августа 2015

Как и оболочки Unix, PowerShell поддерживает > перенаправления с большинством вариантов, известных из Unix, включая 2>&1 (хотя странно, порядок не имеет значения - 2>&1 > file работает так же, как обычный > file 2>&1).

Как и большинство современных оболочек Unix, PowerShell также имеет ярлык для перенаправления как стандартной ошибки, так и стандартного вывода на одно устройство, хотя в отличие от других ярлыков перенаправления, которые в значительной степени следуют соглашению Unix, ярлык захвата всех использует новый sigil и написано так: *>.

Итак, ваша реализация может быть:

& myjob.bat *>> $logfile
0 голосов
/ 04 марта 2013

Возможно, это не так элегантно, но может также сработать следующее. Я подозреваю, что асинхронно это не будет хорошим решением.

$p = Start-Process myjob.bat -redirectstandardoutput $logtempfile -redirecterroroutput $logtempfile -wait
add-content $logfile (get-content $logtempfile)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...