Table of Contents
Terminal
Terminal is conceptually anything that looks like a keyboard + a screen attached to a teletype device (TTY). It gives humans the ability to use the teletype device.
When you type something in a terminal, the terminal sends your characters to the teletype device. When a teletype device responds, the terminal prints the result back to you. A terminal can also reinterpret the characters coming from the teletype device and change its behavior in some way (e.g. change cursor location or turn on colors).
A terminal is thus a way for humans to communicate with a teletype device. Often there is a program sitting on the other end of a teletype device. This program can be anything (vim, echo, cat, sh, grep, …) but in pretty much all cases, that program is the shell such as Bash.
Screen
The terminal screen consists of a rectangular grid of characters. The standard grid size is 80×24 characters. This is inherited from a historic hardware terminal called VT100. Conceptually, a character grid is similar to a pixel matrix. But unlike pixels of an image, you can only edit one character at the time at the location of the cursor.
Cursor
Cursor represents the location where a printable character is going to be drawn next when it's read from a teletype. In a graphical environment, you have access to pixels. You can change colors of those pixel in any order you like. In a terminal environment, you have to move the cursor first, draw something at the location of the cursor, then move the cursor to somewhere else. This is how curses works for example.
Scrollback
Scrollback lets you see the terminal history. Usually you invoke it by pressing 'Ctrl + PgUp' or 'Ctrl + PgDown'. Scrollback size is measured in the number of rows to keep. Different terminals offer different ways to configure the scrollback (usually somewhere in their Settings menu). But scrollback is often unreliable, often impossible to change and often fills up easily (meaning you can't scroll up further). This is why pagers like less or more exist. They allow you view large amounts of text much more conveniently than scrollback.
Clear
The clear command clears the screen. It pushes empty rows until nothing is visible and then resets the cursor to the top left. Often, it does not clear the scrollback so you can still use 'Ctrl + PgUp' to read the history. It also does not fix the terminal state. If for example your terminal colors go crazy, clear command will NOT help with that.
Reset
The reset command resets the terminal. It clears the screen (same as: clear command), but also resets the terminal to a sane default state (same as: stty sane command). If your terminal ever gets badly damaged – and you can barely see what you're typing – just blindly type in “reset” and hit enter. This is the nuclear option for fixing the terminal.
Echo (Command)
The echo command writes the arguments back to the teletype, verbatim.
$ echo Hello Hello
When you type echo Hello in the terminal shell and hit Enter, what you're actually doing is writing a sequence of bytes 65 63 68 6f 20 48 65 6c 6c 6f 0d to the teletype, one byte at a time. The shell on the other end of the teletype collects those bytes and, when it encounters the newline byte 0d, it decides “Okay, the user wants me to start the 'echo' command with 'Hello' as the argument”. It creates the /usr/bin/echo process, provides “Hello” to its argv[1], and rewires its stdout to the teletype.
The echo command writes 48 65 6c 6c 6f to the teletype and dies. Your terminal then reads the teletype one byte at a time and reads 48, prints 'H', moves cursor to the right, reads 65, prints 'e', moves cursor to the right, reads 6c… you get the idea. This is repeated until “Hello” is written on the screen.
Keyboard
The keyboard works mostly as you would expect in the terminal. When you press the letter 'A', a byte 61 is written to the teletype device. This byte represents the small letter 'a' according to the ASCII table. A japanese character 'あ' is reprsented by a Unicode point U+3042. This unicode point is serialized as 3 bytes e3 81 82 according to UTF-8 way of encoding it. Thus, if you have a UTF-8 keyboard and type 'あ' in the terminal, three bytes e3 81 82 will be written to the teletype device.
The troubles start to arise when you try to use modifier keys like Shift, Control, Meta (a.k.a. Alt), Super (a.k.a. Windows key) but also special keys like function keys F1-F12, arrow keys, page up, page down, home, delete, etc.
Shift key mostly stays true to its original mearning. When you press 'Shift + A' in the terminal, a byte 41 is written to the teletype device instead of 61 – corresponding to uppercase 'A' instead of lowecase 'a' respectively. But it's not the terminal doing the shifting – it's the kernel! In fact, there is no way for the terminal to detect a shift key at all. A shift key by itself is simply unencoded.
Control key is used to send a signal to the program. When you press 'Ctrl + C' in the terminal a byte 03 to the teletype device. The teletype device sees this and – instead of delivering the byte to the program on the other end of a teletype device – it asks the kernel to send SIGINT to the program (interrupt signal). This is the default behavior when a teletype device is put “cooked” mode. When a teletype device is put in “raw” mode, it does deliver the byte 03 to the program. Shift key makes no difference when used with Ctrl key. 'Shift + Ctrl + C' writes 03 to the teletype device just as 'Ctrl + C'.
Meta (Alt) key is used to prefix a character with an ESC key. The ESC key is encoded as 1b and is also the same key used in Escape sequences. When you press 'Alt + A' in the terminal, two bytes 1b 61 are written to the teletype device – corresponding to the ESC key + lowercase letter 'a'. If you press 'Alt + Shift + A', the byte 61 (lowercase 'a') changes to 41 (uppercase 'A') but is still prefixed by 1b (ESC key) – resulting in 1b 41. It actually makes no difference whether you use 'Alt + A', or just press ESC key then press 'A', manually.
Super (Windows) key is completely ignored.
Function keys are encoded as escape sequences. Escape sequences are byte sequence that include ESC key + key representing a sequence family + a sequence of bytes. Function keys F1, F2, F3, F4 belong to SS3 family (Single Shift 3) and are represented by ESC O P, ESC O Q, ESC O R, ESC O S respectively. The 'O' character represents the “Single Shift 3” family. It actually makes no difference if you press F1 or press in ESC, O, Shift + P manually.
Arrow keys are also encoded as escape sequences. They are represented by the CSI (Control Sequence Introducer) family. Arrow keys Up, Down, Right, Left are represented by ESC [ A, ESC [ B, ESC [ C, ESC [ D. The '[' key represents the “Control Sequence Introducer” family. It actually makes no difference if you press the Up key or press ESC, [, Shift + A manually (try it!).
Other keys like Home, End, Page up, Page down, Delete are all represented by escape sequences in some way as well.
This behavior comes as surprising to many people who look to configure terminal programs like vim, tmux, less, etc. What? You're saying there is no way to differentiate 'Ctrl + A' from 'Ctrl + Shift + A'?? Unfortunately no.
Signals
Terminals allow you to send signals by pressing Control key + Letter.
For completion, here's a table of all the other Control key + Letter:
Ctrl-key behavior on Linux / POSIX terminals (canonical mode) Key ASCII Name Effect / Meaning Signal ----- ----- ---- ----------------------------------------------- ------- Ctrl+A 0x01 SOH Beginning of line (readline) - Ctrl+B 0x02 STX Backward character (readline) - Ctrl+C 0x03 ETX Interrupt foreground process SIGINT Ctrl+D 0x04 EOT End-of-file on input (read() returns 0 if empty) - Ctrl+E 0x05 ENQ End of line (readline) - Ctrl+F 0x06 ACK Forward character (readline) - Ctrl+G 0x07 BEL Bell / alert - Ctrl+H 0x08 BS Backspace (historical erase) - Ctrl+I 0x09 TAB Tab / completion - Ctrl+J 0x0A LF Line feed (newline) - Ctrl+K 0x0B VT Kill line forward (readline) - Ctrl+L 0x0C FF Clear screen - Ctrl+M 0x0D CR Carriage return (Enter) - Ctrl+N 0x0E SO Next history entry - Ctrl+O 0x0F SI Execute and fetch next history entry - Ctrl+P 0x10 DLE Previous history entry - Ctrl+Q 0x11 DC1 Resume output (XON) - Ctrl+R 0x12 DC2 Reverse search (readline) - Ctrl+S 0x13 DC3 Pause output (XOFF) - Ctrl+T 0x14 DC4 Transpose characters - Ctrl+U 0x15 NAK Kill entire line - Ctrl+V 0x16 SYN Quote next character - Ctrl+W 0x17 ETB Delete previous word - Ctrl+X 0x18 CAN Readline command prefix - Ctrl+Y 0x19 EM Yank (paste) - Ctrl+Z 0x1A SUB Suspend foreground process SIGTSTP Ctrl+\ 0x1C FS Quit and dump core SIGQUIT Ctrl+] 0x1D GS Escape character (telnet, etc.) - Ctrl+^ 0x1E RS Rarely used - Ctrl+_ 0x1F US Undo (readline) -
You can inspect these with:
stty -a
You can change the SIGINT (interrupt i.e. intr) from Contrl + C to e.g. Ctrl + K like this:
stty intr ^K
The stty command is used to inspect and change the terminal discipline.
Note that caret ^ prefix (such as here) often refers to the Control key in documentation and elsewhere.
Echo (Attribute)
Echo is when you type on your keyboard and the terminal echoes your keys back on the screen, so that you can see what you're typing. Terminals let you turn the teletype echo on/off. Commands like passwd, for example, turn the echo off when the user is entering a password.
You can turn the echo off:
stty -echo
You can turn echo back on (or use the nuclear option a.k.a. the reset command):
stty echo
This is unerlated to the echo command but the concept is similar. They're both named that way for similar reasons.
Escape sequences
ANSI escape sequences are byte sequences which the terminal interprets in a special way. They always start with the ESC byte 0x1b, which is usually written as '\e', '\033' (octal), '\x1b' (hexadecimal).
The byte
ESC Bytes Abbr. Description +-----+-------+-----+-----------------------------+ | \e@ | 1b 80 | PAD | Padding Character | | \eA | 1b 81 | HOP | High Octet Preset | | \eB | 1b 82 | BPH | Break Permitted Here | | \eC | 1b 83 | NBH | No Break Here | | \eD | 1b 84 | IND | Index | | \eE | 1b 85 | NEL | Next Line | | \eF | 1b 86 | SSA | Start of Selected Area | | \eG | 1b 87 | ESA | End of Selected Area | | \eH | 1b 88 | HTS | Horizontal Tabulation Set | | \eI | 1b 89 | HTJ | Horizontal Tabulation Just. | | \eJ | 1b 8a | VTS | Vertical Tabulation Set | | \eK | 1b 8b | PLD | Partial Line Down | | \eL | 1b 8c | PLU | Partial Line Up | | \eM | 1b 8d | RI | Reverse Index | | \eN | 1b 8e | SS2 | Single Shift Two | | \eO | 1b 8f | SS3 | Single Shift Three | | \eP | 1b 90 | DCS | Device Control String | | \eQ | 1b 91 | PU1 | Private Use One | | \eR | 1b 92 | PU2 | Private Use Two | | \eS | 1b 93 | STS | Set Transmit State | | \eT | 1b 94 | CCH | Cancel Character | | \eU | 1b 95 | MW | Message Waiting | | \eV | 1b 96 | SPA | Start of Protected Area | | \eW | 1b 97 | EPA | End of Protected Area | | \eX | 1b 98 | SOS | Start of String | | \eY | 1b 99 | SGCI| Single Graphic Char Intro | | \eZ | 1b 9a | SCI | Single Character Introducer | | \e[ | 1b 9b | CSI | Control Sequence Introducer | | \e\ | 1b 9c | ST | String Terminator | | \e] | 1b 9d | OSC | Operating System Command | | \e^ | 1b 9e | PM | Privacy Message | | \e_ | 1b 9f | APC | Application Program Command | +-----+-------+-----+-----------------------------+
Of these, \e[
Escape Bytes Abbr. Description +-----------------------+-----------------------------+------+----------------------------------+ | \e[ <num> A | 1b 5b <num> 41 | CUU | Cursor Up | | \e[ <num> B | 1b 5b <num> 42 | CUD | Cursor Down | | \e[ <num> C | 1b 5b <num> 43 | CUF | Cursor Forward | | \e[ <num> D | 1b 5b <num> 44 | CUB | Cursor Back | | \e[ <num> E | 1b 5b <num> 45 | CNL | Cursor Next Line | | \e[ <num> F | 1b 5b <num> 46 | CPL | Cursor Previous Line | | \e[ <num> G | 1b 5b <num> 47 | CHA | Cursor Horizontal Absolute | | \e[ <num> ; <num> H | 1b 5b <num> 3b <num> 48 | CUP | Cursor Position | | \e[ <num> J | 1b 5b <num> 4a | ED | Erase in Display | | \e[ <num> K | 1b 5b <num> 4b | EL | Erase in Line | | \e[ <num> S | 1b 5b <num> 53 | SU | Scroll Up | | \e[ <num> T | 1b 5b <num> 54 | SD | Scroll Down | | \e[ <num> ; <num> f | 1b 5b <num> 3b <num> 66 | HVP | Horizontal and Vertical Position | | \e[ <num> m | 1b 5b <num> 6d | SGR | Select Graphic Rendition | | \e[ 4 i | 1b 5b 34 69 | MC | Media Copy (Aux Port Off) | | \e[ 5 i | 1b 5b 35 69 | MC | Media Copy (Aux Port On) | | \e[ 6 n | 1b 5b 36 6e | DSR | Device Status Report | | \e[ ? <num> h | 1b 5b 3f <num> 68 | SM | Set Mode (Private) | | \e[ ? <num> l | 1b 5b 3f <num> 6c | RM | Reset Mode (Private) | | \e[ s | 1b 5b 73 | SCP | Save Cursor Position | | \e[ u | 1b 5b 75 | RCP | Restore Cursor Position | +-----------------------+-----------------------------+------+----------------------------------+
Attributes
Color
Font
Mouse
Capabilities
Scripting
When you're scripting, it's often useful to know what terminal the user is using. For example, does the terminal support color? However there is actually no way to definitively say which terminal the user is using from the shell alone. All you can do is check the $TERM variable which the user can spoof.
Types
The following are terminal types differentiated by what teletype device they're attached on:
- Terminal emulator attached on e.g.
/dev/pts/1 - Virtual console attached on e.g.
/dev/tty1 - Serial line attached on e.g.
/dev/ttyS0 - Serial USB attached on e.g.
/dev/ttyUSB0
F.A.Q. (Terminology)
Is terminal a program, like bash?
Strictly speaking, no! A terminal is anything that allows a human to communicate with a teletype device. Anything that looks like a keyboard + screen attached to a teletype device can be called a terminal. It doesn't have to be a program!
This makes it a bit confusing because when most people say “open the terminal” they mean a terminal emulator, like xterm. In this case a terminal is an actual graphical program, yes. But in case of a virtual console there is no additional program. You are interacting with Linux kernel itself. In that case there is only you + bash + Linux kernel.
What's the difference between "terminal" and "console"?
The words “console” and “terminal” are often used interchangeably. Usually, the word “console” refers to a kind of master terminal – the one provided by the system itself. For example, virtual console is a type of terminal provided by Linux kernel which you can access by pressing Ctrl + Alt + F1-6. The word “terminal” refers to a more general concept of “keyboard + screen attached to a teletype device”.
What's the difference between "terminal" and "TTY"?
The word TTY is often used interchangeably with the word terminal. But TTY is actually a shorthand for “teletype device”. A terminal can be attached to a teletype device to allow a human to use it, but a terminal is not a teletype device itself. Teletype devices are exposed in /dev directory (e.g. /dev/tty1) but there is no global list of terminals.
What's the difference between "terminal" and "shell"?
Shell is a type of program that lets you run other programs. It sits on the other end of the teletype device. Both of you communicate via a teletype device, but because you're human you need a keyboard and a screen to use the teletype device, which is called a terminal.
What's the difference between "terminal" and "CLI"?
The acronym CLI stands for “command line interface”. It's a type of user interface where you type in the commands in a one line (hence the name) and is usually associated with the shell. Because the terminal most commonly runs a shell, the words “terminal” and “CLI” are often used interchangeably. However, there are other programs like 'vim', which is a terminal text editor, but which interface is not a command line.
