กระบวนการอินพุตท่อพื้นหลัง


14

ถ้าฉันต้องการแสดง "aaa" บนหน้าจอ:

(1)$: echo aaa | cat                 ... works OK
(2)$: echo aaa | ( cat )             ... works OK
(3)$: echo aaa | ( cat & )           ... NOT working
(4)$: ( echo aaa & ) | cat           ... works OK 
(5)$: echo aaa | ( cat <&0 & )       ... works ok in BASH (but not in SH)
(6)$: echo aaa | ( cat <&3 & ) 3<&0  ... works ok in BASH and SH

การรวมจาก (3) และ (4) -> กระบวนการที่แยกออกยังคงมีเอาต์พุตเชื่อมต่อที่สามารถควบคุมใช้เปลี่ยนเส้นทาง ... แต่ไม่ใช่อินพุต!

คำถามของฉันคือ: มีคนเข้าใจว่าทำไมและวิธีการทำงานของบรรทัด (5) ???

... "<& 0" ย่อมาจาก "0 <& 0" สาเหตุที่การเปลี่ยนเส้นทาง 0 ถึง 0 เป็นวิธีแก้ปัญหาและสิ่งที่เกิดขึ้นจริงด้วยการป้อนข้อมูลของกระบวนการเดี่ยว Subshell ไม่ใช่ปัญหาโดยใช้เครื่องหมายปีกกา {... } แทน (... ) ให้ผลลัพธ์เหมือนกัน

... และคำถาม 2: มีวิธีแก้ปัญหาที่ดีกว่าสำหรับ "การให้อินพุตกับกระบวนการที่แยกออก" กว่าบรรทัด (6)

คำตอบ:


12

ใช่ตามที่ POSIXคำสั่งเริ่มต้นในพื้นหลังได้เข้ามาตรฐานของพวกเขาเปลี่ยนเส้นทางจาก&/dev/null

และแน่นอน

{ cmd <&3 3<&- & } 3<&0

เป็นวิธีที่ชัดเจนที่สุดในการแก้ไข

ยังไม่ชัดเจนว่าทำไมคุณจึงต้องการเรียกใช้ส่วนหนึ่งของการวางท่อในพื้นหลัง


เหตุผลก็คือการได้รับ PID ของคำสั่งเฉพาะหนึ่งในห่วงโซ่ท่อ (cmd1 | {cmd2 &; pid2 = $ !;} | cmd3 ... , ดังนั้น / dev / null == & 0 เป็นมาตรฐานสำหรับ BG proces คุณรู้หรือไม่ว่าทำไม "0 <& 0" ทำงานได้ดีในทุบตี ... และปลอดภัยไหม?
Asain Kujovic

3
@OmerMerdan POSIX กล่าวว่าในทุกกรณีการเปลี่ยนเส้นทางที่ชัดเจนของอินพุตมาตรฐานจะแทนที่กิจกรรมนี้ซึ่งขัดแย้งกับสิ่งที่กล่าวไว้ข้างต้นดังนั้นฉันจึงเชื่อว่าbashตีความ (และฟังดูเหมือนเป็นการตีความที่สมเหตุสมผล) เป็นการยกเลิกการ/dev/nullเปลี่ยนเส้นทาง ตอนนี้กระสุนไม่มากที่ทำเช่นเดียวกัน Ash และ pdksh ทำไม่ได้
Stéphane Chazelas

ทำไมต้องใช้ชิ้น3<&-ส่วนและปลอดภัยที่จะใช้ (จะไม่ปิดท่อก่อนที่จะอ่านอินพุตแบบเต็ม) หรือไม่?
mvorisek

1
@Morork นั้น fd 3 จะใช้ชั่วคราวเพื่อเรียกคืน stdin ดั้งเดิมเท่านั้น เราปิดมันโดยcmdไม่ต้องการมัน เราปิดมันหลังจากที่เราได้วางมันลงบน fd 0 ( <&3ย่อมาจาก0<&3)
Stéphane Chazelas

1
@Mvorisek, nohupนอกจากนี้ยังมีการเปลี่ยนเส้นทาง stdin / dev / null { nohup sh -c 'cmd <&3 3<&-' & } 3<&0ดังนั้นคุณจะต้อง: หรือ(trap '' HUP; cmd <&3 3<&- > nohup.out 2>&1 &) 3<&0
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.