การพิมพ์คำสั่งอื่นไปยัง STDIN ปลอดภัยหรือไม่ในขณะที่คำสั่งก่อนหน้านี้กำลังเขียนไปยัง STDOUT


21

บางทีนี่อาจเป็นคำตอบก่อนหน้านี้ฉันยินดีต้อนรับลิงก์ไปยังคำตอบอื่น ...

ถ้าฉันรันคำสั่งเชลล์ (ในbashเชลล์) เช่นต่อไปนี้:

make

จากนั้นในขณะที่ผลผลิตจากการmakeถูกเลื่อนโดยจากSTDOUTของmakeคำสั่งถ้าผมพิมพ์make checkและกดenterก่อนที่คำสั่งแรกเสร็จสิ้นการดำเนินการเมื่อmakeคำสั่งในที่สุดก็เสร็จสิ้นคำสั่งต่อไปmake checkจะรับสิทธิและเรียกใช้

คำถามของฉันเป็นเพียง:

  1. สิ่งนี้เป็นอันตรายหรือไม่?
  2. มีพฤติกรรมที่คาดไม่ถึงใด ๆ จากการพิมพ์ที่รวดเร็วเช่นนี้หรือไม่?
  3. ทำไมสิ่งนี้ถึงได้ผลเช่นนี้?

2
1. ฉันหวังว่าจะไม่ใช่ ... ฉันทำสิ่งนี้มาหลายปีแล้ว!
John WH Smith

คำตอบ:


20

มันทำงานได้อย่างที่มันเป็นเพราะ Unix เป็นฟูลดูเพล็กซ์ ดังที่ Ritchie กล่าวไว้ในระบบแบ่งปันเวลา UNIX: A Retrospective :

สิ่งหนึ่งที่ดูเหมือนเล็กน้อย แต่สร้างความแตกต่างที่น่าประหลาดใจเมื่อใช้อย่างใดอย่างหนึ่งคือหน้าจอ I / O แบบ full-duplex พร้อมกับอ่านล่วงหน้า แม้ว่าโดยทั่วไปแล้วโปรแกรมจะสื่อสารกับผู้ใช้ในรูปแบบของเส้นมากกว่าตัวอักษรเดียวเทอร์มินัลแบบเต็มดูเพล็กซ์ I / O หมายความว่าผู้ใช้สามารถพิมพ์ได้ตลอดเวลาแม้ว่าระบบจะพิมพ์กลับโดยไม่ต้องกลัวว่าจะสูญเสียอักขระ . ด้วยการอ่านล่วงหน้าเราไม่จำเป็นต้องรอการตอบกลับทุกบรรทัด ผู้พิมพ์ดีดที่ดีที่ป้อนเอกสารจะรู้สึกหงุดหงิดอย่างไม่น่าเชื่อที่ต้องหยุดก่อนที่จะเริ่มแต่ละบรรทัดใหม่ สำหรับทุกคนที่รู้ว่าสิ่งที่เขาต้องการที่จะพูดช้าใด ๆ ในการตอบสนองจะกลายเป็นขยายทางจิตวิทยาถ้าข้อมูลจะต้องป้อนแบบทีละบิตแทนที่จะเป็นความเร็วเต็ม

[อ้างจบ]

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

ssh remotehost do something that takes 20 seconds
mail bob
Dan has retired. Feel free to save any important files and then do
# ssh exits here, discarding the previous 2 lines
rm -fr *
.

ดังนั้นหลังจากคำสั่งbash fork()s และexecs คำสั่งแรกยังคงติดอยู่กับSTDINเปลือก bash หรือไม่? ดูเหมือนว่าคำตอบคือไม่ทุบตีดูเหมือนจะบัฟเฟอร์สำหรับคำสั่งต่อไป ถูกต้องหรือไม่
111 ---

ยกเว้นว่าคุณบอกให้เชลล์เปลี่ยนเส้นทาง stdin ของคำสั่งคำสั่งจะมี stdin เหมือนกับเชลล์ ทุกสิ่งที่คุณพิมพ์จะถูกอ่านโดยกระบวนการแรกที่อ่าน เชลล์ตั้งใจไม่พยายามอ่านสิ่งใดขณะที่คำสั่งกำลังทำงานและรอจนกว่าคำสั่งจะหยุด &สิ่งที่ได้รับความซับซ้อนมากขึ้นถ้าคุณใส่คำสั่งในพื้นหลังที่มี
Mark Plotnick

