Трубный вывод командной строки построчно в 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"
В моем скромном тестировании выходные данные генерировались слишком быстро, чтобы я мог увидеть, работает ли это так, как вы указали.