ป้องกัน EOF อัตโนมัติไปที่ไปป์ที่มีชื่อและส่ง EOF เมื่อฉันต้องการ


12

ฉันมีโปรแกรมที่ออกโดยอัตโนมัติเมื่ออ่าน EOF ในสตรีมที่กำหนด (ในกรณีต่อไปนี้ stdin)
ตอนนี้ฉันต้องการสร้างเชลล์สคริปต์ซึ่งสร้างไพพ์ที่มีชื่อและเชื่อมต่อ stdin ของโปรแกรม จากนั้นสคริปต์จะเขียนไปยังไพพ์หลายครั้งโดยใช้echoและcat(และเครื่องมืออื่น ๆ ที่สร้าง EOF โดยอัตโนมัติเมื่อพวกเขาออก) ปัญหาที่ฉันเผชิญคือเมื่อสิ่งแรกechoเสร็จแล้วมันจะส่ง EOF ไปที่ไพพ์และทำให้โปรแกรมออกจาก ถ้าฉันใช้บางอย่างเช่นtail -fนั้นฉันจะไม่สามารถส่ง EOF เมื่อฉันตั้งใจจะออกจากโปรแกรม ฉันกำลังค้นคว้าวิธีแก้ปัญหาที่สมดุล แต่ก็ไม่มีประโยชน์
ฉันพบวิธีป้องกัน EOF และวิธีส่ง EOF ด้วยตนเองแล้ว แต่ไม่สามารถรวมเข้าด้วยกันได้ มีคำใบ้อะไรบ้าง?

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg

คำตอบ:


13

ตามที่คนอื่นได้ระบุไว้ผู้อ่านของไปป์จะได้รับ EOF เมื่อไม่มีผู้เขียนเหลืออยู่ ดังนั้นวิธีแก้ไขคือทำให้แน่ใจว่ามีนักเขียนหนึ่งคนเปิดค้างอยู่เสมอ ผู้เขียนคนนั้นไม่ต้องส่งอะไรเลยเพียงแค่เปิดค้างไว้

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

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

โปรดทราบว่าหากคุณเว้นบรรทัดสุดท้ายตัวอธิบายไฟล์ 3 จะถูกปิดโดยอัตโนมัติ (และผู้อ่านจะได้รับ EOF) เมื่อสคริปต์ออก นอกเหนือจากความสะดวกสบายแล้วสิ่งนี้ยังให้ความปลอดภัยในการเรียงลำดับหากสคริปต์สิ้นสุดลงก่อนกำหนด


2
exec 3>Pสาเหตุนี้แขวนอยู่ในทุบตีทำไม?
วัง

@ วังมันไม่ควร ถ้าเป็นเช่นนั้นคุณอาจไม่ได้ทำสิ่งเดียวกันกับรหัส POC ในคำถาม เหตุผลเดียวที่ฉันสามารถคิดได้ว่ามันจะปิดกั้นคือถ้าคุณกำลังทำสิ่งที่ต้องการแทนexec 2>Pและคุณได้เปิดใช้โหมดการติดตาม ( set -x) ซึ่งทุบตีจะเขียนลงในไปป์ แต่ไม่มีผู้อ่านจึงบล็อกรอ สิ่งที่อ่าน
Patrick

1
@Wang @Patrick exec 3>Pแขวนในเครื่องของฉันด้วยเช่นกัน Pนี้เป็นเพราะไม่มีการดำเนินการจากการอ่าน ดังนั้นการแก้ปัญหาคือการสลับบรรทัดexec 3>Pและprogram < P &(เพิ่มเครื่องหมายและเพื่อให้โปรแกรมทำงานในพื้นหลัง)
macieksk

2

ไปป์รับ EOF เมื่อตัวเขียนล่าสุดหายไป เพื่อหลีกเลี่ยงปัญหานี้ตรวจสอบให้แน่ใจว่ามีนักเขียนอยู่เสมอ (กระบวนการที่เปิดไพพ์เพื่อการเขียน แต่ไม่ได้เขียนอะไรจริง ๆ ) ในการส่ง EOF ให้ผู้เขียนสำรองนั้นหายไป

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}

0

ไม่มีทางที่โปรแกรมจะแยกความแตกต่างระหว่าง EOF ซึ่งหมายความว่า "ถึงเวลาที่จะเลิก" และ EOF ที่หมายถึง "นักเขียนเสร็จแล้ว แต่อาจมีการป้อนข้อมูลเพิ่มเติมจากคนอื่น"

หากคุณมีความสามารถในการปรับเปลี่ยนพฤติกรรมของโปรแกรมของคุณให้ทำการอ่านในวงวนไม่สิ้นสุด (หนึ่งรอบจะคงอยู่จนกระทั่ง EOF) และส่งสตริงคำสั่งเฉพาะที่หมายถึง "เวลาเลิก" การส่งสตริงนั้นจะเป็นงานของsend_eofคำสั่งในคำถามของคุณ

ตัวเลือกอื่น:

( echo some stuff; cat more_stuff.txt ) >P

หรือ

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