Bash Scripting Fundamentals
Bash scripting transforms repetitive manual tasks into reliable, automated processes. As a sysadmin, the most valuable scripts you write are not fancy programs — they are simple, readable sequences of commands that run consistently without human attention. A well-written 20-line bash script that creates user accounts, configures firewall rules, and sends a confirmation email saves hours of manual work every week and eliminates human error.
Why bash scripting for sysadmins?
Bash scripting use cases for sysadmins:
Automation: deploy apps, configure servers, create users
Monitoring: check disk space, alert on high load, watch log files
Maintenance: rotate logs, clean temp files, backup databases
Reporting: daily system summaries, resource usage reports
Integration: chain tools together, parse command output, call APIsScript structure and variables
nano /usr/local/bin/backup-check.sh
backup-check.sh — basic script structure
#!/bin/bash
# Always start with shebang — tells OS which interpreter to use
# Use set -euo pipefail for safer scripts:
set -e # Exit immediately if any command fails
set -u # Treat unset variables as errors
set -o pipefail # Catch pipe failures (cmd1 | cmd2 — if cmd1 fails, fail the script)
# Variables:
BACKUP_DIR="/var/backups/daily"
RETENTION_DAYS=7
DATE=$(date +%Y-%m-%d) # Command substitution
BACKUP_FILE="${BACKUP_DIR}/backup-${DATE}.tar.gz"
# Quote variables to handle spaces:
echo "Creating backup: ${BACKUP_FILE}"
# Read-only constants:
readonly LOG_FILE="/var/log/backup.log"
# Logging function (used throughout):
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${LOG_FILE}"
}
chmod +x /usr/local/bin/backup-check.sh
/usr/local/bin/backup-check.sh
Conditionals and loops
nano /usr/local/bin/disk-alert.sh
disk-alert.sh — conditionals and loops
#!/bin/bash
set -euo pipefail
THRESHOLD=85
ALERT_EMAIL="admin@example.com"
# Loop over all mounted filesystems:
while IFS= read -r line; do
# Parse df output:
usage=$(echo "$line" | awk '{print $5}' | tr -d '%')
mountpoint=$(echo "$line" | awk '{print $6}')
# Conditional check:
if [[ "$usage" -gt "$THRESHOLD" ]]; then
echo "ALERT: ${mountpoint} is ${usage}% full" | mail -s "Disk Alert on $(hostname)" "${ALERT_EMAIL}"
echo "Sent alert for ${mountpoint}: ${usage}%"
fi
done < <(df -h | tail -n +2) # Process substitution: feed df output as input
# Common conditional patterns:
# [[ -f /path/file ]] → file exists
# [[ -d /path/dir ]] → directory exists
# [[ -z "$var" ]] → variable is empty
# [[ -n "$var" ]] → variable is non-empty
# [[ "$a" == "$b" ]] → string equality
# [[ "$n" -gt 100 ]] → numeric greater than
Functions and arguments
nano /usr/local/bin/create-user.sh
create-user.sh — functions and argument handling
#!/bin/bash
set -euo pipefail
# $0 = script name, $1 = first arg, $2 = second arg, $# = arg count
usage() {
echo "Usage: $0 "
echo "Example: $0 irfan developers"
exit 1
}
# Validate argument count:
if [[ $# -ne 2 ]]; then
usage
fi
USERNAME="$1"
GROUP="$2"
create_user() {
local username="$1" # local = scoped to function
local group="$2"
if id "${username}" &>/dev/null; then
echo "User ${username} already exists"
return 0
fi
useradd -m -G "${group}" -s /bin/bash "${username}"
passwd "${username}"
echo "Created user: ${username} in group: ${group}"
}
create_user "${USERNAME}" "${GROUP}"
sudo /usr/local/bin/create-user.sh irfan developers
Conclusion
The three most important bash scripting practices: always start scripts with set -euo pipefail so failures are caught immediately rather than silently continuing; quote every variable as "${var}" to handle spaces and special characters; and add a usage() function with argument validation so scripts fail loudly with a helpful message rather than failing mysteriously mid-execution. A script that catches its own errors is far more valuable than one that silently does the wrong thing.
FAQ
Why should administrators understand Bash Scripting Fundamentals?+
Because this topic affects planning decisions, server lifecycle, compatibility, support expectations, or how you reason about Ubuntu systems before making operational changes.
Do I need a lab for this topic?+
A lab is useful for checking commands and seeing the concept on a real Ubuntu machine, but the main value is understanding the decision, tradeoff, or system behavior clearly.
How should I use this knowledge in production?+
Use it to make better choices, document why those choices were made, and avoid rushed changes that ignore support windows, compatibility, stability, or operational risk.
Need help with Ubuntu administration?
Work directly with Muhammad Irfan Aslam for Ubuntu Server, Linux, cloud, Docker, DevOps, CI/CD, or infrastructure troubleshooting support.
Hire Me for Support