Terminal & TTY: Explanation & Insights

A text interface for typing commands and reading output; on Linux the underlying device is still called a TTY, after teletype.

What It Is

A terminal is the thing you type into and read replies from — the black window with the blinking cursor where you run ls, watch top scroll, and wait for ssh to drop you onto a far-away box. That much you already know from using one. What almost nobody tells you, and what makes the whole subject suddenly click, is that the word "terminal" describes a device that no longer exists, and that the window on your screen is a meticulous impersonation of it.

Rewind to the 1960s and 70s. A computer was a room-sized machine you did not sit at; you sat at a terminal — a separate physical appliance, wired to the computer by a cable, whose entire job was to send your keystrokes down the wire and present whatever came back. The earliest ones were literally electric typewriters: a teletypewriter, or teletype, that hammered the computer's replies onto a roll of paper in real ink, one character at a time, with a noise like a small machine gun. Later models dropped the paper for a phosphor screen — the video terminal, the most famous of which was the DEC VT100 of 1978, a beige box with a keyboard and a green-on-black display and not a scrap of computing power of its own. It was a window onto a machine somewhere else, nothing more.

That is the crucial idea, and it's worth saying flatly: the terminal was never the computer. It was the channel. The terminal carried your keystrokes to a program and painted that program's text back at you, and it did nothing else — no thinking, no files, no logic. The thinking happened on the big machine; the terminal was the mouth and ears.

Today the physical device is gone, but the channel survives — as software. The window on your screen is a terminal emulator: GNOME Terminal, Konsole, the macOS Terminal, iTerm, the thing that opens when you SSH from your laptop. It is a program pretending to be a VT100, faithfully enough that decades-old software can't tell the difference. It still has exactly one job, the same job the beige box had: carry your keystrokes to the program running inside it, and draw that program's text output back onto the glass. Everything else — the colours, the tabs, the scrollback, the font you fuss over — is convenience bolted onto that ancient, simple contract.

One distinction will save you a great deal of confusion, so let's nail it down before anything else. The terminal is the channel; the shell is the program that runs inside it. When you open a terminal window and see a $ prompt, that prompt belongs to the shell — usually bash or zsh — a program whose job is to read command lines and run them. The terminal knows nothing about commands; it just ferries bytes. The shell knows nothing about fonts or windows; it just reads text and writes text. They are two separate things that happen to live in the same rectangle, and people conflate them constantly. Keep them apart in your head and half the mysteries of the command line dissolve.

Note

"Terminal," "console," "shell," and "command line" get used as if they were synonyms, and in casual speech that's mostly harmless. But they aren't the same: the terminal is the window/device, the shell is the program running in it, the "command line" is the line of text you type, and the "console" historically means the machine's own directly-attached terminal (the keyboard and screen physically bolted to the server). When something is behaving strangely, knowing which of the four you're actually talking about is often the first step to fixing it.

Why It Matters

For someone running servers, the terminal is not a nostalgia piece — it's the primary interface to every Linux box you'll ever own. There's no clickable desktop on a cloud server; there's a terminal, a shell, and the text flowing between them. Understanding what the terminal actually is — a dumb channel impersonating an old device — explains a whole family of everyday puzzles that otherwise feel like black magic.

Why does pressing Ctrl-C kill a runaway command? Why does Ctrl-D at an empty prompt log you out? Why does a program's progress bar look perfect in your terminal but turn into a smear of ^[[0m garbage when you pipe it to a file? Why does clear work but the same program over a flaky connection sometimes leaves the screen wedged? Every one of these is the terminal layer doing its job — and once you see the layer, the answers stop being folklore and become mechanics.

It matters in a second, quieter way too. The terminal is where a server talks to you. When a service is misbehaving, when a disk is filling, when the load is climbing, you find out by typing into a terminal and reading what comes back. The faster and more fluently you can drive that channel — without fighting it, without superstition about which key does what — the faster you diagnose and fix. Fluency at the terminal is the difference between a thirty-second fix and a thirty-minute flail, and it compounds across an entire career, because the terminal, like so much of Unix, has barely changed in fifty years and won't change in the next fifty either.

