Linux and networking
Shell pipes and streams
How programs talk through stdin, stdout and stderr, and how pipes chain small tools into one answer to a production question.
Most Linux tools do one small job and hand their results to the next tool. They talk through three streams: stdin (input), stdout (normal output) and stderr (error messages). Every program also ends with an exit code: 0 means success, anything else means failure. A pipe, written |, connects one program's stdout to the next program's stdin.
Walking through it
Say an incident is in progress and you need to know which client IPs are getting server errors. The nginx access log has the answer on each line.
awk '$9 >= 500 {print $1}' /var/log/nginx/access.log \
| sort | uniq -c | sort -rn | head -10Each stage does one step:
awkkeeps lines whose field 9 (the status code) is 500 or higher, and prints field 1 (the client IP).sortputs identical IPs next to each other.uniq -ccounts each group. It only merges adjacent lines, which is why the sort comes first.sort -rnorders the counts from highest to lowest.head -10keeps the top ten.
The output has one line per IP. Addresses below are invented to show the shape:
412 203.0.113.9
87 198.51.100.23
12 192.0.2.44Redirection in one table
| Syntax | Meaning |
|---|---|
cmd > file | Write stdout to a file, replacing it |
cmd >> file | Append stdout to a file |
cmd 2> err.log | Write stderr to a file |
cmd > out.log 2>&1 | Send stderr to the same place as stdout. Order matters. |
cmd1 && cmd2 | Run cmd2 only if cmd1 succeeded |
cmd1 || cmd2 | Run cmd2 only if cmd1 failed |
The text tools
- grep finds lines.
grep -rn "timeout" src/searches folders and prints line numbers. - awk works on columns.
awk -F, '{sum += $3} END {print sum}' sales.csvadds up the third CSV column. - sed edits streams.
sed -n '100,120p' fileprints lines 100 to 120. - jq does the same job for JSON.
jq -r 'select(.level == "error") | .ts[0:16]' app.log | sort | uniq -ccounts errors per minute, if each line is a JSON log record with an ISO timestamp. - find and xargs handle files in bulk. Use
-print0and-0so filenames with spaces don't break the pipeline.
Common mistakes
- Skipping the sort before
uniq -c. The counts look wrong because equal lines weren't adjacent. - Using
sed -i 's/old/new/'on macOS. BSD sed needssed -i ''. The GNU form fails with a confusing error. - Forgetting
-print0withxargs. A file namedmy log.txtsplits into two arguments. - Trusting a pipeline that failed halfway. Only the last stage's exit code counts unless you set
pipefail. See safe bash scripts.
Check yourself
- Why does
uniq -cneedsortfirst? Becauseuniqonly merges lines that sit next to each other. - In
cmd > out.log 2>&1, where does an error message end up? Inout.log, because2>&1sends stderr to wherever stdout goes.
Key takeaways
- Small tools connected by pipes answer most log questions in one line.
- Stdout is for results, stderr is for errors, and the exit code is the signal scripts read.
sortbeforeuniq, and-print0beforexargs -0, prevent the two most common wrong answers.
Further learning
Next, learn how these programs run as processes and how signals stop them, in processes and signals.
The Missing Semester of Your CS Education (MIT)Master powerful tools that will make you a more productive computer scientist and programmer.Missing Semester
Related
Linux for engineers
The parts of Linux you touch in production, from shell pipelines and systemd services to permissions, disks, network debugging commands and safe remote access.
Safe bash scripts
Bash fails quietly by default. A few lines at the top of every script turn unset variables and hidden failures into loud errors.
Processes and signals
What a process is, how to read its state, and how signals and exit codes tell you why it stopped. Exit 137 and 143 come up constantly.