Skip to main content

Linux Shell Scripting

Automate repetitive tasks and build powerful scripts with Bash. Shell scripting is the duct tape of system administration — it is how you turn a sequence of commands you type repeatedly into something the machine does for you. Every DevOps pipeline, every deployment script, every monitoring check started as a shell script.

Basic Script Structure

Every Bash script starts with a shebang line that tells the system which interpreter to use.
Best practice: Always start scripts with set -euo pipefail right after the shebang. This combination catches most common bugs: -e exits on any error, -u treats unset variables as errors, -o pipefail catches failures in piped commands. Without this, scripts silently continue after errors, which is how you accidentally delete the wrong directory.

Variables

Always quote your variables: Use "$VAR" not $VAR. Without quotes, a variable containing spaces gets split into multiple words, causing subtle bugs. For example, rm $FILE where FILE=“my report.txt” tries to delete “my” and “report.txt” separately. rm "$FILE" does the right thing.

Conditionals

Bash conditionals test exit codes. In Linux, an exit code of 0 means success (true), and anything else means failure (false). This is the opposite of most programming languages.

File and String Tests

Modern Test Syntax


Loops

Gotcha with for loops and files: If no files match a glob pattern like *.txt, bash passes the literal string “*.txt” to the loop. Protect against this with shopt -s nullglob at the top of your script, which makes unmatched globs expand to nothing instead.

Functions

Functions let you organize code into reusable blocks. They are essential once your script grows beyond 20-30 lines.

Practical Script: Deployment Example

Here is a realistic script that ties together variables, conditionals, functions, and error handling. This is the kind of script you would actually use in production — notice how every step validates its preconditions, logs what it does, and has a path for failure.
What makes this production-ready: (1) It validates inputs before doing anything destructive. (2) It creates a backup before overwriting. (3) It uses retries for the health check instead of a single fixed sleep. (4) It rolls back automatically on failure. A script without rollback capability is a script you will regret running at 2 AM.

Cron Jobs

Cron is the Linux scheduler. It runs scripts at specified times, unattended. Think of it as setting an alarm for your server.
Common cron pitfalls: (1) Cron runs in a minimal environment — your $PATH is different from your interactive shell, so use full paths to commands (/usr/bin/python3 not just python3). (2) Always redirect output to a log file (>> /var/log/myscript.log 2>&1), otherwise cron sends email for every run. (3) Cron does not load your .bashrc — if your script depends on environment variables, source them explicitly.

Key Takeaways

  • Start every script with #!/bin/bash and set -euo pipefail
  • Always quote variables ("$VAR") to handle spaces and special characters safely
  • Use local in functions to avoid polluting the global scope
  • Test files with -f, -d, -r, -s before operating on them
  • Use [[ ]] (double brackets) instead of [ ] for safer, more powerful tests
  • Cron runs in a minimal environment — use full paths and redirect output
  • Write logs with timestamps in production scripts so you can trace what happened

Congratulations — you have completed the Linux Crash Course. Next: Docker Crash Course →