Shell Scripting & Automation
Write safe, reusable Bash scripts and schedule them to run automatically.
Scripting converts repeated manual work into reliable, version-controlled automation. This chapter covers Bash fundamentals, defensive scripting practices, and scheduling with cron and systemd timers.
By the end of this chapter you will be able to
- Author Bash scripts with proper structure and a shebang.
- Use variables, parameters, conditionals, loops, and functions.
- Apply strict mode and exit-status checks for robustness.
- Schedule jobs with cron and systemd timers.
- Debug scripts methodically.
12.1 Script Basics
#!/bin/bash
# greet.sh — say hello
echo "Hello, $USER, today is $(date +%A)"
12.2 Variables and Parameters
name="$1" # first argument passed to the script
greeting=${2:-Hi} # second arg, defaulting to 'Hi'
echo "$greeting, $name"
# Run: ./greet.sh Ada Hello
12.3 Conditionals and Loops
# Does a file exist?
if [ -e /etc/app.conf ]; then
echo "config found"
else
echo "missing" >&2
fi
# Loop over files
for f in *.log; do
echo "processing $f"
done
12.4 Defensive Scripting
By default, Bash plods on after errors — dangerous for anything that changes files. Strict mode makes scripts stop the moment something goes wrong.
#!/bin/bash
set -euo pipefail
# -e exit on any error
# -u error on undefined variables
# -o pipefail a failed stage fails the whole pipe
12.5 Functions
log(){ echo "[$(date +%T)] $*"; }
backup(){ tar -czf "$1.tar.gz" "$1" && log "backed up $1"; }
backup /etc
12.6 Scheduling with cron and timers
cron runs jobs on a schedule. The five fields are minute, hour, day-of-month, month, day-of-week.
crontab -e
# Run a backup every day at 1:00 AM, logging output:
0 1 * * * /opt/backup.sh >> /var/log/backup.log 2>&1
# Modern alternative: systemd timers
systemctl list-timers
12.7 Guided Lab: A Safe, Scheduled Backup Script
Estimated time: 30 minutes. Write a strict-mode backup script that archives a folder with a timestamp, logs what it did, and schedule it.
- Create backup.sh starting with
#!/bin/bashandset -euo pipefail. - Accept the target folder as
$1; default the destination to /tmp/backups. - Build a timestamped archive name with
$(date +%F)and run tar -czf. - Add a log() function that prints a timestamped message; call it on success.
- Make it executable and test:
./backup.sh /etc. - Schedule it daily at 02:00 via crontab, redirecting output to a log file.
- Verify the cron line with
crontab -l.
Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
| ‘Permission denied’ running ./script.sh | Not executable. Run chmod +x script.sh. Also ensure the shebang path is correct. |
| Script works by hand but fails in cron | cron’s minimal PATH/environment. Use absolute paths and redirect output to a log to see the real error. |
| Script keeps going after an error | You didn’t enable strict mode. Add set -euo pipefail and check exit codes. |
| Filename with spaces breaks the script | Unquoted variable. Use “$var” everywhere a value could contain spaces. |
Practice & Prove It
Write-the-command drills
- Write the shebang line for a Bash script.
- Write a for-loop that prints the numbers 1 to 5 on one line each.
- Write an if-test that prints ‘missing’ when /etc/app.conf does not exist.
- Add the strict-mode safety line to a script.
- Write a crontab line that runs /opt/job.sh every day at 6:30 AM.
Quick quiz
- What does the shebang line do?
- Why quote “$variable”?
- What does set -euo pipefail improve?
- What are cron’s five time fields, in order?
- Why redirect cron job output to a log?
Key Takeaways
- A script is a file of commands with a #!/bin/bash shebang, made executable with chmod +x.
- Use quoted variables, positional parameters, conditionals, loops, and functions.
- set -euo pipefail makes scripts fail fast and safe — essential for unattended jobs.
- cron and systemd timers run scripts on a schedule; use absolute paths and log output.
- A silently-failing automation is worse than none — always check and log results.
Next — Chapter 13: performance tuning and monitoring.