Bash Scripting: Why Just Typing Commands Isn’t Enough?
Three years ago, I spent an entire night manually typing backup commands for 10 production VPS instances. Back then, I only knew how to use history and copy-paste. Disaster struck when I accidentally typed a space after rm -rf /. Luckily, I stopped in time, but that moment was enough for me to realize: if you want to advance in your Linux career, automation is mandatory.
Which Tool Should You Choose for Automation?
When a task repeats more than three times, you should stop manual typing. Generally, we have a few options:
- Manual Commands: Fast for one-time tasks. However, it’s a “nightmare” if you need to execute them on 20 servers simultaneously.
- Using Aliases: Great for short commands like
alias ll='ls -la'. But Aliases cannot handle complex logic orif-elseconditions. - Bash Script: The most balanced choice. It runs natively on every Linux distro without needing extra installations like Python or Node.js.
- Ansible/Terraform: Extremely powerful for large infrastructure. But if you just want to quickly check disk space, they are way too bulky.
Why You Should (and Shouldn’t) Use Bash?
Pros:
- 100% available on Ubuntu, CentOS, or even the ultra-lightweight Alpine.
- Interacts with files and system processes with near-zero latency.
- Every error you encounter has likely had an answer on StackOverflow from 10 years ago.
Cons:
- Bash syntax is full of “pitfalls” regarding whitespace.
- Debugging can sometimes be more frustrating than in high-level languages.
- Easy to turn into a mess of spaghetti code if you’re too lazy to use functions.
4 Steps to Build “Production-Ready” Scripts
To avoid scripts running wild and deleting the wrong data, I always apply the following 4-step process.
1. Always Use Shebang and Variables
The #! /bin/bash line at the top of the file is mandatory. It tells the system exactly which interpreter to use. Additionally, always use clear variable names instead of hard-coding values.
#!/bin/bash
# Always capitalize environment variable names for easier management
BACKUP_DIR="/var/backups/nginx_logs"
CURRENT_USER=$(whoami)
echo "Hello $CURRENT_USER, system starting backup into $BACKUP_DIR"
2. Controlling Conditions (Conditionals)
In Bash, double square brackets [[ ]] are more flexible than the single [ ] variety. One ironclad rule: always leave whitespace around the brackets. Without it, your script will stop working immediately.
if [[ ! -d "$BACKUP_DIR" ]]; then
echo "Directory does not exist. Initializing..."
mkdir -p "$BACKUP_DIR"
else
echo "Directory already exists, continuing process."
fi
3. Optimization with Loops
Suppose you need to compress 50 old log files to free up 80% of disk space. A for loop will handle this in less than 2 seconds.
# Compress all .log files in the current directory
for log_file in *.log; do
echo "Compressing: $log_file"
tar -czf "${log_file}.tar.gz" "$log_file"
done
4. Encapsulate Code into Functions
If you find yourself writing echo too many times to notify status, create a separate log function. This keeps your code cleaner and much easier to maintain.
notify() {
local status=$1
local msg=$2
echo "[$(date +'%H:%M:%S')] [$status] $msg"
}
notify "INFO" "Script is starting..."
notify "ERROR" "Database not responding!"
Error Handling Techniques to “Survive” on Production
A great script differs from a beginner script in how it handles failure. A small mistake in a backup script can result in total data loss if you don’t check for errors.
The Power Trio: set -euo pipefail
I always add this line right after the Shebang. It’s “insurance” for every script:
-e: Stop the script immediately if any command fails.-u: Report an error if you call an undeclared variable.-o pipefail: Catch errors even when they occur behind a pipe|.
Checking the Exit Code ($?)
After critical commands like rsync or mysqldump, check the $? variable. A value of 0 means success; otherwise, there’s a problem.
rsync -avz /src/ /dest/
if [[ $? -ne 0 ]]; then
echo "Sync error! Check your network connection."
exit 1
fi
Closing Thoughts from Real-World Experience
Writing Bash isn’t hard; writing it safely is. After years of operation, I’ve come to one rule: Always test your scripts in a Staging environment. Never fully trust what you’ve just typed.
If a script exceeds 500 lines, it’s time to switch to Python. But for daily sysadmin tasks, Bash remains “king.” Start with small scripts, and you’ll see your productivity increase significantly.

