为什么Ctrl-D(EOF)退出外壳?


68

您是否通过输入此转义序列从字面上“结束文件”,即,交互shell会话是否像其他文件流一样被shell视为真实文件流?如果是这样,哪个文件?

或者,Ctrl+ D信号只是占位符,意味着“用户已完成输入,您可以终止输入”?



6
仅供参考,您可以通过bash set -o ignoreeof更改该行为。
基思2014年

我有同样的问题。我的错误是我不小心将konsole配置文件快捷方式分配给了“ Ctrl + d”。不是我最骄傲的时刻。
Brian Simonsen

Answers:


78

^D字符(也称为\04或为0x4,传输结束以Unicode)是默认值eof在内核中终端或伪终端驱动器的专用控制字符参数(更精确地的tty连接到串行或伪线路规程tty设备)。这就是传递给TCSETS / TCGETS c_cc[VEOF]termios结构的ioctl一个问题,该问题发给终端设备以影响驱动程序的行为。

发送这些命令的典型命令ioctlsstty命令。

要检索所有参数:

$ stty -a
速度38400波特; 第58行;列191;行= 0;
intr = ^ C; 退出= ^ \; 擦除= ^ ?; 杀= ^ U; eof = ^ D ; eol = <undef>; eol2 = <未定义>; swtch = <未定义>; 开始= ^ Q; 停止= ^ S; susp = ^ Z; rprnt = ^ R; werase = ^ W; lnext = ^ V; 冲洗= ^ O;
最小值= 1; 时间= 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 echo echo echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

eof参数仅在终端设备处于icanon模式下时才相关。

在那种模式下,终端驱动程序(不是终端仿真器)实现了一个非常简单的行编辑器,您可以在其中键入Backspace以擦除字符,Ctrl-U擦除整行...当应用程序从终端设备读取时,直到看到任何内容,您按此键Returnread()返回包括最后一个LF字符的完整行(默认情况下,终端驱动程序还将终端CR发送的内容转换ReturnLF)。

现在,如果您要发送到目前为止输入的内容而无需按Enter,那么您可以在其中输入eof字符。从终端仿真器接收到该字符后,终端驱动程序将提交该行的当前内容,以便在其read上进行操作的应用程序将按原样接收该LF字符(并且不包括尾随字符)。

现在,如果当前行为空,并且假设应用程序将完全读取之前输入的行,则read它将返回0个字符。

这表示应用程序已结束文件(当您从文件中读取时,您将进行读取直到没有更多内容可读取为止)。这就是为什么将其称为eof字符的原因,因为发送它会使应用程序看到没有更多可用的输入。

现在,现代的shell不会在提示符下将终端设置为icanon模式,因为它们实现了自己的行编辑器,该行编辑器比内置的终端驱动程序先进得多。但是,在他们自己的行编辑器中,为避免混淆用户,他们给^D字符(或终端的任何eof设置都赋予了相同的含义)(表示eof)。


我开始阅读此评论后就知道它是斯蒂芬妮(Stephane)撰写的:)斯蒂芬妮(Stephane),您是我的Bash英雄,我并没有讽刺。我很想和你一起吃午饭,如果你在纽约,我要买东西。
Gregg Leventhal

@GreggLeventhal。谢谢。我不久就可以去纽约的机会很小。
斯特凡Chazelas

这是EOT甚至在7位ASCII
Bananguin

9

CTRL_D只是一个信号,表明这是文本流的结尾。您不以此结束文件,而是通过输入结束输入流。您也可以使用工具hexdump找到CTRL_D也不代表任何字符或字节:

# 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

5
它结束外壳的原因是,外壳基本上是一个接受输入并对其进行填充的过程。当您告诉它不再需要输入时,shell便无所事事了。
珍妮·D

我意识到EOF序列不包含在例如文本文件中,而是由OS生成的,以报告没有更多的数据可读取。我想我真正要问的是,交互式终端会话是否像其他任何文件流一样被外壳视为一个真实的文件流。
Geeb 2014年

刚刚编辑了原始问题以进行澄清。
Geeb 2014年

2
是的,去bash的流是输入流,就像其他流一样。CTRL_D表示输入流已结束,bash可以退出。
Thorsten Staerk,2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.