ฉันจะตรวจสอบว่าเชลล์ของฉันทำงานอยู่ในเทอร์มินัลได้อย่างไร


22

ฉันต้องการที่จะดำเนินการบางอย่างเฉพาะกรณีที่เปลือกของฉัน "เชื่อมต่อ" กับเทอร์มินัลคือเฉพาะเมื่ออินพุตมาตรฐานของฉันมาจากอินพุตของเทอร์มินัลและเอาต์พุตมาตรฐานของฉัน (และข้อผิดพลาดมาตรฐาน? อาคารผู้โดยสาร

ฉันจะทำสิ่งนั้นโดยไม่ต้องพึ่ง GNU / Linux specifics (เช่น/proc/self) โดยตรงได้อย่างไร


ที่คล้ายกัน: unix.stackexchange.com/q/22162/117549
Jeff Schaller

คำตอบ:


33

isattyเป็นฟังก์ชั่นสำหรับตรวจสอบสิ่งนี้และ-tแฟล็กของtestคำสั่งทำให้สามารถเข้าถึงได้จากเชลล์สคริปต์:

-t file_descriptor

จริงถ้าหมายเลขไฟล์ตัวอธิบายfile_descriptorเปิดอยู่และเชื่อมโยงกับเทอร์มินัล เท็จถ้าfile_descriptorไม่ใช่หมายเลขตัวอธิบายไฟล์ที่ถูกต้องหรือถ้าหมายเลขตัวอธิบายไฟล์file_descriptorไม่ได้เปิดอยู่หรือหากเปิดอยู่ แต่ไม่ได้เชื่อมโยงกับเทอร์มินัล

คุณสามารถตรวจสอบว่า FD 0 (อินพุตมาตรฐาน) เป็น TTY ด้วย:

test -t 0

คุณสามารถทำเช่นเดียวกันกับ FDs 1 และ 2 เพื่อตรวจสอบเอาต์พุตและสตรีมข้อผิดพลาดหรือทั้งหมด:

test -t 0 -a -t 1 -a -t 2

คำสั่งจะคืนค่า 0 (สำเร็จ) หาก descriptor ต่อกับเทอร์มินัลและเป็นเท็จมิฉะนั้น

testยังมีให้ใช้งานเป็น[คำสั่งสำหรับ "การทดสอบคร่อม"

 if [ -t 0 ] ; then ...

เป็นวิธีที่ใช้สำนวนในการเขียนเงื่อนไขนี้


8

ฉันคิดว่านี่เป็นสิ่งที่ซ้ำกัน แต่ฉันหามันไม่เจอ ใช้

[ -t 0 ]

และ

[ -t 1 ]

เพื่อทดสอบตามลำดับว่าอินพุตและเอาต์พุตมาตรฐานเชื่อมต่อกับเทอร์มินัลหรือไม่ man testมีรายละเอียด


7

เพียงแค่บันทึกเสริมด้านบนของคำตอบที่ดีที่ได้รับแล้ว โปรดทราบว่า[ -t 0 ]การทดสอบว่า file descriptor 0 เปิดไฟล์หนึ่งไฟล์ที่เป็นไฟล์อุปกรณ์ที่มีระเบียบวินัยของ tty line (โดยทั่วไปจะทำโดยตรวจสอบว่า termo ที่ไม่เป็นอันตราย ioctl () ประสบความสำเร็จ)

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

อุปกรณ์ tty และ pty ยังสามารถใช้สำหรับการถ่ายโอนข้อมูลหรือเป็นกลไกการสื่อสารระหว่างกระบวนการ

ตัวอย่างเช่นเราสามารถทำได้:

(stty raw -echo; myscript) < /dev/ttyS0

ฟีดสิ่งที่ได้รับมากกว่า RS232 myscriptไป

echo test | ssh -tt host myscript

จะมีmyscriptstdin เป็นอุปกรณ์ pty ( sshdที่ส่วนอื่น ๆ และในที่สุด (ข้ามการเชื่อมต่อ ssh) ไม่ใช่เทอร์มินัล แต่ไปป์ที่ป้อนโดยecho)

ในการตรวจสอบเพิ่มเติมว่ามีเทอร์มินัลที่ปลายอีกด้านหนึ่งของสาย RS232 หรือ pty คุณสามารถตรวจสอบว่า$TERMตัวแปรถูกตั้งค่าและไม่ว่างเปล่า ( [ -n "$TERM" ]) และส่งลำดับการหลีกเลี่ยงสถานะอุปกรณ์รายงานเหนือ fd นั้นและตรวจสอบว่าคุณได้รับ การตอบกลับ (นอกเหนือจาก[ -t 0 ]และ[ -n "$TERM" ])

printf >&0 '\e[5n'

ตอบกลับ\e[0nโดยเทอร์มินัลส่วนใหญ่

ขณะนี้มีปัญหาหลายอย่างกับที่ดังนั้นฉันจะไม่แนะนำให้ทำที่ยกเว้นในกรณีที่คุณต้องการตรวจสอบว่าเป็นเพราะคุณต้องการที่จะเรียกใช้โปรแกรมประยุกต์ตุ๋ยภาพ (ในกรณีที่คุณต้องการจะดีกว่าการใช้ห้องสมุดเช่นncurses, และแทนที่จะเป็น DSR คุณต้องการส่งลำดับการระบุอุปกรณ์เพื่อสอบถามประเภทเทอร์มินัลที่แม่นยำกว่าผ่าน$TERM):

  • โชคดีที่กรณีส่วนใหญ่ที่ stdin ไม่ใช่เทอร์มินัลจะเปิดในโหมดอ่านอย่างเดียวซึ่งจะทำให้เกิดความprintfล้มเหลว แต่ในกรณีที่ stdin เป็นอุปกรณ์ tty ที่เปิดในโหมดอ่าน + เขียนซึ่งจะมีผลข้างเคียง ของการส่งลำดับนั้นไปยังส่วนอื่น ๆ ตัวอย่างเช่นในตัวอย่าง ssh ของเราด้านบนซึ่งจะส่งลำดับไปยังเทอร์มินัล (แต่การตอบกลับจะไม่มาที่ stdin)
  • มันยากที่จะอ่านคำตอบที่เชื่อถือได้และพกพาได้ คุณต้องเปลี่ยนระเบียบวินัยของ tty line ชั่วคราวและอ่านทีละหนึ่งไบต์ คุณจะต้องตัดสินใจว่าจะหยุดพักชั่วคราวหากไม่เห็นการตอบกลับคุณยอมแพ้และตัดสินใจว่าไม่มีเทอร์มินัล หากคุณต้องการพิจารณาคนที่โทรเข้ามาผ่านการเชื่อมต่อดาวเทียมนั่นหมายถึงการหมดเวลานาน
  • การอ่านจากเทอร์มินัลเมื่ออยู่ในพื้นหลังจะระงับสคริปต์ของคุณด้วยสัญญาณ SIGTTIN
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.