Perl по умолчанию I/O слои буфер, и не использовать stdio
сделать это по умолчанию, поэтому unbuffer
и stdbuf
(которые изменяют Буферизацию stdio
по умолчанию) не работают.
Хотя Perl предоставляет свой собственный способ управления используемыми уровнями ввода / вывода: Переменная среды PERLIO
. В соответствии с документами man perlrun
должна быть возможность запустить set PERLIO=:unix
перед запуском команды или для необработанного ввода-вывода, основанного на дескрипторе Windows, который все еще может быть экспериментальным / ошибочным , set PERLIO=:win32
. Либо следует обойти нормальное поведение буферизации, перейдя прямо к необработанным системным вызовам.
Если предположить, что сама cat
не буферизована (я полагаю, что она использует необработанные операции чтения и записи без буферизации, так и должно быть), это все равно не гарантирует желаемого поведения. Perl может немедленно отправить данные в cat
, но если cat
удастся прочитать их и записать обратно быстрее, чем Perl сможет перейти к следующей строке и распечатать в STDERR
, вы все равно сначала увидите STDERR
. В локальных тестах (в Linux, но это должно быть очень похоже) с PERLIO=:unix
, piping to cat
, я увидел следующие результаты:
222111
333
затем:
222
111
333
затем:
111222
333
затем (дважды подряд):
111
222
333
Дело в том, что даже при буферизации вне уравнения трубопровод вводит условия гонки из-за параллелизма на уровне процесса. Единственный способ обойти это - убедиться, что оба потока идут в cat
:
perl -E "say STDOUT 111; say STDERR 222; say STDOUT 333;" 2>&1 | cat
последовательно выводит:
111
222
333
потому что все данные отправляются в cat
непосредственно перед выполнением следующей print
. Единственный другой способ получить (в основном) надежный заказ - это спать между отпечатками (что позволяет cat
выиграть гонку с помощью perl
).