วิธีเปลี่ยนเส้นทาง stdout และ stderr ไปยังไฟล์และแสดง stderr ไปยังคอนโซล?


18

ฉันรู้วิธีเปลี่ยนเส้นทางไปยังไฟล์และใช้ที ในระดับพื้นฐาน ดังนั้น

$ alias outanderr='bash -c "echo stdout >&1; echo stderr >&2"'
# A fake "application" displaying both output and error messages.

$ outanderr 1>file      # redirect stdout to a file, display stderr
stderr

$ outanderr 2>file      # redirect stderr to a file, display stdout
stdout

$ outanderr 1>file 2>&1 # redirect both to a file, display nothing

$ outanderr | tee file; echo "-- file contents --" && cat file
# redirect stdout to a file, display both (note: order is messed up)
stderr
stdout
-- file contents --
stdout

$ outanderr 2>&1 | tee file; echo "-- file contents --" && cat file
# redirect both to a file, display both
stdout
stderr
-- file contents --
stdout
stderr

คำถามคือสิ่งที่จะเขียนแทนเครื่องหมายคำถามเพื่อรับผลลัพธ์ด้านล่าง:

$ outanderr ???; echo "-- file contents --" && cat file
# redirect both to a file, display stderr
stderr
-- file contents --
stdout
stderr

Constaints:

  • สมมติว่าทุบตี
  • คำสั่งซื้อควรถูกเก็บไว้ในไฟล์
  • เนื้อหา stderr จะแสดงในแบบเรียลไทม์โดยบรรทัดคือไม่มีการบัฟเฟอร์
  • สามารถใช้ไฟล์สคริปต์แยกกันได้
  • อาจจำเป็นต้องใช้เวทย์มนตร์

outanderrคุณมีโปรแกรมที่ควบคุมได้มากแค่ไหน?
Kevin

1
@ เควินฉันคิดว่าคำถามทั่วไปมากกว่านั้น ที่นี่outanderrเป็นเพียงนามแฝงที่พิมพ์บรรทัดไปยัง stdout และอีกชื่อเป็น stderr แนวคิด (ถ้าเป็นไปได้) คือการสร้างโซลูชันทั่วไปที่สามารถทำงานกับโปรแกรมใด ๆ โดยไม่ต้องแก้ไข
lgeorget

@georget ฉันเข้าใจว่า แต่ฉันไม่เชื่อว่าเป็นไปได้ที่จะปฏิบัติตามข้อ จำกัด ทั้งหมดในการแก้ปัญหาทั่วไปอย่างเคร่งครัดดังนั้นฉันจึงเห็นว่าเราจะได้รับเฉพาะเจาะจงหรือไม่
Kevin

@Igeorget ถูกต้อง
TWiStErRob

คำตอบ:


12
2>&1 >>outputfile | tee --append outputfile

สำหรับการทดสอบง่าย:

echo -n >outputfile; bash -c "echo stdout >&1; echo stderr >&2" 2>&1 >>outputfile |
  tee --append outputfile; echo "outputfile:"; cat outputfile

แก้ไข 1:

สิ่งนี้ทำงานโดยการเขียน stdout (เท่านั้น) ลงในไฟล์ทำให้ sterr stdout เพื่อให้ผ่านไปป์และให้ทีเขียนเอาต์พุตไปยังไฟล์เดียวกัน

การเขียนทั้งสองจะต้องทำในโหมดต่อท้าย ( >>แทน>) มิฉะนั้นทั้งสองจะเขียนทับการส่งออกของแต่ละคน