TTY: The Word That Outlived Its Hardware

Here is the fossil at the centre of the whole subject, and it's one of computing's better jokes.

When Unix was born in 1969, the terminals attached to it were teletypewriters — the clattering paper-printing typewriters described above. Unix needed a short name for "the device a user is sitting at," and it took the obvious abbreviation: tty, for teletypewriter. Reasonable in 1969. The thing was, in fact, a teletypewriter.

The teletypewriters are long gone. So are the VT100s. Nobody has hammered a Unix command onto a paper roll in decades. And yet the word tty is everywhere in modern Linux, used with a completely straight face, as though the clattering machine were still bolted to the wall. The kernel calls your terminal a tty. The command that tells you which terminal you're on is named tty. The column in ps and who that shows your terminal is headed TTY. You stare at a GPU-accelerated, full-colour, smooth-scrolling glass emulator running on a laptop that didn't exist in 1969, and the operating system underneath it insists, every single day, that you are typing on a teletype.

That's the ghost worth keeping in mind as we go on. In Linux, "tty" means a terminal — but specifically it means the terminal as the kernel sees it: a device. Not the window on your screen (that's the emulator, a user-space program), but the kernel-level object that represents a terminal and handles the line discipline — the buffering, the echoing of your keystrokes, the special keys. Every terminal, real or emulated, has a tty device behind it inside the kernel, and that device is where a surprising amount of the magic actually happens.

How It Works: Real TTYs and Pseudo-Terminals

To make this concrete, let's open the hood. In Linux, everything is a file — that idea you'll meet again and again — and terminals are no exception. Each tty shows up as a device file under /dev, and there are two flavours: the real ones and the fakes.

Real TTYs

A handful of actual terminal devices still exist, descendants of the physical hardware. On a Linux box, switch to a text console (the screen you get before any graphical desktop loads, reachable with Ctrl-Alt-F1 through F6) and you're on a virtual console — the kernel's built-in terminal, drawn directly onto the screen with no emulator program involved. These live at /dev/tty1, /dev/tty2, and so on:

ls /dev/tty[0-9]*
/dev/tty0  /dev/tty1  /dev/tty2  /dev/tty3  /dev/tty4  /dev/tty5  /dev/tty6 ...

These are as close to "real terminals" as a modern machine has — the kernel itself manages them, soup to nuts. /dev/tty0 is special: it always points at whichever virtual console is currently visible. There's also the bare /dev/tty, a magic alias that means "my own controlling terminal, whatever it happens to be" — a program can open /dev/tty and reach the user directly even when its normal input and output have been redirected elsewhere. That's the trick ssh and sudo use to prompt you for a password even inside a pipeline.

Pseudo-Terminals (PTY/PTS)

Here's where the impersonation gets clever. When you open a terminal emulator — GNOME Terminal, or an SSH session — there is no physical teletype anywhere, and no virtual console either. So the kernel manufactures one out of thin air: a pseudo-terminal, abbreviated PTY (and sometimes PTS, for pseudo-terminal slave).

A pseudo-terminal comes in two halves, wired back-to-back inside the kernel. The master end is held by your terminal emulator (or by the SSH daemon); the slave end looks, to every program that touches it, exactly like a real terminal device — same behaviour, same special keys, same everything. The emulator writes your keystrokes into the master; they pop out of the slave as if a teletype had sent them. The shell writes its output into the slave; it pops out of the master and the emulator paints it on screen. The kernel sits in the middle, impersonating a 1969 typewriter so convincingly that the shell has no idea it isn't one.

The slave ends live under /dev/pts/ (the pseudo-terminal slave directory), numbered as they're created:

ls -la /dev/pts/
total 0
crw--w---- 1 arndt tty  136, 0 Jun 14 13:44 0
crw--w---- 1 arndt tty  136, 1 Jun 14 14:00 1
c--------- 1 root  root   5, 2 Jun 12 19:07 ptmx

