ในการเขียน stderr ไปที่หน้าจอและเขียนทั้ง stderr และ stdout ไปยังไฟล์ - และมีบรรทัดสำหรับ stderr และ stdout ออกมาในลำดับเดียวกันพวกเขาจะถ้าทั้งสองถูกเขียนลงบนหน้าจอ:
กลายเป็นปัญหาที่ยากโดยเฉพาะอย่างยิ่งส่วนที่เกี่ยวกับการมี "ลำดับเดียวกัน" ที่คุณคาดหวังว่าคุณจะเขียนมันลงบนหน้าจอ กล่าวง่ายๆ: เขียนแต่ละไฟล์ของตัวเองทำมายากลพื้นหลังกระบวนการเพื่อทำเครื่องหมายแต่ละบรรทัด (ในแต่ละไฟล์) ด้วยเวลาที่แน่นอนบรรทัดที่ผลิตและจากนั้น: "หาง - ติดตาม" ไฟล์ 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
หวังว่าจะช่วยให้ใครบางคนออกมาที่นี่มานานหลังจากถามคำถามเดิม