ไปป์ที่ไม่มีบัฟเฟอร์ที่บล็อกชื่อ?


20

ฉันกำลังมองหาสิ่งที่ฉันสงสัยว่าไม่มีอยู่: ไปป์บัฟเฟอร์ที่ไม่มีชื่อ (Fifo) ที่ไม่มีการบล็อกเพื่อใช้งานจากบรรทัดคำสั่ง มีอะไรแบบนี้เหรอ?

นี่คือกรณีการใช้งาน: stdoutสมมติว่าฉันมีกระบวนการที่จะไปทำงานเป็นเวลานานในพื้นหลังและคายจำนวนมากของการส่งออกไปยัง ฉันไม่สนใจจริง ๆ เกี่ยวกับผลลัพธ์และไม่ต้องการเก็บไว้ (บางทีฉันไม่มีพื้นที่เพียงพอที่จะ) แต่ฉันต้องการ "ปล่อย" เป็นระยะ ๆ และทำตามสิ่งที่มันทำแล้วเลื่อนออกอีกครั้ง และปล่อยให้มันทำงาน ดังนั้นฉันต้องการที่จะเปลี่ยนเส้นทางการส่งออกไปยังบัฟเฟอร์ที่มีชื่อตามทฤษฎีซึ่งไม่มีการปิดกั้นจากนั้นแตะเป็นระยะ ๆ

โดยพื้นฐานแล้วฉันต้องการเริ่มต้นเช่นนี้ ( 10Mเป็นขนาดของบัฟเฟอร์):

mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &

... และแวะเข้าไปเป็นระยะเพื่อดูว่าเกิดอะไรขึ้น ...

tail -f magicfifo

... โดยไม่ต้อง magicfifoเก็บเอาท์พุททั้งหมด (ดังนั้นไม่ใช่ไฟล์ปกติ) และไม่มีการปิดกั้นกระบวนการที่ทำให้เกิดการระเบิดเมื่อมันเต็มและไม่ได้ถูกทาบทาม (ดังนั้นไม่ใช่ไปป์ปกติที่มีชื่อ)

ฉันไม่คิดว่าวิธีแก้ปัญหาที่เกี่ยวข้องtailหรือpruneจะทำ (ดีฉันสามารถคิดถึงวิธีแก้ปัญหาที่เกี่ยวข้องtail) เพราะtailจะยังคงต้องการให้ฉันเก็บข้อมูลทั้งหมดที่ไหนสักแห่ง (ถ้าฉันต้องการที่จะลดลงและออกจากการดู) และpruneจะต้องเขียนไฟล์ใหม่อีกครั้งสันนิษฐาน (ฉันจะยอมรับว่าฉันไม่ได้ลอง / พิสูจน์ได้) ทำลายการเปลี่ยนเส้นทางของกระบวนการที่สร้างผลลัพธ์ทั้งหมด

ฉันคาดหวังว่าฉันสามารถเขียนยูทิลิตี้เพื่อทำสิ่งนี้ได้ แต่ * ระวังมีแง่มุมที่ยอดเยี่ยมมากมายของไฟล์และไพพ์และเช่นนั้นฉันอดไม่ได้ที่จะคิดว่ามันมีอยู่และฉันไม่รู้เกี่ยวกับมัน

ดังนั้น: มีสิ่งนั้นหรือไม่และถ้าเป็นเช่นนั้น


1
สิ่งที่คุณกำลังอธิบายคือ "บัฟเฟอร์วงแหวน" หรือ "บัฟเฟอร์วงกลม" ฉันไม่ได้ตระหนักถึงเครื่องมือบรรทัดคำสั่งใด ๆ สำหรับการบำรุงรักษาสิ่งนั้นแม้ว่ามันจะเป็นเรื่องเล็กน้อยที่จะสร้าง
Shawn J. Goff

2
ดูที่โซลูชันที่อธิบายไว้ใน "Linux non-blocking Fifo (ตามการบันทึกความต้องการ)", stackoverflow.com/questions/7360473/… .

1
ดูเหมือนว่าสิ่งนี้ได้รับการแก้ไขแล้วใน StackOverflow: stackoverflow.com/questions/7360473/…
James Blackburn

@ JamesBlackburn: ขอบคุณ! น่าสนใจมาก.
TJ Crowder

คำตอบ:


16

ผมคิดว่าสิ่งที่คุณกำลังมองหา screenGNU มันคงบัฟเฟอร์ที่จะเก็บหน้าจอสุดท้ายเต็มหรือสองออกจากหนึ่งหรือมากกว่าหนึ่งโปรแกรมและช่วยให้คุณยกเลิกการเชื่อมต่อและกลับมาในภายหลัง


+1 สำหรับหน้าจอการแนะนำ BTW คุณสามารถกำหนดค่าเพื่อเก็บ "สายประวัติ" จำนวนมาก
Mr Shunz

