Mengapa saya tidak bisa membaca / dev / stdout dengan editor teks?

9

Saya baru mulai belajar bagaimana Everything Is A File TM di Linux, yang membuat saya bertanya-tanya apa yang akan terjadi jika saya benar-benar membaca dari / dev / stdout:

$ cat /dev/stdout 
^C
$ tail /dev/stdout 
^C

( ^CAku yang membunuh program setelah hang).

Ketika saya mencoba vim, saya mendapatkan pesan yang tidak terpikirkan: "/ dev / stdout" bukan file. Terkesiap!

Jadi apa yang memberi, mengapa saya mendapatkan hangup atau pesan kesalahan ketika saya mencoba membaca "file" ini?

pengguna1717828
sumber
1
Apa yang dianggap file oleh vim dan apa yang dimaksud dengan "semuanya adalah file" (tidak ada merek dagang terkait) di * nix bukanlah hal yang sama. Lihat misalnya # 1 dan # 2 .
goldilocks

Jawaban:

11

mengapa saya mendapatkan hangup

Anda tidak mendapatkan "hangup" dari cat(1)dan tail(1), itu hanya memblokir saat dibaca. cat(1)menunggu input, dan mencetaknya segera setelah melihat garis lengkap:

$ cat /dev/stdout
foo
foo
bar
bar

Di sini saya mengetik fooEnterbarEnterCTRL- D.

tail(1)menunggu input, dan mencetaknya hanya ketika ia dapat mendeteksi EOF:

$ tail /dev/stdout
foo
bar
foo
bar

Di sini saya mengetik lagi fooEnterbarEnterCTRL- D.

atau pesan kesalahan

Vim adalah satu-satunya yang memberi Anda kesalahan. Itu melakukan itu karena berjalan stat(2) melawan /dev/stdout, dan menemukan itu tidak memiliki S_IFREGset bit.

/dev/stdoutadalah file, tetapi bukan file biasa . Bahkan, ada beberapa tarian di kernel untuk memberikannya entri di sistem file. Di Linux:

$ ls -l /dev/stdout
lrwxrwxrwx 1 root root 15 May  8 19:42 /dev/stdout -> /proc/self/fd/1

Di OpenBSD:

$ ls -l /dev/stdout
crw-rw-rw-  1 root  wheel   22,   1 May  7 09:05:03 2015 /dev/stdout

Di FreeBSD:

$ ls -l /dev/stdout
lrwxr-xr-x  1 root  wheel  4 May  8 21:35 /dev/stdout -> fd/1

$ ls -l /dev/fd/1
crw-rw-rw-  1 root  wheel  0x18 May  8 21:35 /dev/fd/1
lcd047
sumber
5

(Hampir) semuanya adalah file tetapi tidak semuanya adalah file biasa . Tidak masuk akal untuk memanggil editor teks pada sesuatu yang merupakan file khusus seperti direktori, soket jaringan, port serial, dll.

File /dev/stdoutdapat menjadi salah satu dari beberapa hal tergantung pada varian unix:

  • file "khusus", biasanya perangkat karakter;
  • tautan simbolis "ajaib" yang menunjuk ke file yang proses pengaksesannya terbuka pada deskriptor ini;
  • tautan simbolis ke salah satu di atas.

Dalam kasus apa pun, membuka /dev/stdoutdan file-file serupa membuat deskriptor file baru yang dikaitkan dengan file yang sama yang sudah dibuka aplikasi pada deskriptor file 1. “Output standar” berarti deskriptor file 1, dan itu hanya konvensi bahwa deskriptor file ini digunakan untuk output - kernel tidak peduli.

Ketika Anda menjalankan program di terminal, ketiga deskriptor standar (0 = input standar, 1 = output standar, 2 = standard error) dibuka pada perangkat terminal. Membaca dari perangkat itu mengembalikan karakter yang diketik oleh pengguna, dan menulis ke perangkat itu menampilkan teks di jendela terminal. (Tidak ada cara standar, diberikan perangkat terminal, untuk membaca output yang ditampilkan atau menyuntikkan input ke dalamnya.)

Ketika Anda menjalankan cat /dev/stdout, itu melakukan hal yang persis sama dengan cat /dev/stdinatau cat /dev/stderr, karena ketiga penjelas file ini terhubung ke file yang sama: ia memberitahu catuntuk membaca dari terminal. Itulah yang cattanpa argumen juga.

Jika Anda berlari cat /dev/stdout >foo, maka /dev/stdoutakan merujuk ke file foo- perintah itu setara dengan cat foo >foo. Bergantung pada catimplementasinya, mungkin kesalahan keluar (versi GNU mengeluh bahwa "file input adalah file output"), atau mungkin tidak melakukan apa-apa karena membaca dari file fooyang kosong ( >foohanya terpotong). Dengan versi catyang tidak mendeteksi kasus khusus ini, jika footidak kosong, maka cat /dev/stdout >>fooatau yang setara cat foo >>fooakan menambahkan konten file ke dirinya sendiri tanpa batas.

Ketika Anda menjalankan vim /dev/stdout, itu mengeluh karena tidak tahu cara mengedit terminal (itu tidak masuk akal).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2

catdan tailsedang mencari konten opsional diikuti oleh akhir file. /dev/stdouttetap terbuka, jadi catdan tailteruslah mencari.

Politank-Z
sumber