Насколько я знаю, не существует элегантного способа сделать это (для не элегантного способа, который работает, но не симпатичен, прокрутите вниз до конца моего ответа). Я сомневаюсь, что вы можете сделать лучше, чем:
$ command >stdout.txt 2>stderr.txt && cat stdout.txt stderr.txt > both.txt
Есть несколько интересных трюков, которые вы можете использовать, но ни один из них, похоже, не удастся создать 3 файла лучше, чем указано выше. Основная проблема заключается в том, что файл both.txt
не будет отображать сообщения (STDERR и STDOUT) в правильном порядке. Это потому что (как объяснено здесь):
Когда вы перенаправляете стандартный вывод и стандартную ошибку в один и тот же файл, вы можете получить неожиданные результаты. Это связано с тем, что STDOUT является буферизованным потоком, а STDERR всегда небуферизованным.
Это означает, что каждый символ STDERR записывается, как только он становится доступным, в то время как STDOUT пишет вещи в пакетном режиме. Когда и STDOUT, и STDERR переходят в один и тот же файл, вы можете увидеть, что сообщения об ошибках появляются раньше, чем вы ожидали, по отношению к фактическому выводу вашей программы или скрипта. Не о чем беспокоиться, а просто побочный эффект буферизованных и небуферизованных потоков, вам просто нужно помнить об этом.
Лучшая альтернатива, которую я мог найти, - это использование bash-подоболочек, довольно сложная и все еще не отображающая вывод в правильном порядке. Я сделал простой Perl-скрипт test.pl
который печатает "OUT" в STDOUT
и "ERR" в STDERR
, повторяя процесс 3 раза:
#/usr/bin/perl
for($i=0; $i<=2; $i++){
print STDOUT "OUT\n";
print STDERR "ERR\n"
}
Обычный, не перенаправленный вывод:
$ ./test.pl
OUT
ERR
OUT
ERR
OUT
ERR
Чтобы перенаправить вывод (ы), я запустил:
(./test.pl 2> >(tee error.txt) > >(tee out.txt)) > both.txt
Это использует tee
, программу, которая будет печатать свои данные на экране и в имени файла. Итак, я перенаправляю STDERR
и передаю его в качестве входных данных tee
, приказывая записать его в файл error.txt
. Аналогично с STDOUT
и файлом out.txt
. Я помещаю все это в подоболочку ((...)
), чтобы затем я мог перехватить весь его вывод и перенаправить в both.txt
.
Теперь это работает, поскольку создает 3 файла, один с STDERR
, один с STDOUT
и один с обоими. Однако, как объяснено выше, это приводит к тому, что сообщения отображаются в неправильном порядке в both.txt
:
$ cat both.txt
ERR
ERR
ERR
OUT
OUT
OUT
Единственный способ обойти это , я смог найти , чтобы добавить время он был напечатан в каждой строке вывода , а затем сортировка, но она становится все серьезно запутанным и, на вашем месте, я бы спросить себя , если это действительно стоит:
$(./test.pl \
2> >(while read n; do echo `date +%N`" $n"; echo "$n" >>error.txt; done) \
> >(while read n; do echo `date +%N`" $n"; echo "$n" >> out.txt; done )) \
| gawk '{print $2}'> both.txt