Para escrever stderr na tela e escrever AMBOS stderr e stdout em um arquivo - E fazer com que as linhas para stderr e stdout saiam na mesma sequência que seriam se ambas fossem gravadas na tela:
Acabou sendo um problema difícil, especialmente a parte de ter a "mesma sequência" que você esperaria se simplesmente as escrevesse na tela. Em termos simples: escreva cada um em seu próprio arquivo, faça alguma mágica do processo em segundo plano para marcar cada linha (em cada arquivo) com a hora exata em que a linha foi produzida e depois: "tail --follow" o arquivo stderr na tela , mas para ver AMBOS "stderr" e "stdout" juntos - em sequência - classifique os dois arquivos (com marcações de tempo exato em cada linha) juntos.
Código:
# 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'"
Sim, isso parece elaborado e resulta em 4 arquivos de saída (2 dos quais você pode excluir). Parece que este é um problema difícil de resolver, por isso foram necessários vários mecanismos.
No final, para ver os resultados de ambos stdout e stderr na sequência que você esperaria, execute o seguinte:
cat $pth/$ffn.out.txt $pth/$ffn.err.txt | sort
A única razão pela qual a sequência está pelo menos muito próxima do que seria se stdout e stderr simplesmente tivessem ido para a tela é: Cada linha é marcada com um carimbo de data / hora até o milissegundo.
Para ver o stderr na tela à medida que o processo avança, use o seguinte:
tail -f $pth/$ffn.out
Espero que ajude alguém que chegou aqui muito tempo depois que a pergunta original foi feita.