Трубный вывод командной строки построчно в Windows

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

powershell "startmyserver | tee server.log"

Проблема заключается в том, что канал вызывает выполнение первой команды и ее полное выполнение до выполнения второй команды. Это означает, что я не могу контролировать стандартный вывод моего сервера, пока он действительно работает, что я и пытаюсь сделать (я не хочу выключать сервер, чтобы просто проверить самые последние сообщения журнала).

Для более простого примера я попытался pause, Что ж, pause не существует на Powershell, поэтому я должен был запустить его во вложенном cmd ракушка:

powershell "cmd /c pause | tee test.txt"

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

То, что я хочу сделать, это канал для потоковой передачи stdout строка за строкой к следующей команде. Другими словами, всякий раз, когда он встречает символ EOL, он должен посылать некоторый вывод, и это должно (в моем случае tee) заставлять текст появляться на экране и одновременно записываться в файл. (На самом деле, я даже не беспокоюсь о том, записывается ли текст в файл построчно, он может быть записан полностью в конце, хотя это не было бы идеально. Я просто хочу видеть строки на экране, как они написаны.)

Возможно ли это в командной строке и / или Powershell?

1 ответ

Решение

Эта проблема объясняется переполнением стека как тот факт, что PowerShell Tee-Object не сбрасывает поток вывода, а только ждет, пока источник сделает это, поэтому вы получите вывод в конце операции. Это по замыслу.

Обходной путь, предложенный в ответе, заключался в использовании этого кода:

./program | ForEach-Object {
    Write-Host $_
    $_
} | Set-Content program.log

Альтернативная формулировка, чтобы попробовать, если вышеупомянутое не сработало:

./program | ForEach-Object {
    [Console]::WriteLine($_)
    [Console]::Out.Flush()
    $_
} | Set-Content program.log

Таким образом, команда будет выглядеть так:

PowerShell -ExecutionPolicy Unrestricted "startmyserver | ForEach-Object { Write-Host $_; $_} | Set-Content server.log"

В моем скромном тестировании выходные данные генерировались слишком быстро, чтобы я мог увидеть, работает ли это так, как вы указали.

Другие вопросы по тегам