Powershell не захватывает стандартный вывод Perl
У меня есть следующий простой скрипт в powershell (скажем, под C:\Users\myusername\Desktop\tests\test.ps1
)
$counter = 0
while (1) {
$counter++
if ($counter % 2) {
[Console]::Error.WriteLine("($counter) This is an error")
} else {
echo "($counter) Some output"
}
sleep 1
}
Я хочу программно вызвать этот скрипт и записать его стандартный вывод и стандартную ошибку в файл (скажем, C:\Users\myusername\Desktop\test.log
). Для этого я написал следующий скрипт powershell:
$psi = New-object System.Diagnostics.ProcessStartInfo
$psi.CreateNoWindow = $true
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.FileName = 'C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe'
$psi.Arguments = @('C:\Users\myusername\Desktop\tests\test.ps1')
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi
$logAction = {
$time = Get-Date -Format o
Add-Content 'C:\Users\myusername\Desktop\test.log' "($time)[$($Event.MessageData)]: $($Event.SourceArgs.Data)"
}
Register-ObjectEvent -InputObject $process -EventName ErrorDataReceived -Action $logAction -MessageData "STDERR" >$null
Register-ObjectEvent -InputObject $process -EventName OutputDataReceived -Action $logAction -MessageData "STDOUT" >$null
$process.Start() >$null
$process.BeginErrorReadLine() >$null
$process.BeginOutputReadLine() >$null
$process.Id
Содержание test.log
файл, как и ожидалось:
(2018-12-05T15:00:45.7615056+01:00)[STDERR]: (1) This is an error
(2018-12-05T15:00:47.0119743+01:00)[STDOUT]: (2) Some output
(2018-12-05T15:00:47.9497710+01:00)[STDERR]: (3) This is an error
(2018-12-05T15:00:49.8253980+01:00)[STDOUT]: (4) Some output
(2018-12-05T15:00:49.8253980+01:00)[STDERR]: (5) This is an error
(2018-12-05T15:00:51.2008546+01:00)[STDOUT]: (6) Some output
(2018-12-05T15:00:51.8260768+01:00)[STDERR]: (7) This is an error
(2018-12-05T15:01:03.6269252+01:00)[STDERR]:
(2018-12-05T15:01:03.6269252+01:00)[STDOUT]:
Но теперь наступает интересная часть. У меня есть следующий скрипт на Perl (скажем, под C:\Users\myusername\Desktop\tests\test.pl
), который я запускаю в Windows, используя http://strawberryperl.com/, и который в значительной степени напоминает первый скрипт powershell в моем вопросе:
#!/usr/bin/perl
use strict;
use warnings;
my $counter = 0;
while (1) {
$counter++;
if ($counter % 2) {
print STDERR "($counter) This is an error!\n";
} else {
print STDOUT "($counter) Some message\n";
}
sleep 1;
}
Я также хочу программно вызвать этот скрипт и записать его стандартный вывод и стандартную ошибку в файл. Для этого я изменил второй скрипт в моем вопросе, обновив $psi.FileName
а также $psi.Arguments
значения для:
$psi.FileName = 'C:\Strawberry\perl\bin\perl.exe'
$psi.Arguments = @('C:\Users\myusername\Desktop\tests\test.pl')
Но теперь содержание test.log
файл не то, что я ожидал
(2018-12-05T14:14:53.9176561+01:00)[STDERR]: (1) This is an error!
(2018-12-05T14:14:55.7926306+01:00)[STDERR]: (3) This is an error!
(2018-12-05T14:14:57.9801317+01:00)[STDERR]: (5) This is an error!
(2018-12-05T14:15:22.2301618+01:00)[STDOUT]:
(2018-12-05T14:15:22.2301618+01:00)[STDERR]:
Как видите, стандартный вывод не захватывается. Я понятия не имею, почему это происходит и как я могу это решить. Почему это не работает для Perl, но это для PowerShell? Как я могу заставить его работать с Perl?
Моя версия powershell 5.1.17134.407 на Windows 10 Pro.
1 ответ
STDERR обычно устанавливается для автоматической промывки, STDOUT - нет. Ваш код ожидает получить каждую строку вывода, как она написана.
Попробуйте добавить следующие 2 строки в ваш скрипт на Perl после use warnings;
use IO::Handle;
STDOUT->autoflush(1);