The Three Streams

Every Linux program has three standard streams. Understanding them unlocks the power of piping and redirection.

The Three Streams

StreamNumberPurpose
stdin0Standard input - where data comes in
stdout1Standard output - where results go
stderr2Standard error - where errors go

Think of them as:

  • stdin = your keyboard (by default)
  • stdout = your screen (by default)
  • stderr = also your screen (by default)
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│    ┌──────────┐      ┌─────────────┐      ┌──────────┐     │
│    │  stdin   │ ───→ │   COMMAND   │ ───→ │  stdout  │     │
│    │   (0)    │      │             │      │   (1)    │     │
│    │ keyboard │      │  ls, grep,  │      │  screen  │     │
│    └──────────┘      │  cat, etc.  │      └──────────┘     │
│                      │             │                        │
│                      │             │ ───→ ┌──────────┐     │
│                      │             │      │  stderr  │     │
│                      └─────────────┘      │   (2)    │     │
│                                           │  screen  │     │
│                                           └──────────┘     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

By default, all three are connected to your terminal. Redirection changes where they go.

stdout - Standard Output

Normal output from commands:

Terminal
$ls
Documents Downloads projects
$echo 'hello'
hello

This is stdout - the successful result.

stderr - Standard Error

Error messages go to stderr:

Terminal
$ls /nonexistent
ls: cannot access '/nonexistent': No such file or directory
$cat missing.txt
cat: missing.txt: No such file or directory

Both appear on screen, but they're separate streams.

Why Separate Streams?

Because you might want to:

  • Save output to a file but see errors on screen
  • Discard errors but keep output
  • Log errors separately from results

stdin - Standard Input

Commands can read from stdin:

Terminal
$cat
(waits for your input... type something, then Ctrl+D)

When you type and press Enter, cat reads from stdin and writes to stdout.

Demonstrating the Difference

Terminal
$ls Documents /nonexistent
ls: cannot access '/nonexistent': No such file or directory Documents: file1.txt file2.txt

Here:

  • Documents: list goes to stdout
  • Error message goes to stderr

Both appear on screen, but they traveled different paths.

File Descriptors

Those numbers (0, 1, 2) are file descriptors. You'll use them for redirection:

hljs bash
# Redirect stdout (1) to file
command > output.txt
command 1> output.txt    # Same thing

# Redirect stderr (2) to file
command 2> errors.txt

# Redirect both
command > output.txt 2> errors.txt

Why This Matters

Consider this script running in production:

hljs bash
./backup.sh > backup.log 2> errors.log
  • Normal progress messages → backup.log
  • Any errors → errors.log

You can check errors.log to see if anything went wrong, without wading through thousands of success messages.

Redirecting stderr to stdout

Sometimes you want both in the same place:

hljs bash
command > all.log 2>&1

2>&1 means "send stderr (2) to wherever stdout (1) is going."

Order Matters

hljs bash
command > file 2>&1    # Correct - stderr follows stdout to file
command 2>&1 > file    # Wrong - stderr goes to terminal, stdout to file

The order is crucial.

Modern Syntax

Bash 4+ has a shortcut:

hljs bash
command &> all.log     # Both stdout and stderr to file
Knowledge Check

If you want to save command output but see errors on screen, what would you use?

Key Takeaways

  • Every command has 3 streams: stdin (0), stdout (1), stderr (2)
  • By default, both stdout and stderr display on screen
  • They're separate so you can handle them differently
  • File descriptors (0, 1, 2) let you redirect each stream
  • 2>&1 sends stderr to wherever stdout is going
  • Understanding streams is crucial for scripting and automation

Next: redirecting output to files.