Изменить стандартную ошибку на стандартный вывод
У меня есть сценарий PowerShell, который пишет в вывод ошибок. Сценарий может быть таким простым:
Write-Error 'foo'
Start-Sleep -s 5
Write-Error 'bar'
Сценарий, который я на самом деле вызываю, порождает внешний процесс, который занимает некоторое время для обработки и записи со стандартной ошибкой.
Теперь, когда я вызываю скрипт так:
. myScript.ps1
Я получаю сообщение об ошибке с обычным поведением PowerShell (т. Е. Красный текст и много отладочной информации). Поскольку этот текст не имеет отношения к PowerShell в моем реальном приложении, мне не нужна эта отладочная информация, и это только делает результат менее читаемым (и невозможным для обработки).
Есть ли способ перенаправить этот вывод прямо в стандартный вывод, чтобы я просто получил текст?
Я попробовал что-то вроде этого:
Write-Host ( . myScript.ps1 2>&1 )
но это задерживает вывод, пока все не будет завершено.
редактировать:
Что касается "отладочной информации", когда я запускаю скрипт прямо сейчас, вывод выглядит примерно так (красным):
C:\path\to\myScript.ps1 : foo
Bei Zeile:1 Zeichen:2
+ . <<<< 'C:\path\to\myScript.ps1'
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,myScript.ps1
C:\path\to\myScript.ps1 : bar
Bei Zeile:1 Zeichen:2
+ . <<<< 'C:\path\to\myScript.ps1'
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,myScript.ps1
Когда я запускаю скрипт с Write-Host ( . myScript.ps1 2>&1 )
где вывод ошибок записывается в стандартный вывод, я получаю такой результат:
foo bar
Это именно то, что я хотел бы получить на выходе, за исключением того, что Write-Host (..)
вывод выводится только после завершения скрипта, поэтому я не могу получить никакой информации о ходе выполнения скрипта.
редактировать 2:
Хорошо, чтобы приблизиться к моей реальной проблеме (потому что это трудно объяснить с помощью чистого PowerShell); У меня есть следующий скрипт на Python, который примерно напоминает то, что делает программа командной строки, которую я использую, то есть он выполняет некоторую обработку и выводит ход выполнения к стандартной ошибке:
#!/usr/bin/python
import sys, time
sys.stderr.write( 'Progressing... ' )
sys.stderr.flush()
time.sleep( 5 )
sys.stderr.write( 'done.\n' )
sys.stderr.flush()
Теперь, когда я звоню с python script.py
, он работает правильно и печатает "прогрессирующую" строку, ждет 5 секунд, а затем печатает "готово" в PowerShell (как обычный текст). Проблема в том, что теперь я хочу запустить это на работе, например так: Start-Job { python script.py }
,
Работа запускается правильно, а также отлично работает в фоновом режиме, но когда я хочу проверить ее выполнение с помощью Receive-Job <id>
Сначала я вообще не получаю вывод, а после завершения скрипта / программы (т.е. через 5 секунд) я получаю следующий вывод (снова красным):
Progressing... done.
+ CategoryInfo : NotSpecified: (Progressing... done.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Очевидно, это не то, что я пытаюсь получить. Вместо этого я хочу получить фактический вывод, который был напечатан со стандартной ошибкой, как в реальном времени (то есть, когда это происходит в скрипте), так и без этого отладочного текста, связанного с PowerShell.
2 ответа
Согласно разделу редактирования вопроса, это должно быть подходящим:
. MyScript.ps1 2>&1 | %{ Write-Host $_ }
Он пишет только "foo" и "bar", и они появляются, как только они происходят.
РЕДАКТИРОВАТЬ
На самом деле это еще проще и тоже отлично работает:
. MyScript.ps1 2>&1 | Write-Host
Но я держу оригинальный ответ. Этот код позволяет обрабатывать вывод ($_
) динамически и делать что-то еще (т.е. не просто записать это на хост).
РЕДАКТИРОВАТЬ 2
Внешняя программа, которая пишет в STDERR:
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; ++i)
{
Console.Error.WriteLine("Step " + i);
System.Threading.Thread.Sleep(2000);
}
}
}
}
Сценарий, который запускает это приложение как задание и периодически получает его выходные данные.
$ErrorActionPreference = 'continue'
$job = Start-Job { C:\TEMP\Test\ConsoleApplication1.exe 2>&1 }
for(;;) {
Receive-Job $job | Write-Host
Start-Sleep 2
}
Сценарий делает именно то, что вам нужно (для вашего раздела 2 редактирования): он отображает вывод, как только он становится доступным, и не показывает ненужную дополнительную информацию об ошибке.
PS Эта версия тоже работает:
$job = Start-Job { C:\TEMP\Test\ConsoleApplication1.exe }
for(;;) {
Receive-Job $job 2>&1 | Write-Host
Start-Sleep 2
}
Пытаться:
ps> $erroractionpreference = "silentlycontinue"
ps> .\myscript.ps1