Chapter Eleven

Shell Scripting

From a shebang line to a cron entry: writing bash that runs unattended on a server and fails loudly when it should.

6 topics

Shell scripting is the glue that holds a Linux server together. Backups, log rotation, deployment hooks, health checks, and one-off data fixes all end up as a .sh file at some point, and most of them run with no human watching. That changes the priorities: a script you run by hand can get away with sloppy error handling because you see the output, but a script wired into cron or a systemd timer has to decide on its own what counts as success and what counts as failure.

This chapter builds bash in the order you actually need it. You start with how a script is structured and how the kernel decides to execute it, then variables and arguments, then the control flow — conditionals, loops, and functions — that turns a list of commands into a program. The last two topics are what separate a script that works on your laptop from one you trust in production: rigorous exit-code and error handling, and scheduling the finished script with cron. Examples are bash on Debian and Ubuntu throughout; where /bin/sh (dash) differs from bash, the topic pages call it out.

What makes a script reliable
#!/usr/bin/env bashthe shebang
set -euo pipefailstrict mode
quote + checkdefensive logic
trap ... EXITcleanup
exit Nmeaningful status

Topics in This Chapter

Topic 58
Script Structure and Execution
The shebang line that picks the interpreter, the execute bit that makes a file runnable, and the difference between ./script.sh, bash script.sh, and source. Why #!/bin/bash and #!/bin/sh are not the same interpreter on Debian.
ScriptingExecution
Topic 59
Variables and Arguments
Assigning and quoting variables, why "${VAR}" beats a bare $VAR, and reading positional arguments $1, "$@", and $#. Command substitution and why unquoted expansions break on filenames with spaces.
ScriptingVariables
Topic 60
Conditionals and test
Branching built on exit codes: if runs a command and acts on its status. The [ ], test, and bash [[ ]] operators for comparing strings, numbers, and files, and why [[ ]] avoids the quoting traps of POSIX [ ].
ScriptingControl Flow
Topic 61
Loops and Functions
Iterating with for, while, and until, reading a file line by line without mangling whitespace, and factoring repeated logic into functions with local variables and return codes.
ScriptingControl Flow
Topic 62
Exit Codes and Error Handling
Reading $?, the set -euo pipefail strict mode and its blind spots, and trapping failure with trap cleanup EXIT to remove temp files and locks. How to make an unattended script fail fast instead of corrupting data.
ScriptingReliability
Topic 63
cron and Scheduled Tasks
The five-field crontab format, per-user versus system crontabs and /etc/cron.d, and why cron's minimal PATH and silently discarded output trip up scripts that worked in your shell. When to graduate to systemd timers or anacron.
SchedulingAutomation