У меня нет решения, чтобы предложить вам, однако я могу дать некоторые объяснения относительно поведения, которое вы видите.
Во-первых, IPC::Open3
не должен работать, когда ваши файловые дескрипторы являются переменными;см. этот вопрос для более подробных объяснений.
Теперь, почему IPC::Run3
не работает?Во-первых, обратите внимание, что если не перенаправлять STDERR
и не запускать
run3 ["date"], undef, \$buffer, { append_stdout => 1 };
вместо
run3 ["date"], undef, \*STDOUT;
, то это работает, как и ожидалось.(вам нужно добавить { append_stdout => 1 }
или ваши предыдущие выходы к $buffer
будут перезаписаны)
Чтобы понять, что происходит в вашей программе, после
open(STDOUT, '>', \$buffer) or die "Can't redirect STDOUT: $!";
Добавить
print STDERR ref(\$buffer), "\n"
print STDERR ref(\*STDOUT), "\n"
который напечатает
SCALAR
GLOB
Это именно то, что IPC::Run3::run3
сделает, чтобы узнать, что делать с "stdout", который вы ему дадите (см. Источник: _fh_for_child_output
, который вызывается как run3
):
, если это скаляр, то используется временный файл (соответствующая строка $fh = $fh_cache{$what} ||= tempfile
, где tempfile
- это функция от File::Temp
.
С другой стороны, когда стандартный вывод равен GLOB
(илипривязанный к IO::Handle
), этот дескриптор файла используется напрямую (это строка кода ).
Что объясняет, почему при вызове run3
с \$buffer
это работает, но не с \*STDOUT
.
При перенаправлении STDERR
и вызове
run3 ["date"], undef, \$buffer, \$buffer, { append_stdout => 1, append_stderr => 1 };
все начинает казаться странным.понимаю, что происходит, но я поделюсь чВот что я нашел, и, надеюсь, кто-то поймет это.
Я изменил источник IPC::Run3
и добавил
open my $FP, '>', 'logs.txt' or die "Can't open: $!";
в начале подпрограммы run3
.При запуске я вижу только
Restored!
1: Test
на STDOUT (мой терминал), но logs.txt
содержит дату (что-то в строках Mon Mar 25 17:49:44 CET 2019
).
Инвестирование немного показывает, что fileno $FP
возвращает 1
(что, если я не ошибаюсь, обычно STDOUT
(но вы закрыли его, так что я не настолько удивлен, что его дескриптор можно использовать повторно)) и fileno STDOUT
возвращает 2
(это может зависеть от вашей версии Perl и других открытых файловых дескрипторов).То, что , похоже, происходит, так это то, что system
предполагает, что STDOUT
является файловым дескриптором 1
и, таким образом, печатает в $FP
вместо STDOUT
(хотя я просто предполагаю).
Пожалуйста, не стесняйтесь комментировать / редактировать, если вы понимаете, что происходит.