Подтвердить что ты не робот

Перенаправление стандартного и выходного файла ошибки, добавляемого к одному и тому же лог файлу

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

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

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

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

Где мне нужно добавить эту информацию?

4b9b3361

Ответ 1

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

  • Прочитайте содержимое файла stdout/stderr, созданное Start-Process
  • Не использовать Start-Process и использовать оператор вызова &
  • Не использовать 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

Ответ 2

Энди дал мне несколько хороших указателей, но я хотел сделать это еще более чистым способом. Не говоря уже о том, что с помощью метода 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 в один файл, но он не работает правильно с внешними командами. Поэтому позвольте просто перенаправить все выходные данные на stdout PS и позволить транскрипту сделать все остальное.

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

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

Ответ 3

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

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

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

& myjob.bat *>> $logfile

Ответ 4

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

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