Free — no signup required

Redirection and Output Control

3 min read

Controlling Where Data Goes

Every process in Linux is handed three standard data streams when it starts, each identified by a small integer called a file descriptor:

  • stdin (0): Standard input — where the process reads data from (usually your keyboard).
  • stdout (1): Standard output — where the process writes its normal output (usually your terminal).
  • stderr (2): Standard error — where the process writes error and diagnostic messages (also usually your terminal, but as a genuinely separate stream from stdout).

The key conceptual point is that stdout and stderr are two independent channels that simply both happen to display on your terminal by default — a program's normal output and its error output are never mixed together at the source, only at whatever destination both streams happen to be pointed at. Redirection is the shell disconnecting one of these streams from the terminal and pointing it somewhere else instead — a file, /dev/null, or another process's stdin — which is only possible because the streams were independent to begin with.

Because stdout and stderr are separate, they can be redirected independently: capture only normal output to a log while errors still surface on screen, capture only errors while normal output stays visible, or send each to its own file. Redirecting both streams to the same place is a distinct operation from redirecting either alone — informally, "point stderr at wherever stdout currently goes." Order matters here in a way that trips people up: the shell processes redirections left to right, rebinding one file descriptor at a time, so pointing stderr at stdout only makes it inherit whatever stdout is bound to at that point in the command. Writing that step before redirecting stdout itself captures nothing useful, because stderr gets bound to the terminal (stdout's binding at that moment) before stdout is ever redirected to a file.

This is not an academic distinction. It is the single most common cause of a "successful" cron job or CI step that actually failed silently: the script's own exit code was 0, but the actual error message went out over stderr and was never captured anywhere, because whoever wrote the logging only redirected stdout.

tee — see output live and keep a permanent record

Redirecting a stream to a file normally means you stop seeing it on screen — file and terminal are exclusive destinations. tee breaks that trade-off: it reads from its own stdin and duplicates everything it receives to two destinations at once, your terminal and a file. For long operational tasks, this is what lets you watch progress live while still keeping a record to consult afterward.

/dev/null — the black hole

/dev/null is a special device file that silently discards anything written to it and returns nothing (immediate end-of-input) when read from. It exists specifically as a destination for output you have no use for — a way to explicitly say "I know this stream exists and I am deliberately discarding it," rather than letting unwanted output clutter a terminal or bloat a log file no one will ever read.

Understanding redirection — and specifically that stdout and stderr are separate streams that must each be accounted for — is what separates engineers who write robust automation from those who only run interactive commands, where a mixed, on-screen view of both streams is good enough.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free