Per scrivere stderr sullo schermo e scrivere ENTRAMBE stderr e stdout in un file - E far sì che le linee per stderr e stdout escano nella stessa sequenza che farebbero se entrambi fossero scritti sullo schermo:
Risulta essere un problema difficile, in particolare la parte sull'avere la "stessa sequenza" che ti aspetteresti se li scrivessi semplicemente sullo schermo. In termini semplici: scrivi ciascuno nel suo file, esegui un po 'di magia in background per contrassegnare ogni riga (in ciascun file) con l'ora esatta in cui la riga è stata prodotta, quindi: "tail --follow" il file stderr sullo schermo , ma per vedere ENTRAMBE "stderr" e "stdout" insieme - in sequenza - ordina i due file (con marcature del tempo esatto su ciascuna riga) insieme.
Codice:
# 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'"
Sì, questo sembra elaborato e si traduce in 4 file di output (2 dei quali è possibile eliminare). Sembra che questo sia un problema difficile da risolvere, quindi ci sono voluti diversi meccanismi.
Alla fine, per vedere i risultati di ENTRAMBE stdout e stderr nella sequenza che ti aspetteresti, esegui questo:
cat $pth/$ffn.out.txt $pth/$ffn.err.txt | sort
L'unico motivo per cui la sequenza è almeno molto vicina a come sarebbe stata se sia stdout che stderr fossero semplicemente andati sullo schermo è: ogni singola riga è contrassegnata da un timestamp fino al millisecondo.
Per vedere stderr sullo schermo mentre il processo procede, usa questo:
tail -f $pth/$ffn.out
Spero che aiuti qualcuno, che è arrivato qui molto tempo dopo che è stata posta la domanda originale.