Измените «стандартную ошибку» на «стандартный вывод» - PullRequest
5 голосов
/ 28 мая 2011

У меня есть сценарий 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 (..) заставляет вывод появляться только после завершения сценария,поэтому я не могу получить никакой информации о продвижении указанного сценария.

Чтобы действительно приблизиться к моей настоящей проблеме (потому что это трудно объяснить с помощью чистого 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

Очевидно, это не то, что я пытаюсь получить.Вместо этого я хочу получить фактический вывод, который был напечатан со стандартной ошибкой, как live (т.е. когда это происходит в скрипте), так и без этого отладочного текста, связанного с PowerShell.

Ответы [ 2 ]

4 голосов
/ 29 мая 2011

Согласно разделу вопроса edit , это должно быть подходящим:

. 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
}

Скрипт делает именно то, что вам нужно (для вашего edit 2 section): отображает выходные данные, как только они становятся доступными, и не отображает ненужную дополнительную информацию об ошибках.

PS Эта версия также работает:

$job = Start-Job { C:\TEMP\Test\ConsoleApplication1.exe }
for(;;) {
    Receive-Job $job 2>&1 | Write-Host
    Start-Sleep 2
}
1 голос
/ 29 мая 2011

Попробуйте:

$erroractionpreference = "silentlycontinue"
.\myscript.ps1
...