Это очень хорошо может подпадать под принцип KISS (будь проще), но мне все еще любопытно и я хочу узнать, почему я не получил ожидаемых результатов.Итак, поехали ...
У меня есть сценарий оболочки для захвата STDOUT и STDERR без нарушения исходных файловых дескрипторов.Это в надежде сохранить исходный порядок вывода (см. test.pl
ниже), как видно пользователю на терминале.
К сожалению, я ограничен использованием sh вместо bash (но я приветствую примеры), так как я вызываю это из другого набора, и я могу захотеть использовать его в cron в будущем (я знаю, что cron имеет переменную окружения SHELL
).
wrapper.sh
содержит:
#!/bin/sh
stdout_and_stderr=$1
shift
command=$@
out="${TMPDIR:-/tmp}/out.$$"
err="${TMPDIR:-/tmp}/err.$$"
mkfifo ${out} ${err}
trap 'rm ${out} ${err}' EXIT
> ${stdout_and_stderr}
tee -a ${stdout_and_stderr} < ${out} &
tee -a ${stdout_and_stderr} < ${err} >&2 &
${command} >${out} 2>${err}
test.pl
содержит:
#!/usr/bin/perl
print "1: stdout1\n";
print STDERR "2: stderr1\n";
print "3: stdout2\n";
В сценарии:
sh wrapper.sh /tmp/xxx perl test.pl
STDOUT содержит:
1: stdout1
3: stdout2
STDERR содержит:
2: stderr1
Пока все хорошо ...
/tmp/xxx
содержит:
2: stderr1
1: stdout1
3: stdout2
Однако я ожидал, что /tmp/xxx
будет содержать:
1: stdout1
2: stderr1
3: stdout2
Может кто-нибудь объяснить мне, почему STDOUT и STDERR не добавляют /tmp/xxx
в порядке, который я ожидал?Я предполагаю, что фоновые процессы tee
блокируют ресурс /tmp/xxx
друг от друга, так как они имеют одно и то же «назначение».Как бы вы решили это?
related: Как записать stderr в файл при использовании "tee" с каналом?