стандартный вывод в файл1, стандартный вывод в файл2, оба корректно чередуются с стандартным выводом и файлом - PullRequest
5 голосов
/ 12 августа 2011

Учитывая стороннюю программу, как бы одну одновременно:

  1. записать стандартный вывод в z.stdout
  2. запись stderr в z.stderr
  3. передать коды выхода соответственно
  4. записать оба в правильном порядке чередования в стандартный вывод

Вот тестовая программа (delayed_interleaved_stdout_stderr.pl), которую я использовал:

#!/usr/bin/env perl

use strict;
use warnings;

# fixme: debug, uncomment to force stdout flushing
# use English '-no_match_vars';
# $OUTPUT_AUTOFLUSH = 1;

# use sleeps to simulate delays and test buffering
use Time::HiRes 'sleep';

foreach my $num ( 0..9 ) {
  if ( 0 == $num % 2 ) {
    print STDOUT $num, ":stdout\n";
  }
  else {
    print STDERR $num, ":stderr\n";
  }
  sleep 0.25;
}

До сих пор я мог делать 1,2,3 с:

( set -o pipefail; \
  ( set -o pipefail; delayed_interleaved_stdout_stderr.pl \
    | tee z.stdout; exit $? \
  ) 3>&1 1>&2 2>&3 | tee z.stderr; exit $? \
) 3>&1 1>&2 2>&3

Благодаря связанному ответу lhunath и другу, я упростил его до:

delayed_interleaved_stdout_stderr.pl > >(tee z.stdout) 2> >(tee z.stderr >&2)

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

1:stderr
3:stderr
5:stderr
7:stderr
9:stderr
0:stdout
2:stdout
4:stdout
6:stdout
8:stdout

Запуск delayed_interleaved_stdout_stderr.pl сам по себе отображается в правильном порядке 0-9. Принудительное сбрасывание stdout работает должным образом (см. Раздел с комментариями fixme), но я не смогу изменить реальные файлы.

Может быть, я упускаю что-то простое и начинаю задумываться, возможно ли это вообще: (

Ответы [ 2 ]

2 голосов
/ 12 августа 2011

Требование 4 сложное.Логика буферизации для stdout и stderr скрыта в libc, и чтобы изменить ее, вам нужно обмануть приложение и подумать, что оно пишет в терминал.

unbuffer, который поставляется с ожидаемым пакетом, сделает это за вас,Предостережение: даже при записи в терминал stdout буферизуется по строкам, поэтому, если ваше приложение не пишет полные строки, это не сработает.

1 голос
/ 15 августа 2011

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

delayed_interleaved_stdout_stderr.pl > >(tee z.stdout) 2> >(tee z.stderr >&2)

Спасибо за помощь!

...