ดังนั้นSTDINการจัดการในลักษณะ Fifo? และฉันคิดว่าถ้ากระบวนการลูกของทุบตีปิดการจัดการไฟล์ที่สืบทอดมาอย่างชัดเจนเพื่อให้STDINมันยังคงสามารถอ่านได้จากการพิมพ์เพิ่มเติม?
111 ---

ใช่อินพุตเทอร์มินัลทั้งหมดได้รับการจัดการ FIFO ไม่แน่ใจว่าฉันเข้าใจคำถามที่สองของคุณ กระบวนการลูก - คำสั่งที่เชลล์เรียกใช้ - โดยปกติจะไม่ปิด stdin อย่างชัดเจน เชลล์ดำเนินไปจนสุดทางและอนุญาตให้คำสั่งอ่านทั้งหมดตามที่ต้องการจากนั้นชายด์จะหยุดทำงานและเชลล์จะกลับมาอ่านต่อ
Mark Plotnick

ใช่คุณตอบคำถามติดตามทั้งสองของฉันอย่างชัดเจนขอบคุณ!
111 ---

12

พฤติกรรมพื้นฐานที่คุณเห็นกำลังป้อนข้อมูลที่ตั้งอยู่ในที่ใดที่หนึ่งบัฟเฟอร์จนกว่าจะมีการอ่าน (ดีถ้าคุณพิมพ์พอในที่สุดบัฟเฟอร์จะเติมขึ้นและบางสิ่งบางอย่างจะหายไปที่ต้องการเป็นจำนวนมากของการพิมพ์แม้ว่า) สิ่งที่ดำเนินการโดย make ส่วนใหญ่จะไม่อ่านจาก STDIN ดังนั้นจึงอยู่ในบัฟเฟอร์

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

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

make && make checkตัวเลือกที่ดีน่าจะเป็นที่ทำงาน:


8
  1. คุณไม่ควรเรียกใช้คำสั่งที่สองซึ่งขึ้นอยู่กับคำสั่งแรก ( makeในตัวอย่างของคุณ) หลังจากเสร็จสมบูรณ์ ตัวอย่างเช่นmake foo Enter> ./foo Enter อาจทำให้เกิดปัญหา คุณอาจต้องการลองเป็นนิสัยในการพิมพ์สิ่งต่าง ๆ เช่นmake && make checkที่ซึ่งคำสั่งที่สองจะถูกดำเนินการเฉพาะถ้าคนแรกประสบความสำเร็จ
  2. เป็นไปได้ในทางทฤษฎีว่าคำสั่งแรก (กระบวนการ (es)) สามารถอ่านส่วนหนึ่งของคำสั่งที่สองหรือลบออกจากบัฟเฟอร์อินพุตเทอร์มินัล ถ้ามันกินหกตัวอักษรแรกของmake checkคุณจะสิ้นสุดการดำเนินการคำสั่งheckซึ่งอาจไม่มีอยู่ในระบบของคุณ (แต่อาจเป็นสิ่งที่น่ารังเกียจ) หากคำสั่งแรกเป็นสิ่งที่ไม่เป็นพิษเป็นภัยที่คุณรู้จักและเชื่อถือฉันจะไม่เห็นปัญหาทันที
  3. มันทำงานอย่างไร / ทำไม? ระบบบัฟเฟอร์คีย์บอร์ดอินพุต มันคล้ายกับอีเมล: คุณสามารถส่งข้อความถึงห้าคนในช่วงเวลาสั้น ๆ และพวกเขาจะนั่งอยู่ในกล่องจดหมายเข้าของเขารอให้เขาอ่าน ในทำนองเดียวกันตราบใดที่คำสั่งแรกไม่ได้อ่านจากแป้นพิมพ์คำสั่งที่คุณพิมพ์จะนั่งลงและรอให้เชลล์ทำการอ่าน มีการ จำกัด ว่า“ การพิมพ์ล่วงหน้า” เท่าไรที่สามารถบัฟเฟอร์ได้ แต่โดยทั่วไปจะมีอักขระหลายร้อยตัว (หากไม่ใช่หลายพัน)

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