1
ขอบคุณ คุณสามารถยกตัวอย่างว่าคุณจะใช้สิ่งนั้นกับคำสั่งที่ฉันแสดงในคำถามของฉันได้อย่างไร หน้าคนบอกว่ามันเป็นตัวจัดการหน้าต่าง (ฉันคิดว่าพวกเขาหมายถึงในแง่ขั้วไม่ใช่ความรู้สึกแบบกราฟิก แต่ยังคง) และฉันจะยังสามารถดรอป (ผ่าน ssh) และเลื่อนออกได้ตามความจำเป็น? (เช่น ops บนเซิร์ฟเวอร์ระยะไกล)
TJ Crowder

ใช่คุณสามารถใช้หน้าจอ GNU ด้วยวิธีนี้ คุณจะสร้างเซสชันใหม่ (อาจตั้งชื่อ) เรียกใช้คำสั่งของคุณภายในเซสชันนั้นแล้วตัดการเชื่อมต่อ
TML

2
นอกจากนี้ยังมีtmuxและdtach- สิ่งใดในแอปพลิเคชันตัวจัดการมัลติเพล็กซ์ / เทอร์มินัลคลาสเดียวกันควรจะสามารถบรรลุสิ่งเดียวกัน
jw013

5

คุณสามารถใช้pvมันให้บัฟเฟอร์มากเท่าที่คุณต้องการในไปป์ไลน์ คุณสามารถใช้สิ่งนี้:

sprewingprocess | pv -B 1g > ordinaryfifo &

นั่นจะทำให้คุณมีบัฟเฟอร์มากถึง 1GB ระหว่างspewingprocessและ Fifo ลินุกซ์ส่วนใหญ่มีในแพคเกจที่เรียกว่าเชื่อหรือไม่pvpv


ขอบคุณ แต่จะไม่บล็อกนั้นเมื่อบัฟเฟอร์เต็มถ้าฉันไม่ได้อ่านไปป์ที่มีชื่อเป้าหมาย?
TJ Crowder

1
ใช่ แต่คุณมีทางเลือกอะไรบ้าง? ในจักรวาลอัน จำกัด คุณไม่สามารถกำหนดบัฟเฟอร์ได้ไม่ จำกัด
David Schwartz

ตัวเลือกอื่นคือตามที่ฉันอธิบายไว้ในคำถามของฉัน: ไม่เก็บผลลัพธ์ทั้งหมด เมื่อบัฟเฟอร์เต็มสิ่งที่เก่าที่สุดจะถูกโยนทิ้งไป
TJ Crowder

อืมฉันทดสอบสิ่งนี้แล้วและมันก็ไม่ได้ผล หากกระบวนการอ่านฟีฟ่าหยุดอ่านครู่หนึ่ง pv บล็อกพยายามเขียนไปยังฟีเจอร์และเนื่องจากไม่ใช่มัลติเธรดจึงบล็อกการอ่านข้อมูลลงในบัฟเฟอร์ของ pv ดังนั้นบัฟเฟอร์ของ pv จะยังคงเติมต่อไปในขณะที่กระบวนการอ่านฟีฟ่าอ่านต่อไป pv อาจสามารถอ่านและบัฟเฟอร์ข้อมูลบางอย่างได้ แต่ไม่ได้ป้องกันตัวเขียนจากการบล็อกทั้งหมด
Daniel S. Sterling

1

ผมมีปัญหาเดียวกัน. นี่เป็นทางออกแรกของฉัน ก่อนอื่นให้เขียนเอาต์พุตไปยังไฟล์ที่เราตัดทอนหลังจากแต่ละบรรทัดดังนั้นมันจะไม่ขยายไปเรื่อย ๆ :

spewingprocess | while read line; do echo $line > buffer.txt ; done

จากนั้นอ่านจากไฟล์โดยใช้ tail (โดยที่2> /dev/nullได้รับข้อความแสดงข้อผิดพลาด "file truncated"):

tail -f ./buffer.txt 2> /dev/null

วิธีนี้บัฟเฟอร์ไม่เติบโตและเราสามารถมัลติเพล็กซ์ได้เช่นรันก้อยได้มากเท่าที่เราต้องการ อย่างไรก็ตามปัญหาของวิธีนี้คือเราสามารถสูญเสียข้อมูลเมื่อเราตัดส่วนที่เร็วกว่าส่วนท้ายสามารถอ่านได้จากการทดสอบนี้:

for ((i=0; ; i++)) ; do echo "$i" ; done | while read line; do  echo $line > buffer.txt ; done
tail -f ./buffer.txt 2> /dev/null > log.txt

หลังจากทำงานไประยะหนึ่งบรรทัดแรกและบรรทัดสุดท้ายคือ:

$ head -n 1 log.txt
0
$ tail -n 1 log.txt
78783

แต่ไฟล์มีจำนวนบรรทัดน้อยกว่าดังนั้นบางส่วนจึงสูญหาย:

$ wc log.txt
67087  67087 392819 log.txt

นี่เป็นวิธีแก้ปัญหาที่ดีหากคุณไม่สนใจเรื่องการสูญหายของข้อมูลมากนักหรือเมื่อกระบวนการ spewing ของคุณไม่เร็วพอสำหรับการสูญหายของข้อมูล

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