Pourquoi Ctrl-D (EOF) quitte-t-il le shell?

69

Etes-vous littéralement en train de "terminer un fichier" en entrant cette séquence d'échappement, c'est-à-dire si la session interactive du shell est vue comme un véritable flux de fichiers par le shell, comme tout autre flux de fichiers? Si oui, quel fichier?

Ou bien, le signal Ctrl+ est-il Dsimplement un espace réservé signifiant "l'utilisateur a fini de fournir des entrées et vous pouvez mettre fin à l'opération"?

Geeb
la source
6
Pour info, en bash, vous pouvez faire set -o ignoreeofpour changer ce comportement.
Keith
J'ai eu le même problème. Mon erreur a été d'avoir accidentellement assigné le raccourci de profil konsole à "Ctrl + d". Pas mon moment le plus fier.
Brian Simonsen

Réponses:

79

Le ^Dcaractère (également appelé \04ou 0x4, FIN DE TRANSMISSION en Unicode) est la valeur par défaut du eofparamètre caractère de contrôle spécial du terminal ou du pilote de pseudo-terminal dans le noyau (plus précisément de la ttydiscipline de ligne attachée au port série ou pseudo). appareil tty ). C'est c_cc[VEOF]la termiosstructure transmise au TCSETS / TCGETS que l' ioctlon envoie au terminal pour influer sur le comportement du conducteur.

La commande typique qui envoie ceux-ci ioctlsest la sttycommande.

Pour récupérer tous les paramètres:

$ stty -a
vitesse 38400 bauds; les rangées 58; colonnes 191; ligne = 0;
intr = ^ C; quitter = ^ \; effacer = ^ ?; tuer = ^ U; eof = ^ D ; eol = <undef>; eol2 = <undef>; swtch = <undef>; début = ^ Q; stop = ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W; lnext = ^ V; flush = ^ O;
min = 1; temps = 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 ecxo ecxo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

Ce eofparamètre n'est pertinent que lorsque le terminal est en icanonmode.

Dans ce mode, le pilote de terminal (pas l'émulateur de terminal) implémente un éditeur de ligne très simple , dans lequel vous pouvez taper Backspacepour effacer un caractère, Ctrl-Upour effacer toute la ligne ... Lorsqu'une application lit à partir du terminal, elle ne voit rien jusqu'à ce que vous appuyez sur Returnà quel point les read()rendements de la ligne complète , y compris le dernier LFcaractère (par défaut, le pilote de terminal se traduit également par l' CRenvoyé par votre terminal lors Returnde LF).

Maintenant, si vous voulez envoyer ce que vous avez tapé jusqu'à présent sans appuyer Enter, vous pouvez entrer le eofcaractère. À la réception de ce caractère de l'émulateur de terminal, le pilote de terminal soumet le contenu actuel de la ligne afin que l'application qui le readreçoit le reçoive tel quel (et n'inclura pas de LFcaractère de fin ).

Maintenant, si la ligne en cours était vide et que l'application lise intégralement les lignes entrées précédemment, le readcaractère 0 sera renvoyé.

Cela signifie la fin du fichier dans l'application (lorsque vous lisez un fichier, vous lisez jusqu'à ce qu'il ne reste plus rien à lire). C'est pourquoi il est appelé le eofcaractère, car son envoi fait en sorte que l'application constate qu'aucune autre entrée n'est disponible.

Maintenant, les shells modernes, à leur invite, ne mettent pas le terminal en icanonmode, car ils implémentent leur propre éditeur de ligne, qui est beaucoup plus avancé que le pilote de terminal intégré. Cependant, dans leur propre éditeur de lignes , pour éviter de dérouter les utilisateurs, ils donnent au ^Dcaractère (ou quel que soit le eofréglage du terminal avec certains) la même signification (signifier eof).

Stéphane Chazelas
la source
J'ai su une fois que j'ai commencé à lire ce commentaire qu'il avait été écrit par Stéphane :) Toi, Stéphane, tu es mon héros Bash et je ne suis pas sarcastique. J'adorerais déjeuner avec vous et choisir votre cerveau si vous êtes à New York, j'achète.
Gregg Leventhal
@ GreggLeventhal. Merci. Les chances que je retourne bientôt à New York sont plutôt minces.
Stéphane Chazelas
C'est EOT même en ASCII 7 bits
Bananguin
9

CTRL_D est juste un signal disant qu'il s'agit de la fin d'un flux de texte. Vous ne terminez pas un fichier avec celui-ci, vous terminez votre flux d'entrée en le tapant. De plus, CTRL_D ne représente aucun caractère ou octet comme vous pouvez le savoir avec l'outil hexdump:

# 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
la source
5
Et la raison pour laquelle il termine le shell est que le shell est fondamentalement un processus qui accepte les entrées et les manipule. Quand vous lui dites que plus aucune entrée ne va arriver, le shell n'a plus rien à faire.
Jenny D
Je réalise que la séquence EOF n'est pas contenue, par exemple, dans un fichier texte, et est générée par le système d'exploitation pour signaler qu'il n'y a plus de données à lire. Je pense que ce que je veux vraiment savoir, c'est si la session de terminal interactive est considérée comme un véritable flux de fichiers par le shell, comme n'importe quel autre flux de fichiers.
Geeb
Vient de modifier la question initiale pour clarifier.
Geeb
2
oui, le flux qui va à bash est un flux d’entrée comme un autre. CTRL_D signale que le flux d'entrée est à sa fin et que bash peut quitter.
Thorsten Staerk