Bagaimana `less` mengambil data dari stdin sementara masih bisa membaca perintah dari pengguna?


47

Karena sebagian besar dari Anda telah melakukan berkali-kali, nyaman untuk melihat teks panjang menggunakan less:

some_command | less

Sekarang stdinnya terhubung ke pipa (FIFO). Bagaimana bisa masih membaca perintah seperti naik / turun / keluar?


15
lessmembaca data yang akan ditampilkan dari stdin, dan membaca perintah dari tty. Mereka adalah hal yang berbeda.
William Pursell

2
@ WilliamPursell Ya saya tahu. Tetapi hanya ada satu aliran input standar, kan?
iBug

4
Ya, ada satu aliran input, dan satu tty. lessmembaca data dari stdin, dan perintah dari tty.
William Pursell

Jawaban:


52

Seperti yang disebutkan oleh William Pursell , lessmembaca penekanan tombol pengguna dari terminal. Secara eksplisit terbuka /dev/tty, terminal pengendali; yang memberikannya deskriptor file, terpisah dari input standar, dari mana ia dapat membaca input interaktif pengguna. Secara bersamaan dapat membaca data untuk ditampilkan dari input standar jika diperlukan. (Bisa juga menulis langsung ke terminal jika perlu.)

Anda dapat melihat ini terjadi dengan menjalankan

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

Bergerak di sekitar input, keluar less, dan melihat isi less.trace: Anda akan melihatnya terbuka /dev/tty, dan membaca dari kedua deskriptor file 0 dan mana yang dikembalikan ketika dibuka /dev/tty(kemungkinan 3).

Ini adalah praktik umum untuk program yang ingin memastikan mereka membaca dan menulis ke terminal. Salah satu contohnya adalah SSH, misalnya ketika meminta kata sandi atau frasa sandi.

Seperti yang dijelaskan oleh schily , jika /dev/ttytidak dapat dibuka, lessakan membaca dari kesalahan standarnya (file descriptor 2). lessPenggunaan /dev/ttydiperkenalkan pada versi 177, dirilis pada 2 April 1991.

Jika Anda mencoba berlari cat /dev/tty | less, seperti yang disarankan oleh Hagen von Eitzen , lessakan berhasil membuka /dev/ttytetapi tidak akan mendapatkan masukan dari itu sampai catmenutupnya. Jadi Anda akan melihat layar kosong, dan tidak ada yang lain sampai Anda menekan CtrlCuntuk membunuh cat(atau membunuhnya dengan cara lain); maka lessakan ditampilkan apa pun yang Anda ketikkan saat catsedang berjalan, dan memungkinkan Anda untuk mengontrolnya.


4
@HagenvonEitzen Komputer Anda akan meledak! Ini seperti cara Kirk dan Spock membuat android Mudd crash.
Barmar

7
@HagenvonEitzen Wow. Sebuah doubly- penggunaan berguna kucing . Saya terkesan.
Andrew Henle

8
@ kegembiraan Saya pikir poin Andrew adalah bahwa cat blah |dapat digantikan oleh < blah, dan bahkan itu tidak perlu dalam hal ini karena less blahberfungsi juga (well, less -f /dev/tty). Tetapi membaca dari /dev/ttyadalah sedikit kasus khusus, dan ketiga varian ( cat /dev/tty | less, less < /dev/ttydan less -f /dev/tty) menghasilkan hasil yang berbeda.
Stephen Kitt

1
Apakah / dev / tty selalu menunjuk ke tempat yang tepat? Saya pikir Anda harus menggunakan / dev / ptsX biasanya?
StarWeaver

2
@ StarWeaver melihat pertanyaan ini tentang perbedaan antara /dev/ttydan /dev/pts/....
Stephen Kitt

26

UNIX memberikan dua metode untuk membaca input pengguna sementara stdin telah diarahkan:

  • Metode aslinya adalah membaca dari stderr . Stderr terbuka untuk menulis dan membaca dan ini masih disebutkan dalam POSIX.

  • Versi UNIX kemudian (sekitar 1979) menambahkan /dev/ttyantarmuka driver yang memungkinkan untuk membuka tty mengendalikan proses. Karena ada proses tanpa kontrol tty, ada kemungkinan bahwa upaya untuk membuka /dev/ttygagal. Oleh karena itu, perangkat lunak tertulis yang ramah memiliki fallback ke metode asli dan kemudian mencoba membaca dari stderr.


11
Baca dari stderr? Belajar sesuatu yang baru.
iBug

1
Saya senang seseorang mengingat cara lama.
Joshua

3
Apakah alasan stderr digunakan untuk membaca, karena itu kemungkinan paling kecil untuk diarahkan? Saya tidak melihat perbedaan lain antara itu dan stdout (atau untuk mater stdin itu, sebelum pengalihan).
ctrl-alt-delor

4
Ya, itu karena ini adalah deskriptor file yang memiliki peluang paling sedikit untuk diarahkan.
schily

@ ctrl-alt-delor: Itu adalah / khas untuk menjalankan shell dengan stdin, stdout, dan stderr, semuanya merupakan dup()lisensi dari deskripsi file yang sama, meskipun, semua dibuka pada tty. (Rupanya POSIX masih membutuhkan atau menyarankan (jawaban ini tidak mengatakan) bahwa stderr menjadi baca / tulis FD, tidak dibuka dengan sesuatu seperti open("/dev/ttyS0", O_WRONLY). Membaca stderr akan gagal dalam kasus itu.)
Peter Cordes
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.