Every terminal window and every SSH session you open gets a fresh /dev/pts/N. Open three terminal tabs and you've got /dev/pts/0, /dev/pts/1, /dev/pts/2. The ptmx device at the bottom is the pt master mux — the single factory device a program opens to be handed a brand-new master/slave pair. It's the assembly line that mints pseudo-terminals on demand.

So the next time you SSH into a server, picture what actually happens: the SSH daemon on the far side asks the kernel for a pseudo-terminal, gets a /dev/pts/N, and hands the slave end to your login shell. Your keystrokes travel from your laptop's emulator, through the encrypted SSH tunnel, into that pty's master, out its slave, and into the shell — which believes, to its dying breath, that you're sitting at a teletype in the next room.

The tty Command

Which one are you on right now? The tty command answers in one word:

tty
/dev/pts/0

That's it — it prints the device file of your current terminal. /dev/pts/something means you're in an emulator or an SSH session (a pseudo-terminal); /dev/tty1 (or similar) means you're on a real virtual console at the physical machine. If tty prints not a tty, your input isn't connected to a terminal at all — you're inside a pipe, a cron job, or a script with redirected input. That last case matters more than it sounds: a great many "it works when I type it but not from the script" bugs are programs that behave differently when they discover there's no terminal listening.

The Controlling Terminal and Job Control

Now we get to the part most tutorials never explain, the part that turns four mysterious keypresses into one clean idea. Ctrl-C, Ctrl-Z, and Ctrl-D are the terminal's doing — not the shell's.

It feels like the shell is in charge: you press Ctrl-C, the command stops, and you're back at the shell prompt, so surely the shell caught the keystroke? It didn't. Here's what really happens.

Every process you start is associated with a controlling terminal — the tty it was launched from. The kernel's terminal driver (the "line discipline" mentioned earlier) sits between your keystrokes and the program, and it watches for a few magic characters. When it sees one, it doesn't pass it through as text — it acts on it:

  • Ctrl-C sends a SIGINT (interrupt signal) to the foreground process group on that terminal. The program receives the signal and, by default, dies. The shell never saw the keystroke; the terminal driver turned Ctrl-C into a signal and delivered it.
  • Ctrl-Z sends SIGTSTPsuspend. The program freezes mid-flight and the shell gets it back as a stopped job, which you can resume with fg or push to the background with bg. This is job control, and it lives in the terminal.
  • Ctrl-\ sends SIGQUIT — like Ctrl-C but ruder, and it usually drops a core dump. The escape hatch when Ctrl-C is being ignored.
  • Ctrl-D is subtler and gets misunderstood constantly. It is not a signal. It's end-of-input — it tells the terminal driver "the input is finished." A program reading from the terminal gets an end-of-file, exactly as if it had reached the end of a file. At a shell prompt with nothing typed, end-of-input means "no more commands," so the shell exits and you're logged out. That's why Ctrl-D logs you off: you didn't send a "quit" command, you closed the input stream, and the shell took the hint.

This is why these keys work the same in bash, in Python's interactive prompt, in cat reading from the keyboard, in anything: they aren't features of those programs at all. They're features of the terminal, applied uniformly to whatever happens to be the foreground process. The line discipline is doing the work, every time, no matter what's running.

Pro Tip

When a key combination seems "stuck" — Ctrl-C won't kill a wedged program, the screen is showing garbage, your typing doesn't echo — the terminal's line discipline has usually been left in a weird state by a program that crashed before tidying up. The fix is reset, which reinitialises the terminal to sane defaults. If even that's hard to type because nothing's echoing, type it blind and press Enter; it works far more often than people expect. The runner-up is stty sane.

You can see and change every one of these settings with stty, which configures the terminal driver directly:

stty -a
speed 38400 baud; rows 50; columns 204; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; ...

There it is in black and white: intr = ^C (the interrupt key is Ctrl-C), eof = ^D (end-of-file is Ctrl-D), erase = ^? (backspace). These aren't hard-wired — they're settings on the tty, and stty can change them. The historical curiosity that backspace is sometimes ^? and sometimes ^H, and that getting it wrong leaves you unable to delete characters over an old SSH link, is precisely a stty question with a stty answer.

