Why does Ctrl-D (EOF) exit the shell?
Are you literally «ending a file» by inputting this escape sequence, i.e. is the interactive shell session is seen as a real file stream by the shell, like any other file stream? If so, which file? Or, is the Ctrl + D signal just a placeholder which means «the user has finished providing input and you may terminate»?
I had the same problem. My error was that I accidentally assigned the konsole profile shortcut to «Ctrl+d». Not my proudest moment.
2 Answers 2
The ^D character (also known as \04 or 0x4, END OF TRANSMISSION in Unicode) is the default value for the eof special control character parameter of the terminal or pseudo-terminal driver in the kernel (more precisely of the tty line discipline attached to the serial or pseudo-tty device). That’s the c_cc[VEOF] of the termios structure passed to the TCSETS/TCGETS ioctl one issues to the terminal device to affect the driver behaviour.
The typical command that sends those ioctls is the stty command.
To retrieve all the parameters:
$ stty -a speed 38400 baud; rows 58; columns 191; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; swtch = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 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
That eof parameter is only relevant when the terminal device is in icanon mode.
In that mode, the terminal driver (not the terminal emulator) implements a very simple line editor, where you can type Backspace to erase a character, Ctrl-U to erase the whole line. When an application reads from the terminal device, it sees nothing until you press Return at which point the read() returns the full line including the last LF character (by default, the terminal driver also translates the CR sent by your terminal upon Return to LF ).
Now, if you want to send what you typed so far without pressing Enter , that’s where you can enter the eof character. Upon receiving that character from the terminal emulator, the terminal driver submits the current content of the line, so that the application doing the read on it will receive it as is (and it won’t include a trailing LF character).
Now, if the current line was empty, and provided the application will have fully read the previously entered lines, the read will return 0 character.
That signifies end of file to the application (when you read from a file, you read until there’s nothing more to be read). That’s why it’s called the eof character, because sending it causes the application to see that no more input is available.
Now, modern shells, at their prompt do not set the terminal in icanon mode because they implement their own line editor which is much more advanced than the terminal driver built-in one. However, in their own line editor, to avoid confusing the users, they give the ^D character (or whatever the terminal’s eof setting is with some) the same meaning (to signify eof ).
Ctrl + C, Ctrl + D, Ctrl + Z
Комбинации клавиш Ctrl + C, Ctrl + D и Ctrl + Z часто используются в терминале для выхода из программы, работающей на переднем плане (foreground), и передачи управления Bash.
Ctrl + C выполняет прерывание процесса. По-сути убивает его. Результат действия Ctrl + D такой же. Однако разница между этими двумя способами выхода есть, и заключается она во внутреннем механизме.
Нажатие Ctrl + C заставляет терминал послать сигнал SIGINT процессу, который на данный момент его контролирует. Когда foreground-программа получает сигнал SIGINT , она обязана прервать свою работу.
Нажатие Ctrl + D говорит терминалу, что надо зарегистрировать так называемый EOF (end of file – конец файла), то есть поток ввода окончен. Bash интерпретирует это как желание выйти из программы.
При работе в конкретной программе могут срабатывать оба способа, но может только один. Так команда cat без параметров запускается в интерактивном режиме, в котором то, что вы ввели, будет тут же выводиться на экран после нажатия Enter . Выйти из программы можно как с помощью Ctrl + С , так и Ctrl + D .
Выйти из интерпретатора Питона с помощью Ctrl + C нельзя.
Комбинация клавиш Ctrl + Z посылает процессу сигнал, который приказывает ему остановиться. Это значит, что процесс остается в системе, но как бы замораживается. Само собой разумеется он уходит в бэкграунд (background) – в фоновый режим. С помощью команды bg его можно снова запустить, оставив при этом в фоновом режиме. Команда fg не только возобновляет ранее приостановленный процесс, но и выводит его из фона на передний план.
На скриншоте сначала запускается интерпретатор Питона. Далее его работа останавливается с помощью Ctrl + Z . Командой fg python3 мы возобновляем работу приложения и делаем его текущим. То, что мы вернулись в тот же самый процесс, видно по переменной a , значение которой остается доступным.
С помощью команды ps можно посмотреть процессы текущего сеанса Bash (используя ключи можно просматривать и другие процессы). А команда kill позволяет удалять ненужные.
Здесь запускается cat и приостанавливается. Далее смотрим список процессов. Ключ -9 команды kill обозначает, что мы хотим полностью избавиться от процесса. В качестве аргумента передается идентификационный номер процесса (PID).
Отметим, что во многих консольных программах управляющие комбинации с клавишей Ctrl обычно обозначаются как ^C , ^Z и т. п. То есть вместо Ctrl используется знак ^ .
Также обратим внимание, что понятие «процесса» связано с понятием «одновременного выполнения нескольких программ». Процесс – это выполняющаяся программа, а точнее экземпляр выполняющейся программы, потому что в системе может существовать несколько процессов, запущенных на основе одной программы. Ядром операционной системы создается видимость одновременного выполнения множества процессов.
При необходимости системный администратор может запускать процессы, требующие длительного выполнения, в бэкграунде, а на «переднем плане» выполнять другие команды. Запустить процесс в фоне можно с помощью знака амперсанда & , который записывается в конце команды.
Если в текущем терминале было запущено и переведено в фон несколько одноименных процессов, то сделать один из них текущим с помощью команды fg имя_программы не получится. PID также не используется как аргумент для fg . Здесь используется идентификатор процесса, который возвращает команда jobs . Причем для fg его надо использовать в формате %ID .
Выполните команды sleep 10m и sleep 10s , каждую остановите с помощью Ctrl + Z . Посмотрите идентификаторы процессов с помощью jobs . Выведите из бэкграунда десятисекундный слип. Учитывалось ли время, когда процесс был остановлен? После этого сделайте текущим десятиминутный слип и прервите его.
Курс с ответами к заданиям и дополнительными уроками в PDF
Введение в Linux и Bash. Курс