มีวิธีการเปลี่ยนเส้นทางการส่งออกไปยังไฟล์โดยไม่บัฟเฟอร์ใน unix / linux หรือไม่


49

ฉันมีกระบวนการแบตช์ที่รันเป็นเวลานานซึ่งส่งเอาต์พุตการดีบักและประมวลผลข้อมูลบางส่วนไปยัง stdout ถ้าฉันเพิ่งเรียกใช้จากเทอร์มินัลฉันสามารถติดตาม 'อยู่ที่ไหน' แต่จากนั้นข้อมูลได้มากเกินไปและเลื่อนออกจากหน้าจอ

หากฉันเปลี่ยนเส้นทางไปยังเอาต์พุตไปยังไฟล์ '> out.txt' ฉันจะได้รับผลลัพธ์ทั้งหมดในที่สุด แต่จะถูกบัฟเฟอร์ดังนั้นฉันจึงไม่เห็นสิ่งที่กำลังทำอยู่อีกต่อไป

มีวิธีการเปลี่ยนเส้นทางการส่งออก แต่ทำให้มันไม่บัฟเฟอร์เขียนมันได้หรือไม่


1
คุณช่วยกรุณาดูที่ "อภิปราย" ของฉัน (และ @cnst) ด้านล่างฉันเดาว่าสิ่งเดียวที่คุณต้องการคือการเห็นผลลัพธ์ในเวลาเดียวกับการบันทึกลงในไฟล์ หากคุณพบวิธีแก้ไขให้เราทราบเกี่ยวกับมัน;)!
Benj

คำตอบ:


52

คุณสามารถตั้งค่าตัวเลือกการบัฟเฟอร์ของสตรีมมาตรฐานอย่างชัดเจนโดยใช้การsetvbufโทรใน C (ดูลิงค์นี้ ) แต่หากคุณกำลังพยายามปรับเปลี่ยนพฤติกรรมของการลองใช้โปรแกรมที่มีอยู่stdbuf(ส่วนหนึ่งของการcoreutilsเริ่มต้นด้วยเวอร์ชัน 7.5)

บัฟเฟอร์นี้stdoutขึ้นอยู่กับบรรทัด:

stdbuf -oL command > output

สิ่งนี้ปิดใช้งานstdoutการบัฟเฟอร์ทั้งหมด:

stdbuf -o0 command > output

aaarghhh ... อูบุนตูของฉันมีแกนกลาง 7.4 เท่านั้น ... :(
Calmarius

@Calarius: รวบรวม coreutils ควรจะค่อนข้างง่าย เพียงแค่หยิบเวอร์ชันใหม่จากftp.gnu.org/gnu/coreutilsและไปได้เลย มันเป็นค่า./configure && makeโดยสารมาตรฐาน คุณไม่ได้มีการติดตั้งหลังจากนั้นคุณก็สามารถใช้ไบนารีปิดstdbuf src/
Eduardo Ivanec

double argh ฉันต้องการสิ่งนี้ใน centos distro AND OSX และ Ubuntu
edk750

คำตอบ upvoted เพิ่มเติมอีกunix.stackexchange.com/a/25378/5510
เทรเวอร์บอยด์สมิ ธ

มีวิธีบังคับบัฟเฟอร์ไปป์ / printf ภายนอกจากกระบวนการที่กำลังทำงานด้วย PID ที่รู้จักหรือไม่?
Mvorisek

9

คุณสามารถใช้เอาต์พุตบัฟเฟอร์บรรทัดกับไฟล์โดยใช้scriptคำสั่งดังนี้:

stty -echo -onlcr   # avoid added \r in output
script -q /dev/null batch_process | tee output.log        # Mac OS X, FreeBSD
script -q -c "batch_process" /dev/null | tee output.log   # Linux
stty echo onlcr

-1 เนื่องจาก: a) ต่างจากคำตอบที่ยอมรับซึ่งใช้ไม่ได้หากคุณต้องการรันคำสั่งในพื้นหลัง (คำสั่งจะยุติทันทีโดยไม่จบbatch_processถ้าคุณต่อท้าย&คำสั่งด้านบนอย่างน้อยในกล่อง Linux ของฉัน) ซึ่งดูเหมือนว่า เช่นกรณีการใช้งานที่ธรรมดามากและข) ไม่มีคำอธิบายใด ๆ เกี่ยวกับการใช้คาถานี้
Mark Amery

8

บน Ubuntu แพคเกจunbufferโปรแกรม (จากexpect-dev) ทำเคล็ดลับสำหรับฉัน เพิ่งรัน:

unbuffer your_command

และมันจะไม่บัฟเฟอร์มัน


6

