วิธีเปลี่ยนเส้นทาง stderr และ stdout ไปยังไฟล์ต่าง ๆ และแสดงใน terminal ได้อย่างไร?


30

ฉันต้องการเห็นผลลัพธ์ของคำสั่งในเทอร์มินัลราวกับว่าไม่มีการเปลี่ยนเส้นทาง นอกจากนี้ stderr จะต้องถูกเปลี่ยนเส้นทางไปยัง err.log และ stdout จะต้องถูกเปลี่ยนเส้นทางไปยัง stdout.log

มันจะดีถ้ามีสำเนาที่ถูกต้องของสิ่งที่ปรากฏใน terminal เช่นข้อผิดพลาดที่พิมพ์เป็นและเมื่อมันเกิดขึ้นในไฟล์แยกต่างหาก: stdouterr.log


@Nuno ไม่มันไม่ใช่ OP ต้องการมีไฟล์ต่างกันสำหรับ stdout และ stderr
dogbane

@dogbane ใช่คุณพูดถูก ขอโทษสำหรับเรื่องนั้น.
Nuno C. Inácio

ฉันยังพบว่าคำถามนี้คุ้นเคยมาก ขอผมดูหน่อย ... นี่คืออันที่คล้ายกันมากunix.stackexchange.com/q/4195/250และนี่คืออันที่เกี่ยวข้องunix.stackexchange.com/q/1416/250
phunehehe

คำตอบ:


37

ใช้teeคำสั่งดังต่อไปนี้:

(cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log

3>&1 1>&2 2>&3 เป็นวิธีที่คุณสลับ stderr และ stdout เนื่องจาก tee สามารถยอมรับ stdout ได้เท่านั้น

ลองดูที่คำสั่งที Unixteeสำหรับการเปลี่ยนเส้นทางที่สูงขึ้นโดยใช้


ทางออกที่ดี มีวิธีการรับรหัสออก cmd หรือไม่?
turbanoff

2
@turbanoff แทนที่ด้วยcmd (cmd ; echo >exit_code.txt $?)
คู่ปรับ Shot

ฉันเชื่อว่าสิ่งนี้ควรรักษาลำดับของสิ่งต่าง ๆ ที่ส่งออกไปยังบรรทัดคำสั่ง:((cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log)
TTT

5

ฉันคิดว่าการบันทึก stdout และ stderr ไปยังสองไฟล์ต่างกันเป็นแนวคิดที่ยอดเยี่ยม มันไม่ได้ทำให้บันทึกตรงกันหรือไม่? ดังนั้นฉันลองทำสิ่งต่อไปนี้:

  • stdout เป็น "stdout.log" (ตามที่แนะนำ dogbane)
  • stderror ถึง "stderr.log" (ตามที่แนะนำ dogbane)
  • เอาต์พุตทั้งหมดไปที่ "all.log" และ
  • ยังคงสามารถเห็นเอาต์พุตบนจอแสดงผล (ในเทอร์มินัลแยกต่างหาก!)

((cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log) &> all.log

ในเทอร์มินัลอื่น

tail -f --sleep-interval=2 all.log

เป็นไปไม่ได้ที่จะนำ stderr ไปยัง tty ตัวที่สองโดยตรงหรือไม่? จากนั้นไม่จำเป็นต้องใช้ไฟล์บันทึก
Steven Lu

@StevenLu ใช่ถ้าคุณรู้ชื่อและได้รับอนุญาตให้เขียนไปยัง tty ที่สองที่สามารถทำได้
Jasen

1
จะง่ายขึ้น&| tee all.logในตอนท้ายของคำสั่งแทน&> all.log
Jasen

@Jasen: ครั้งที่ 2 &|ที่ผมเห็น ผมเข้าใจ&>, |&เกินไป แต่สิ่งที่ไม่&|ได้หมายความว่าในบริบทนี้? ฉันไม่พบการอ้างอิงไวยากรณ์ที่เหมาะสมไม่ได้อยู่ในเน็ตหรือแม้แต่ปรึกษา bash manual page "bash (1)" ... Tx
Cbhihe

1
@Chihhe เท่าที่ฉันสามารถบอกได้ว่ามันไม่ทำอะไรเลยฉันหมายถึงพูดว่า|&
Jasen

3

@dogbane ขอบคุณ
ฉันพบวิธีอื่นเช่นกันซึ่งช่วยประหยัดทั้งสองสตรีมโดยประมาณตามลำดับเนื่องจากจะถูกพิมพ์โดยไม่มีการเปลี่ยนเส้นทาง

command 2> >(tee errlog | tee -a bothLog > /dev/tty ) | tee outlog | tee -a bothLog

แต่ใช้งานได้กับเชลล์ที่รองรับการทดแทนกระบวนการเท่านั้น


-2

ลองนี้:

command 2>&1 | tee bothLog

4
สวัสดี vasile นี่ไม่ได้ตอบคำถาม: balki ต้องการไฟล์แยกต่างหากสำหรับ stdout และ stderr โซลูชันของคุณจะผสมทั้งสองอย่างในสตรีมเดียวกัน
เสื่อ

ทำไมผู้คนถึงรวม stdout และ stderr เข้าด้วยกัน? หรือบอกให้คนอื่นทำเช่นนั้น?
นูเร
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.