`น้อยกว่า 'ใช้ข้อมูลจาก stdin ในขณะที่ยังสามารถอ่านคำสั่งจากผู้ใช้ได้อย่างไร


47

ตามที่คุณส่วนใหญ่ทำมาแล้วหลายครั้งการดูตัวอักษรแบบยาวทำได้โดยสะดวกless:

some_command | less

ตอนนี้ stdin เชื่อมต่อกับไพพ์ (FIFO) แล้ว มันยังสามารถอ่านคำสั่งเช่นขึ้น / ลง / ออกได้อย่างไร?


15
lessอ่านข้อมูลที่จะแสดงจาก stdin และอ่านคำสั่งจาก tty พวกมันต่างกัน
วิลเลียม Pursell

2
@WilliamPursell ใช่ฉันรู้ แต่มีอินพุตมาตรฐานเดียวเท่านั้นใช่ไหม
iBug

4
ใช่มีสตรีมอินพุตหนึ่งรายการและหนึ่งไฟล์ tty lessอ่านข้อมูลจาก stdin และคำสั่งจาก tty
วิลเลียม Pursell

คำตอบ:


52

ดังกล่าวโดยวิลเลียม Pursell , lessอ่านการกดแป้นพิมพ์ของผู้ใช้จากขั้ว มันเปิดขึ้นอย่างชัดเจน/dev/ttyสถานีควบคุม; ที่ให้คำอธิบายไฟล์แยกจากอินพุตมาตรฐานซึ่งสามารถอ่านอินพุตแบบโต้ตอบของผู้ใช้ได้ สามารถอ่านข้อมูลที่จะแสดงจากอินพุตมาตรฐานในเวลาเดียวกันหากจำเป็น (สามารถเขียนโดยตรงไปยังเทอร์มินัลหากจำเป็น)

คุณสามารถเห็นสิ่งนี้เกิดขึ้นได้จากการวิ่ง

some_command | strace -o less.trace -e open,read,write less

ย้ายไปรอบ ๆ อินพุตออกlessและดูเนื้อหาของless.trace: คุณจะเห็นมันเปิดอยู่/dev/ttyและอ่านจากทั้งตัวอธิบายไฟล์ 0 และสิ่งใดที่ถูกส่งคืนเมื่อมันเปิด/dev/tty(น่าจะเป็น 3)

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

ตามที่อธิบายโดยschilyหาก/dev/ttyไม่สามารถเปิดได้lessจะอ่านจากข้อผิดพลาดมาตรฐาน (ตัวอธิบายไฟล์ 2) lessมีการ/dev/ttyแนะนำการใช้งานในรุ่น 177 วางจำหน่ายเมื่อวันที่ 2 เมษายน 1991

ถ้าคุณพยายามที่ทำงานcat /dev/tty | lessเป็นปัญหาโดยHagen ฟอน Eitzen , lessจะประสบความสำเร็จในการเปิด/dev/ttyแต่จะไม่ได้รับข้อมูลใด ๆ จากมันจนกว่าcatจะปิดมัน ดังนั้นคุณจะเห็นหน้าจอว่างเปล่าและไม่มีอะไรอื่นจนกว่าคุณCtrlCจะกดเพื่อฆ่าcat(หรือฆ่าด้วยวิธีอื่น); จากนั้นlessจะแสดงสิ่งที่คุณพิมพ์ในขณะที่catทำงานและอนุญาตให้คุณควบคุม


4
@HagenvonEitzen คอมพิวเตอร์ของคุณจะระเบิด! มันเหมือนกับวิธีที่เคิร์กและสป็อคทำให้หุ่นยนต์ของ Mudd พัง
Barmar

7
@HagenvonEitzen ว้าว การใช้แมวเป็นสองเท่าอย่างไร้ประโยชน์ ฉันประทับใจ.
Andrew Henle

8
@ grawity ฉันคิดว่าประเด็นของ Andrew คือcat blah |สามารถถูกแทนที่ด้วย< blahและถึงแม้ว่ามันจะไม่จำเป็นในกรณีนี้เพราะมันใช้less blahงานได้ (เช่นกันless -f /dev/tty) แต่อ่านจาก/dev/ttyเป็นบิตของการเป็นกรณีพิเศษและทั้งสามสายพันธุ์ ( cat /dev/tty | less, less < /dev/ttyและless -f /dev/tty) ผลลัพธ์ที่แตกต่าง
สตีเฟ่น Kitt

1
/ dev / tty ชี้ไปยังสถานที่ที่เหมาะสมเสมอไหม? ฉันคิดว่าคุณจะต้องใช้ / dev / ptsX ปกติหรือไม่
StarWeaver

2
@StarWeaver ดูคำถามนี้เกี่ยวกับความแตกต่างระหว่างและ/dev/tty /dev/pts/...
สตีเฟ่น Kitt

26

UNIX มีสองวิธีในการอ่านอินพุตของผู้ใช้ในขณะที่ stdin ถูกเปลี่ยนเส้นทาง:

  • วิธีการเดิมคือการอ่านจากstderr Stderr เปิดให้บริการสำหรับการเขียนและการอ่านและยังคงกล่าวถึงใน POSIX

  • รุ่น UNIX ในภายหลังได้ (ประมาณปี 1979) เพิ่ม/dev/ttyอินเตอร์เฟสไดรเวอร์ที่อนุญาตให้เปิดการควบคุม tty ของกระบวนการ เนื่องจากมีกระบวนการที่ไม่มี tty ควบคุมจึงเป็นไปได้ที่ความพยายามในการเปิด/dev/ttyล้มเหลว ซอฟต์แวร์ที่เขียนเป็นมิตรจึงมีทางเลือกกลับไปที่วิธีดั้งเดิมแล้วพยายามอ่านจาก stderr


11
อ่านจาก stderr? เรียนรู้สิ่งใหม่ ๆ
iBug

1
ฉันดีใจที่มีคนจำวิธีเก่า ๆ ได้
Joshua

3
เป็นเหตุผลที่ใช้ stderr สำหรับการอ่านเพราะมีโอกาสน้อยที่สุดที่จะถูกเปลี่ยนเส้นทาง? ฉันไม่เห็นความแตกต่างอื่น ๆ ระหว่างมันและ stdout (หรือสำหรับ stater ที่สำคัญก่อนการเปลี่ยนเส้นทาง)
ctrl-alt-delor

4
ใช่มันเป็นเพราะนี่เป็นตัวบอกไฟล์ที่มีโอกาสน้อยที่สุดที่จะถูกเปลี่ยนเส้นทาง
Schily

@ ctrl-alt-delor: มันเป็น / เป็นเรื่องปกติสำหรับเชลล์ที่จะทำงานกับ stdin, stdout และ stderr ทั้งหมดเป็นdup()ลิขสิทธิ์ของคำอธิบายไฟล์เดียวกันแม้ว่าทั้งหมดจะเปิดบน tty (เห็นได้ชัด POSIX ยังคงต้องหรือแนะนำ (คำตอบนี้ไม่ได้พูด) ที่ stderr เป็นอ่าน / เขียน FD ไม่เปิดกับสิ่งที่ต้องการopen("/dev/ttyS0", O_WRONLY)อ่าน stderr จะล้มเหลวในกรณีที่..)
ปีเตอร์ Cordes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.