Skip to Content
Navigation:

A stick figure smiling

Here's a preview from my zine, The Secret Rules of the Terminal! If you want to see more comics like this, sign up for my saturday comics newsletter or browse more comics!

Image of a comic. To read the full HTML alt text, click "read the transcript". get the zine!
read the transcript!

all terminal programs have 1 input and 2 outputs

they’re numbered: stdin is “0”, stdout is “1”, stderr is “2”.

Illustration of a program, represented by a box with a smiley face. There is an arrow labelled “0 IN” going into it, and arrows labelled “1 OUT” and “2 ERR” coming out of it.

(the numbers are called “file descriptors”)

3 things you can set the inputs/outputs to

  1. the TTY (so output is displayed in your terminal emulator)
  2. a file
  3. a pipe (to write output to the input of another program)

your shell is in charge of setting up stdin/stdout/stderr

tiny smiling tick figure: “python3 script.py > out.txt”

shell: “ok, I’ll set stdout to out.txt for that program”

when you redirect, the shell opens the file before the program starts

sudo echo blah > file.txt

shell, thinking: first i’ll open file.txt… THEN I’ll run sudo echo blah

this is why file.txt isn’t opened as root!

on 2>&1

2>&1 redirects stderr to stdout

The same illustration from the first panel, but with the addition of an arrow coming out from “2 ERR” and going into “1 OUT”.

you could also do echo "oops" 1>&2if you want to write a message to stderr in a script.

gotcha: programs often buffer stdout but not stderr

when a program writes text to stdout, it’ll often

  1. check if stdout is a TTY (using the isatty function)
  2. if not, “buffer” the writes until there’s 1KB of data to write, for performance reasons

(this is the default in libc)