Mengapa Ctrl-D (EOF) keluar dari shell?

69

Apakah Anda benar-benar "mengakhiri file" dengan memasukkan urutan melarikan diri ini, yaitu apakah sesi shell interaktif dilihat sebagai aliran file nyata oleh shell, seperti aliran file lainnya? Jika demikian, file mana?

Atau, apakah sinyal Ctrl+ Dhanya placeholder yang berarti "pengguna telah selesai memberikan input dan Anda dapat mengakhiri"?

Geeb
sumber
6
FYI, dalam bash yang dapat Anda lakukan set -o ignoreeofuntuk mengubah perilaku itu.
Keith
Saya memiliki masalah yang sama. Kesalahan saya adalah bahwa saya tidak sengaja menetapkan pintasan profil konsole ke "Ctrl + d". Bukan momen paling membanggakan saya.
Brian Simonsen

Jawaban:

79

The ^Dkarakter (juga dikenal sebagai \04atau 0x4, AKHIR TRANSMISI di Unicode) adalah nilai default untuk eofparameter karakter kontrol khusus dari terminal atau pengemudi pseudo-terminal di kernel (lebih tepatnya dari ttydisiplin baris melekat pada serial atau pseudo perangkat tty ). Itulah c_cc[VEOF]yang termiosstruktur dilewatkan ke TCSETS / TCGETS ioctlsalah satu isu ke perangkat terminal untuk mempengaruhi perilaku pengemudi.

Perintah khas yang mengirim itu ioctlsadalah sttyperintah.

Untuk mengambil semua parameter:

$ stty -a
kecepatan 38400 baud; baris 58; kolom 191; baris = 0;
intr = ^ C; berhenti = ^ \; hapus = ^?; bunuh = ^ U; bukti = ^ D ; eol = <undef>; eol2 = <undef>; swtch = <undef>; mulai = ^ Q; stop = ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W; lnext = ^ V; flush = ^ O;
min = 1; waktu = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

Itu eofparameter hanya relevan bila perangkat terminal di icanonmodus.

Dalam mode itu, driver terminal (bukan emulator terminal) mengimplementasikan editor baris yang sangat sederhana , di mana Anda dapat mengetik Backspaceuntuk menghapus karakter, Ctrl-Uuntuk menghapus seluruh baris ... Ketika aplikasi membaca dari perangkat terminal, ia tidak melihat apa pun hingga Anda menekan Returnpada titik mana read()mengembalikan garis penuh termasuk LFkarakter terakhir (secara default, driver terminal juga menerjemahkan yang CRdikirim oleh terminal Anda Returnke LF).

Sekarang, jika Anda ingin mengirim apa yang Anda ketikkan sejauh ini tanpa menekan Enter, di situlah Anda dapat memasukkan eofkarakter. Setelah menerima karakter itu dari emulator terminal, driver terminal mengirimkan konten baris saat ini, sehingga aplikasi yang melakukan hal readitu akan menerimanya apa adanya (dan itu tidak akan menyertakan LFkarakter tambahan).

Sekarang, jika baris saat ini kosong, dan asalkan aplikasi akan sepenuhnya membaca baris yang dimasukkan sebelumnya, readakan mengembalikan 0 karakter.

Itu menandakan akhir file ke aplikasi (ketika Anda membaca dari file, Anda membaca sampai tidak ada lagi yang bisa dibaca). Itu sebabnya ini disebut eofkarakter, karena mengirimkannya menyebabkan aplikasi melihat bahwa tidak ada lagi input yang tersedia.

Sekarang, shell modern, pada prompt mereka tidak mengatur terminal dalam icanonmode karena mereka mengimplementasikan editor baris mereka sendiri yang jauh lebih maju daripada driver terminal built-in. Namun, dalam editor baris mereka sendiri , untuk menghindari membingungkan para pengguna, mereka memberikan ^Dkarakter (atau apa pun pengaturan terminal eofdengan beberapa) makna yang sama (untuk menandakan eof).

Stéphane Chazelas
sumber
Saya tahu begitu saya mulai membaca komentar ini bahwa itu ditulis oleh Stephane :) Anda, Stephane, adalah pahlawan Bash saya, dan saya tidak sedang menyindir. Saya ingin makan siang dengan Anda dan memilih otak Anda jika Anda pernah berada di NYC, saya membeli.
Gregg Leventhal
@GreggLeventhal. Terima kasih. Peluang saya pergi ke NYC dalam waktu dekat ini cukup tipis.
Stéphane Chazelas
EOT bahkan dalam 7-Bit ASCII
Bananguin
9

CTRL_D hanyalah sinyal yang mengatakan bahwa ini adalah akhir dari aliran teks. Anda tidak mengakhiri file dengan itu, Anda mengakhiri aliran input Anda dengan mengetiknya. CTRL_D juga tidak mendukung karakter atau byte apa pun karena Anda dapat mengetahuinya dengan hexdump alat:

# cat >test.txt
asdf# hexdump -C test.txt 
00000000  61 73 64 66                                       |asdf|
00000004
# ll test.txt 
-rw-r--r-- 1 root root 4 Jan 21 11:55 test.txt
Thorsten Staerk
sumber
5
Dan alasan ia mengakhiri shell adalah bahwa shell pada dasarnya adalah sebuah proses yang menerima input dan melakukan hal-hal dengannya. Ketika Anda memberi tahu bahwa tidak ada lagi input yang akan datang, tidak ada lagi yang bisa dilakukan shell.
Jenny D
Saya menyadari bahwa urutan EOF tidak terkandung oleh, katakanlah, file teks, dan dihasilkan oleh OS untuk melaporkan bahwa tidak ada lagi data untuk dibaca. Saya pikir apa yang sebenarnya saya tanyakan adalah apakah sesi terminal interaktif dilihat sebagai aliran file nyata oleh shell, seperti aliran file lainnya.
Geeb
Baru saja mengedit pertanyaan asli untuk diklarifikasi.
Geeb
2
ya, aliran yang menuju ke bash adalah aliran input seperti yang lainnya. CTRL_D memberi sinyal bahwa aliran input pada akhirnya dan bash dapat berhenti.
Thorsten Staerk