เนื่องจาก pipe เป็นบัฟเฟอร์จึงไม่รับประกันว่าเอาต์พุตจะปรากฏในไฟล์ตามลำดับที่ถูกต้อง สิ่งนี้จะไม่เปลี่ยนแปลงหากแอปพลิเคชันเชื่อมต่อกับตัวอธิบายไฟล์ (สองไพพ์) สำหรับการสั่งซื้อที่รับประกันผลลัพธ์ทั้งสองจะต้องผ่านช่องทางเดียวกันและถูกทำเครื่องหมายตามลำดับ หรือคุณต้องการบางสิ่งที่แฟนซีจริงๆ:

  1. หากทั้ง stdout และ stderr ถูกเปลี่ยนเส้นทางไปยังไฟล์ (ไม่ใช่ไฟล์เดียวกัน!) และทั้งสองไฟล์อยู่ในปริมาณ FUSE โมดูล FUSE สามารถทำเครื่องหมายแต่ละการเขียนด้วยการประทับเวลาเพื่อให้แอปพลิเคชันที่สองสามารถเรียงลำดับข้อมูลได้อย่างถูกต้องและรวมเข้าด้วยกัน สำหรับไฟล์เอาต์พุตจริง หรือคุณไม่ทำเครื่องหมายข้อมูล แต่ให้โมดูลสร้างไฟล์เอาต์พุตรวม ส่วนใหญ่คงไม่มีโมดูล FUSE ที่ทำสิ่งนี้ ...
  2. ทั้ง stdout และ stderr /dev/nullอาจถูกนำไป strace -f -s 32000 -e trace=writeเอาท์พุทของโปรแกรมจะถูกแยกออกจากกันโดยการทำงานผ่าน คุณจะต้องย้อนกลับการหลบหนีในกรณีนั้น จำเป็นต้องพูดว่าแอปพลิเคชันไม่ทำงานเร็วขึ้นโดยการติดตาม
  3. อาจเข้าถึงได้โดยใช้โมดูล FUSE ที่มีอยู่แล้วและติดตามโมดูลแทนแอปพลิเคชัน นี่อาจเร็วกว่าการติดตามแอปพลิเคชันเนื่องจาก (หรือมากกว่า: ถ้า) โมดูลอาจมี syscalls น้อยกว่าแอปพลิเคชันมาก
  4. หากแอปพลิเคชันสามารถแก้ไขได้: แอปสามารถหยุดทำงานหลังจากแต่ละเอาต์พุต (แต่ฉันคิดว่านี่เป็นไปได้จากภายในเท่านั้น) และดำเนินการต่อหลังจากได้รับสัญญาณ (SIGUSR1 หรือ SIGCONT) แอปพลิเคชันที่อ่านจากไปป์จะต้องตรวจสอบทั้งไปป์และไฟล์สำหรับข้อมูลใหม่และส่งสัญญาณหลังจากข้อมูลใหม่แต่ละครั้ง ขึ้นอยู่กับชนิดของแอปพลิเคชันซึ่งอาจเร็วกว่าหรือช้ากว่าวิธีสเตรซ FUSE จะเป็นวิธีแก้ปัญหาความเร็วสูงสุด

1
Bah จับฉันในตอนกลางของการเขียนคำตอบเดียวกันอย่างแม่นยำว่าทำไมไม่ชา
Kevin

2
NB นี้มีเงื่อนไขการแข่งขันที่แนะนำความเป็นไปได้ในการสลับสาย / ออก แต่ฉันไม่คิดว่าจะหลีกเลี่ยงได้
Kevin

1
@ เควินที่เกิดขึ้นกับพวกเราที่ดีที่สุดฉันได้รับความเดือดร้อนจากมันมาก่อนและเกือบจะขอคุณลักษณะ "แสดงให้ฉันเห็นว่ามีใครบางคนกำลังเขียน" (ซึ่งจะซับซ้อนแม้ว่า) สำหรับฉันแล้วดูเหมือนว่าสภาพการแย่งชิงเกิดขึ้นเฉพาะในกรณีที่การเขียนไปยังไฟล์ (stdout) เกิดขึ้นหลังจากการเขียนไปยังไปป์ไลน์
Hauke ​​Laging

จะไม่ส่งทั้งไปstdoutและstderrที่teeหรือว่าฉันหายไปบางสิ่งบางอย่าง? ฉันคิดว่าข้อกำหนดของ OP เป็นtee stderrเพียงเท่านั้น
Joseph R.

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