Who's On Which Terminal

On a shared box, two questions nag at you: who's actually here, and — since anyone logged in can write straight to your terminal — who could be typing at you? Both answers hang off the tty. Because every logged-in session has one, you can see exactly who's connected and where. who lists the sessions:

who
arndt    seat0        2026-06-12 19:10
arndt    tty1         2026-06-12 19:10

The second column is the tty. Someone on tty1 is at the physical console; someone on pts/3 came in over the network (SSH). For a richer picture, w adds what each user is doing:

w
 14:03:31 up 1 day, 18:55,  1 user,  load average: 0.48, 0.88, 0.77
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU  WHAT
arndt    tty1     -                Fri19   42:54m  0.13s  0.13s /usr/bin/startplasma-wayland

The TTY column again, plus FROM (the remote address for network logins — a dash for a local console), how long they've been idle, and the command they're running. On a shared server, w is the fastest "who else is here and what are they up to" you have. And the same TTY column shows up in ps, where a ? means "no controlling terminal" — that's how you spot daemons and background services, which deliberately detach from any terminal so they keep running after the session that started them logs out.

Backstory

The reason a runaway log message can sometimes flash across another user's screen is buried in this same history. On the old hardware, a terminal was a physical device anyone with write access could send characters to, and the write and wall commands still do exactly that — they write straight to another user's tty device file. It's why your session can be interrupted by a broadcast "system going down in 5 minutes," and why mesg n (which revokes write permission on your tty) exists. The kernel still treats your glass emulator as a device that other people can, with permission, type onto from across the machine.

Cheat Sheet

The moves and concepts worth keeping at hand:

# --- Which terminal am I on? ---
tty                      # print my terminal device, e.g. /dev/pts/0
                         # "not a tty" => input isn't a terminal (pipe/cron/script)

# --- Who else is connected, and where ---
who                      # users + their ttys
w                        # users + ttys + what they're running + idle time
ps -o pid,tty,cmd        # the TTY column; "?" means no controlling terminal (a daemon)

# --- Terminal settings (the line discipline) ---
stty -a                  # show every terminal setting (intr, eof, erase, size...)
stty sane                # restore sane defaults after a program mangles them
reset                    # full reinit when the screen is wedged / garbled
stty size                # rows and columns of the current terminal

# --- Inspect the device files ---
ls /dev/pts/             # one entry per emulator/SSH session
ls /dev/tty[0-9]*        # the real virtual consoles (physical machine)
echo $TERM               # the terminal *type*, e.g. xterm-256color

Key keystrokes, all handled by the terminal driver (not the shell):

Keys What the terminal does Mechanism
Ctrl-C Interrupt the foreground program sends SIGINT
Ctrl-Z Suspend it (resume with fg/bg) sends SIGTSTP
Ctrl-\ Quit, usually with a core dump sends SIGQUIT
Ctrl-D End of input (empty prompt → logout) closes the input stream (EOF)
Ctrl-U Erase the whole line you're typing line-edit (kill)
Ctrl-L Clear the screen redraw

The TERM Variable and Terminfo

One more piece, because it explains the garbage characters. A program that wants to do anything beyond plain text — move the cursor, paint colours, draw a top-style live display — needs to send control codes, and different terminals understood different codes. A VT100 took one set; an old ADM-3A took another. So how does a program know which dialect to speak?

It reads the TERM environment variable:

echo $TERM
xterm-256color

TERM names your terminal's type, and the system keeps a database called terminfo describing what each type can do and which codes trigger it. When top wants to move the cursor to the top-left, it looks up "how does an xterm-256color move the cursor" in terminfo and emits exactly those bytes. Your emulator claims to be an xterm (or xterm-256color) because that dialect is the lingua franca every modern emulator implements — a 1980s terminal type that became the universal standard, the same way the VT100 was before it.