วิธีแก้ปัญหาที่ง่ายที่สุดที่ฉันพบ (ไม่จำเป็นต้องติดตั้งแพ็กเกจของ บริษัท อื่น) ถูกกล่าวถึงในเธรดที่คล้ายกันบนบนไซต์Unix & Linux : ใช้scriptคำสั่ง มันเก่าและมีแนวโน้มที่จะติดตั้งแล้ว

$ script -q /dev/null long_running_command | print_progress       # FreeBSD, Mac OS X
$ script -q -c "long_running_command" /dev/null | print_progress  # Linux

โปรดทราบว่าพารามิเตอร์ชื่อไฟล์ครั้งแรกสำหรับscriptคำสั่งล็อกไฟล์ที่จะเขียน หากคุณเพียงแค่เรียกใช้script -q your_commandคุณจะเขียนทับคำสั่งที่คุณเยื้องเพื่อเรียกใช้กับไฟล์บันทึก ตรวจสอบman scriptเพื่อความปลอดภัยก่อนที่จะลอง


4

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


ฉันรู้เคล็ดลับ 'script -a out.txt' ฉันสงสัยว่ามีวิธีอื่นใดที่จะทำให้กระบวนการเขียนไม่ใช่บัฟเฟอร์
James Dean

3

teeส่วนตัวผมชอบการส่งออกท่อของคำสั่งฉันต้องการที่จะตรวจสอบผ่าน

scriptบันทึกข้อมูลมากเกินไปรวมถึงเวลาของการกดปุ่มและตัวอักษรที่พิมพ์ไม่ได้จำนวนมาก สิ่งที่teeช่วยประหยัดนั้นเป็นสิ่งที่มนุษย์อ่านได้มากขึ้นสำหรับฉัน


ฉันจะเพิ่ม "| น้อย" ลงในบรรทัดคำสั่ง
HUB

4
ฉันค่อนข้างแน่ใจว่าteeได้รับผลกระทบจากการบัฟเฟอร์ด้วย ฉันยังคงได้รับบางส่วนแสดงบรรทัดโดยทีเมื่อแยกออกจากfindคำสั่ง
Magellan

2

เปลี่ยนทิศทางเอาต์พุตเป็นไฟล์และติดตามไฟล์ด้วยtail -fคำสั่ง

แก้ไข

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


3
นี่คือสิ่งที่ฉันทำตอนนี้ แต่กระบวนการบัฟเฟอร์การเขียนไปยังไฟล์และนั่นคือสิ่งที่ฉันต้องการหลีกเลี่ยง
James Dean

ดูการแก้ไขข้อเสนอที่อัปเดตของฉัน
wolfgangsz

1
สิ่งนี้ไม่ทำงานด้วยเหตุผลที่ชัดเจน ใครเป็นคนให้This answer is usefulคำตอบที่ไม่ได้ผลและใช้ไม่ได้
cnst

1

คุณสามารถใช้teeคำสั่งเพียงมายากล!

someCommand | tee logFile.logทั้งสองจะแสดงในคอนโซลและเขียนลงในล็อกไฟล์


ใช้งานไม่ได้ teeจะไม่หยุดการบัฟเฟอร์ใด ๆ
cnst

1
@cnst อย่างมีประสิทธิภาพteeจะไม่หลีกเลี่ยงการบัฟเฟอร์ แต่จะช่วยให้คุณได้ดูสิ่งที่ส่งออก นี่คือสิ่งที่ @JamesDean ต้องการ (เนื่องจากฉันยกเลิกการตั้งคำถามของเขา) แต่ฉันคิดว่าการบัฟเฟอร์ไม่ใช่ปัญหาที่นี่จริงๆ หากคุณมีรายละเอียดเพิ่มเติมแจ้งให้เราทราบ
เบญจ

เขาต้องการที่จะเห็นผลลัพธ์และเขาไม่ได้รับผลลัพธ์ใด ๆ (ในลักษณะที่ไม่มีข้อผูกมัด) และคุณยังแนะนำให้ใช้teeเพื่อให้ได้มุมมองที่ดีขึ้นของผลลัพธ์ที่ไม่ได้รับ
cnst

1
ฉันแดง @JamesDean คำถาม: "ฉันเปลี่ยนเส้นทางไปยังไฟล์ '> out.txt'" หมายถึงฉันไม่มีคอนโซลเอาต์พุตรอกระบวนการให้เสร็จสมบูรณ์ในขณะที่เอาท์พุททั้งหมดถูกเปลี่ยนเส้นทาง เมื่อคุณใช้งาน>คุณจะไม่เห็นอะไรเลยบนคอนโซล ฉันเดา @JamesDean ใช้คำว่า "การบัฟเฟอร์" เพื่ออธิบายสิ่งนั้น ฉันจะแสดงความคิดเห็นเกี่ยวกับคำถามของเขาเพื่อให้เขาพูดเพิ่มเติมเกี่ยวกับสิ่งที่เขาต้องการ
Benj
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.