Чтобы записать stderr на экран и записать ОБА stderr и stdout в файл - И получить строки для stderr и stdout в той же последовательности, в которой они были бы, если бы оба были записаны на экран:
Оказывается, это сложная проблема, особенно та часть, которая касается «той же последовательности», которую можно ожидать, если вы просто напишите их на экран. Проще говоря: запишите каждый в свой файл, сделайте некоторую магию фонового процесса, чтобы пометить каждую строку (в каждом файле) точным временем, когда была произведена строка, а затем: «tail --follow» файл stderr на экран , но чтобы увидеть оба «stderr» и «stdout» вместе - по порядку - отсортируйте два файла (с отметками точного времени на каждой строке) вместе.
Код:
# Set the location of output and the "first name" of the log file(s)
pth=$HOME
ffn=my_log_filename_with_no_extension
date >>$pth/$ffn.out
date >>$pth/$ffn.err
# Start background processes to handle 2 files, by rewriting each one line-by-line as each line is added, putting a label at front of line
tail -f $pth/$ffn.out | perl -nle 'use Time::HiRes qw(time);print substr(time."0000",0,16)."|1|".$_' >>$pth/$ffn.out.txt &
tail -f $pth/$ffn.err | perl -nle 'use Time::HiRes qw(time);print substr(time."0000",0,16)."|2|".$_' >>$pth/$ffn.err.txt &
sleep 1
# Remember the process id of each of 2 background processes
export idout=`ps -ef | grep "tail -f $pth/$ffn.out" | grep -v 'grep' | perl -pe 's/\s+/\t/g' | cut -f2`
export iderr=`ps -ef | grep "tail -f $pth/$ffn.err" | grep -v 'grep' | perl -pe 's/\s+/\t/g' | cut -f2`
# Run the command, sending stdout to one file, and stderr to a 2nd file
bash mycommand.sh 1>>$pth/$ffn.out 2>>$pth/$ffn.err
# Remember the exit code of the command
myexit=$?
# Kill the two background processes
ps -ef | perl -lne 'print if m/^\S+\s+$ENV{"idout"}/'
echo kill $idout
kill $idout
ps -ef | perl -lne 'print if m/^\S+\s+$ENV{"iderr"}/'
echo kill $iderr
kill $iderr
date
echo "Exit code: $myexit for '$listname', list item# '$ix', bookcode '$bookcode'"
Да, это кажется сложным, и это приводит к 4 выходным файлам (2 из которых вы можете удалить). Похоже, что эту проблему трудно решить, поэтому потребовалось несколько механизмов.
В конце, чтобы увидеть результаты ОБА stdout и stderr в последовательности, которую вы ожидаете, запустите это:
cat $pth/$ffn.out.txt $pth/$ffn.err.txt | sort
Единственная причина, по которой последовательность, по крайней мере, очень близка к тому, что было бы, если бы stdout и stderr просто были выведены на экран, заключается в следующем: каждая строка помечена меткой времени до миллисекунды.
Чтобы увидеть stderr на экране во время процесса, используйте это:
tail -f $pth/$ffn.out
Надеюсь, что это поможет кому-то, кто прибыл сюда намного позже, чем был задан первоначальный вопрос.