To write stderr to screen and write BOTH stderr and stdout to a file -- AND have the lines for stderr and stdout come out in the same sequence they would if both were written to the screen:
Turns out to be a difficult problem, especially the part about having "same sequence" you would expect if you simply wrote them to the screen. In simple terms: Write each to its own file, do some background-process magic to mark each line (in each file) with the exact time the line was produced, and then: "tail --follow" the stderr file to the screen, but to see BOTH "stderr" and "stdout" together -- in sequence -- sort the two files (with exact-time markings on each line) together.
Code:
# 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'"
Yes, this seems elaborate, and it results in 4 output files (2 of which you can delete). It does appear this is a hard problem to solve, so it took several mechanisms.
In the end, to see the results from BOTH stdout and stderr in the sequence you would expect, run this:
cat $pth/$ffn.out.txt $pth/$ffn.err.txt | sort
The only reason the sequence is at least very close to what it would have been had both stdout and stderr simply gone to the screen is: Every single line is marked with a timestamp down to the millisecond.
To see stderr on screen as the process goes along, use this:
tail -f $pth/$ffn.out
Hope that helps someone out, who arrived here long after the original question was asked.