This is also the root of a classic frustration: SSH into an old box whose terminfo database doesn't list your fancy TERM, and suddenly your editor's arrow keys spew letters and the screen redraws wrong. The remote program can't find your terminal's dialect, so it guesses, and guesses badly. The fix is usually to fall back to a TERM the remote box does know — TERM=xterm ssh oldbox — trading a few fancy capabilities for one both ends agree on. It's the same negotiation the VT100 and the mainframe did over a serial cable in 1978, just with the cable replaced by an encrypted tunnel.

History and Philosophy

The whole arc of this page is a single, slightly absurd act of preservation, and it's worth stepping back to admire it.

The teletypewriter wasn't invented for computers at all. It was a telegraphy device — a typewriter that could send and receive text over a wire — and it predates the electronic computer by decades. When the first interactive computers arrived in the 1960s, the teletype was simply the input/output device already lying around: a keyboard to type on, a printer to read the replies from, a wire in between. So computing borrowed it wholesale, abbreviation and all. The Unix abstraction of "a tty" was modelled on the real, physical Model 33 Teletype that sat next to the PDP-11 — and that machine left a fingerprint you press with your thumb every single day. At the end of a line the Model 33 flung its print carriage bodily back to the left margin, a real mechanical lunge, and the key that gave the order is the same broad key you still hit to send a chat message or fire off a search. It's why Apple stamps it, to this day, not "Enter" but "Return": return the carriage. The carriage was scrapped long ago; the command to slam it home sits under your hand right now.

Then the hardware evolved out from under the abstraction — paper gave way to phosphor (the VT100 and its kin), phosphor gave way to pixels (the X terminal, then the software emulator), the serial cable gave way to TCP/IP and SSH — but at every step, the abstraction held. Each new technology was built to look, to the software above it, exactly like the teletype it replaced. The genius and the comedy of it are the same thing: rather than redesign the interface every time the hardware changed, Unix kept the old interface and taught each new device to wear its costume. The pseudo-terminal is the purest expression of that — a terminal made entirely of software, impersonating a device that itself impersonated a typewriter that impersonated a telegraph.

The payoff is staggering compatibility. Software written in 1975 to talk to a teletype runs, unmodified, in your GPU-accelerated terminal in 2026, because every layer in between agreed to keep pretending. It is, like a great deal of Unix, an accident of history that turned out to be quietly perfect engineering. And it means that when you read /dev/pts/0 or watch ^C interrupt a command, you're not using a quaint legacy feature — you're touching a fifty-year unbroken chain of abstractions, each one politely lying to the next so that your keystrokes still find their way home.

There's a lovely smallness to where the thread ends, too. Pull on tty — just the three letters — and it unwinds through pseudo-terminals, line disciplines, signals, the VT100, the Model 33 Teletype, telegraphy, and out the far end into the nineteenth century. The window you stare at all day is the visible tip of that. Not bad for a word that means "teletypewriter" on a machine that has never seen one.

See Also

  • shell — the program that runs inside the terminal and reads your commands
  • signal — what Ctrl-C and Ctrl-Z actually send to a process
  • process — what the terminal's controlling-terminal and job control act upon
  • ssh — how a remote session gets its own pseudo-terminal across the network
  • stdin — the input stream the terminal feeds, and what Ctrl-D closes
  • stdout — the output stream the terminal paints back onto the glass
  • linux — the kernel that manufactures every tty and pty on the box
  • unix — where the teletype, the tty, and the whole abstraction began
  • tty — print which terminal device you're on
  • stty — read and change the terminal's line-discipline settings
  • who — who's logged in, and on which tty
  • w — the same, plus what each session is doing

Garbled screens, a wedged session, and four magic keys you can't quite explain?

CleverUptime watches the things underneath the terminal that actually decide whether a server is healthy — load, CPU, memory, swap, disk, temperature, the processes doing the real work — and tells you in plain language what each reading means, so you spend your terminal time fixing problems instead of decoding them.

Want to see your own server's health right now? One command, no signup, no install.

Check your server →