Once you understand the basics of shell scripting, Bash provides many advanced features that allow you to write more powerful, flexible, and maintainable scripts. System administrators, DevOps engineers, and Linux professionals often rely on these features to automate complex tasks and manage large environments.
This tutorial introduces several advanced Bash scripting concepts, including functions, arrays, loops, case statements, command-line arguments, error handling, and automation techniques.
Understanding Script Exit Codes
Every Linux command returns an exit code.
A value of:
0
indicates success.
Any non-zero value indicates an error.
Example:
#!/bin/bash
mkdir testdir
echo $?
Output:
0
The special variable $? contains the exit code of the most recently executed command.
Using Conditional Execution
Execute commands based on success or failure.
Run a command only if the previous command succeeds:
mkdir backup && echo "Directory created"
Run a command only if the previous command fails:
mkdir backup || echo "Failed to create directory"
These operators are commonly used in automation scripts.
Writing Reusable Functions
Functions help organize scripts and reduce duplicated code.
Example:
#!/bin/bash
backup_file() {
cp "$1" "$1.bak"
}
backup_file report.txt
Functions can accept parameters using:
$1
$2
$3
just like regular scripts.
Returning Values from Functions
Example:
#!/bin/bash
show_date() {
date
}
current_date=$(show_date)
echo "$current_date"
This captures a function’s output into a variable.
Working with Arrays
Arrays store multiple values.
Example:
#!/bin/bash
distros=("Ubuntu" "Debian" "Fedora" "FreeBSD")
echo ${distros[0]}
Output:
Ubuntu
Display all elements:
echo ${distros[@]}
Output:
Ubuntu Debian Fedora FreeBSD
Loop through an array:
for distro in "${distros[@]}"
do
echo "$distro"
done
Using Case Statements
Case statements simplify multiple conditional tests.
Example:
#!/bin/bash
read -p "Choose an option: " option
case $option in
start)
echo "Starting service"
;;
stop)
echo "Stopping service"
;;
restart)
echo "Restarting service"
;;
*)
echo "Invalid option"
;;
esac
Case statements are often cleaner than long chains of if-else statements.
Processing Command-Line Arguments
A script can accept parameters when it is executed.
Example:
#!/bin/bash
echo "First argument: $1"
echo "Second argument: $2"
Run:
./script.sh Linux Bash
Output:
First argument: Linux
Second argument: Bash
Looping Through Arguments
Example:
#!/bin/bash
for arg in "$@"
do
echo "$arg"
done
Run:
./script.sh one two three
Output:
one
two
three
Reading Files Line by Line
Example:
#!/bin/bash
while read line
do
echo "$line"
done < users.txt
If users.txt contains:
alice
bob
charlie
Output:
alice
bob
charlie
This technique is commonly used in administrative scripts.
Redirecting Output
Save output to a file:
ls > files.txt
Append output:
date >> logfile.txt
Redirect errors:
ls missingfile 2> errors.txt
Redirect both output and errors:
command > output.txt 2>&1
Using Here Documents
A Here Document allows multiple lines of text to be passed into a command.
Example:
cat << EOF
Welcome to Linux
This text is generated
by a shell script.
EOF
Output:
Welcome to Linux
This text is generated
by a shell script.
Error Handling
Exit immediately when a command fails:
set -e
Example:
#!/bin/bash
set -e
mkdir backup
cp important.txt backup/
If any command fails, the script stops.
This helps prevent unexpected behavior.
Using Trap for Cleanup
The trap command executes code when a script exits.
Example:
#!/bin/bash
cleanup() {
echo "Removing temporary files"
rm -f temp.txt
}
trap cleanup EXIT
touch temp.txt
When the script ends, cleanup runs automatically.
Checking for Root Privileges
Many administrative scripts require root access.
Example:
#!/bin/bash
if [ "$EUID" -ne 0 ]
then
echo "Please run as root"
exit 1
fi
echo "Running as root"
Automating Backups
Example backup script:
#!/bin/bash
SOURCE="/home/user/documents"
DESTINATION="/backup"
rsync -av "$SOURCE" "$DESTINATION"
echo "Backup completed."
This uses rsync to synchronize files efficiently.
Parsing User Options
Example:
#!/bin/bash
while getopts "ab" option
do
case $option in
a)
echo "Option A selected"
;;
b)
echo "Option B selected"
;;
esac
done
Run:
./script.sh -a
Output:
Option A selected
The getopts command is commonly used in professional shell scripts.
Logging Script Activity
Example:
#!/bin/bash
LOGFILE="/var/log/myscript.log"
echo "$(date): Script started" >> "$LOGFILE"
This creates a persistent record of script activity.
Example System Information Script
#!/bin/bash
echo "Hostname: $(hostname)"
echo "Kernel: $(uname -r)"
echo "Memory:"
free -h
echo ""
echo "Disk Usage:"
df -h
This combines several Linux commands into a useful administrative tool.
Best Practices for Advanced Scripts
- Use meaningful variable names.
- Quote variables whenever possible.
- Validate user input.
- Check exit codes.
- Use functions to organize code.
- Log important actions.
- Handle errors gracefully.
- Test scripts in a safe environment.
- Comment complex logic.
Example:
# Verify backup directory exists
if [ ! -d "$BACKUP_DIR" ]
then
mkdir "$BACKUP_DIR"
fi
Real-World Uses of Advanced Bash Scripting
Advanced Bash scripts are commonly used for:
- System monitoring
- Automated backups
- User account management
- Log analysis
- Software deployment
- Server maintenance
- Security auditing
- Scheduled tasks using cron
Even in modern cloud environments, Bash scripting remains one of the most valuable skills for Linux administrators and DevOps engineers.
Conclusion
Advanced Bash scripting builds on the fundamentals of shell scripting by introducing functions, arrays, error handling, command-line processing, and automation techniques. These features enable administrators and developers to create powerful tools that automate complex tasks and improve system management. Mastering advanced Bash scripting is an important step toward becoming a proficient Linux user, system administrator, or DevOps professional.