ใน zsh ความแตกต่างระหว่าง cat <(cat) กับ cat | cat vs cat = (cat)?


18

ฉันคาดหวังcat <(cat)และcat | catทำสิ่งเดียวกัน: คัดลอกบรรทัดจาก stdin ไปยัง stdout ความเข้าใจของฉันคือการที่ทั้งสองจะดำเนินการcatใน subshell การเปลี่ยนเส้นทาง subshell cat's stdout เพื่อไปป์ที่มีชื่อชั่วคราวและจากนั้นดำเนินการอื่นcatในเปลือกปัจจุบันกับ stdin มันเปลี่ยนเส้นทางไปยังท่อ

แต่cat <(cat)ช่วยให้ฉันพิมพ์ที่ terminal ของฉัน แต่ไม่มีเส้นที่นำเข้าได้รับการคัดลอกและ^Dล้มเหลวในการส่งสัญญาณEOF; cat | catทำงานได้ตามที่คาดหวัง

จากการทดสอบเพิ่มเติมฉันได้ตรวจสอบว่าcat =(cat)มีปัญหาคล้ายกันcat <(cat)แต่ใช้งานได้ตามที่คาดไว้: stdin ทั้งหมดไปจนถึงการ^Dคัดลอกไปยัง stdout ในครั้งเดียว

ใครสามารถช่วยฉันเข้าใจสิ่งที่ zsh กำลังทำอยู่ภายใต้ประทุน?

คำตอบ:


23
  1. a | bเชื่อมต่อSTDOUTจากaและSTDINจากโดยใช้เพียงแค่b dup/dup2คำสั่งทั้งสองจะถูกดำเนินการในแบบคู่ขนาน

  2. a =(b)แทนที่อาร์กิวเมนต์aด้วยชื่อไฟล์ชั่วคราว bจะถูกเรียกใช้งานก่อนaเนื่องจากจะต้องสร้างไฟล์ชั่วคราวก่อนจึงจะสามารถส่งผ่านได้a

  3. a <(b)แทนที่อาร์กิวเมนต์aด้วยไพพ์ที่มีชื่อ aและbทำงานแบบขนาน นี่คือตอนที่มันซับซ้อนเล็กน้อย:

    bอยู่ในพื้นหลังและไม่สามารถอ่านได้จากเครื่อง คุณสามารถทดสอบด้วยตัวเองโดยใช้strace -p $PIDเพื่อแนบกับกระบวนการ cat ที่สองของคุณเพื่อดูกระบวนการ

    aในระหว่างนี้พยายามอ่านจากไพพ์ที่มีชื่อ แต่ไม่สามารถอ่านอะไรได้อย่างที่bไม่สามารถอ่านได้

    •โดยทั่วไปหมายความว่าคุณมีการหยุดชะงักโดยaพยายามอ่านbแต่bไม่สามารถอ่านSTDINและเขียนไม่ได้a

ข้อมูลเพิ่มเติมเกี่ยวกับกระบวนการพื้นหลังและเทอร์มินัลจากการทุบตีคน :

เพื่ออำนวยความสะดวกการดำเนินงานของส่วนติดต่อผู้ใช้ในการควบคุมงานระบบปฏิบัติการรักษาความคิดของการเป็นกระบวนการกลุ่มขั้ว ID สมาชิกของกลุ่มกระบวนการนี้ (กระบวนการที่มีกลุ่มกระบวนการ ID เท่ากับกระบวนการขั้ว ID กลุ่มในปัจจุบัน) ได้รับสัญญาณแป้นพิมพ์ที่สร้างขึ้นเช่น SIGINT กระบวนการเหล่านี้จะกล่าวว่าเป็นในเบื้องหน้า พื้นหลังกระบวนการคือผู้ที่มี ID กลุ่มกระบวนการแตกต่างจากเทอร์มินัล กระบวนการดังกล่าวมีภูมิคุ้มกันต่อสัญญาณที่สร้างจากคีย์บอร์ด กระบวนการพื้นหน้าเท่านั้นที่ได้รับอนุญาตให้อ่านจากหรือถ้าผู้ใช้ระบุด้วย stty tostop ให้เขียนไปที่เทอร์มินัล กระบวนการเบื้องหลังที่พยายามอ่าน (เขียนถึงเมื่อ stty tostop มีผล) เทอร์มินัลจะส่งสัญญาณSIGTTIN (SIGTTOU)โดยไดรเวอร์เทอร์มินัลของเคอร์เนล


เยี่ยมมากขอบคุณ - มันล้างออกเยอะมาก!
Alan O'Donnell

1
หมายเหตุเมื่อไม่โต้ตอบ, zsh เปลี่ยนเส้นทางอินพุตมาตรฐานของคำสั่งพื้นหลัง (รวมถึงคำสั่งใน<(cmd)) ไป/dev/nullดังนั้นพฤติกรรมที่แตกต่าง ( zsh -c 'cat <(cat)'กลับทันทีและไม่ส่งออกอะไร)
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.