The number every command leaves behind
Every Unix process exits with an integer in the range 0–255. The shell stores the most recent exit code in $?. By convention, 0 means success, anything non-zero means "something is off — and the number tells you what." This is the foundation of every && chain and every CI pipeline you'll ever debug.
Common codes
- 0 — success
- 1 — generic error (catch-all for unspecified failure)
- 2 — usage error (the user's flags didn't make sense)
- 126 — command found but not executable
- 127 — command not found
- 128 + N — terminated by signal N.
Ctrl+C(SIGINT = 2) gives 130;kill -9(SIGKILL = 9) gives 137.
Most well-written tools document their codes in the man page. grep uses 0 = match found, 1 = no match, 2 = error.
Chaining on success or failure
cmd1 && cmd2 runs cmd2 only if cmd1 succeeded. cmd1 || cmd2 runs cmd2 only if cmd1 failed. cmd1 ; cmd2 runs both regardless. Together they are a tiny if/else: ./test.sh && ./deploy.sh || echo "tests failed".
Returning your own codes
In a script, exit N ends the process with code N. In a function, return N sets $? for the caller. Always pick a non-zero code for failures — never silently exit 0 from an error path or your CI lies to you.
Pipeline exit codes
By default, a pipeline's exit code is the last command's. cat missing.txt | wc -l exits 0 even though cat failed. Add set -o pipefail in your scripts and the whole pipeline fails if any stage failed. The scripting track digs into this with set -euo pipefail.