Table of Contents
- What is Bash, and Why Automate with It?
- Bash Fundamentals: Building Blocks of Automation
- Advanced Bash Concepts
- Practical Automation Examples
- Best Practices for Bash Scripting
- Conclusion
- References
1. What is Bash, and Why Automate with It?
Bash is a command-line shell and scripting language developed as a free replacement for the original Bourne Shell (sh). It interprets commands typed into the terminal and can execute scripts—text files containing sequences of commands—to automate tasks.
Why Bash for Automation?
- Ubiquity: Bash is preinstalled on nearly all Linux and macOS systems, so scripts work across environments without extra dependencies.
- Simplicity: Bash scripts are plain text files, making them easy to write, edit, and debug with basic tools like
nanoorvim. - Integration: Bash seamlessly interacts with Linux core utilities (
grep,awk,sed,rsync, etc.), allowing you to combine powerful tools into workflows. - Speed: For system-level tasks (e.g., file operations, process management), Bash is often faster than interpreted languages like Python because it avoids startup overhead.
2. Bash Fundamentals: Building Blocks of Automation
2.1 Shebang: The Script Header
Every Bash script starts with a shebang line, which tells the system which interpreter to use. For Bash scripts, this is:
#!/bin/bash
Save your script with a .sh extension (e.g., my_script.sh), make it executable with chmod +x my_script.sh, and run it with ./my_script.sh.
2.2 Variables: Storing and Manipulating Data
Variables let you store and reuse data in scripts. Use = to assign values (no spaces around =), and $ to access them.
Example: Basic Variables
#!/bin/bash
name="Alice"
age=30
echo "Hello, $name! You are $age years old." # Output: Hello, Alice! You are 30 years old.
Key Notes:
- Quoting: Use double quotes (
" ") to expand variables (e.g.,"$name"). Single quotes (' ') treat text literally:echo 'Hello, $name' # Output: Hello, $name (no expansion) - Command Substitution: Capture output of a command into a variable with
$(command)or backticks (`command`):current_date=$(date +%Y-%m-%d) echo "Today is $current_date" # Output: Today is 2024-05-20 - Environment Variables: Predefined variables like
$HOME(your home directory),$PATH(executable search path), or$USER(current user):echo "Your home directory is $HOME" # Output: Your home directory is /home/alice
2.3 Input/Output Redirection and Pipes
Bash lets you redirect input/output (I/O) to/from files or chain commands with pipes (|).
Redirection:
>: Overwrite a file with output (e.g.,echo "Hello" > output.txt).>>: Append to a file (e.g.,echo "World" >> output.txt).<: Read input from a file (e.g.,grep "error" < app.log).2>: Redirect errors (e.g.,command_that_fails 2> errors.log).&>: Redirect both output and errors (e.g.,script.sh &> combined.log).
Pipes:
Use | to send the output of one command as input to another. For example, count lines containing “error” in a log:
grep "error" app.log | wc -l # Output: Number of lines with "error"
2.4 Conditionals: Making Decisions in Scripts
Use if statements to run code based on conditions. Conditions are checked with [ ] (POSIX-compliant) or [[ ]] (Bash-specific, supports more features like regex).
Example: Check if a File Exists
#!/bin/bash
file="data.txt"
if [ -f "$file" ]; then # -f checks if file exists and is a regular file
echo "$file exists!"
else
echo "$file not found."
fi
Common Conditions:
- File tests:
-f(file),-d(directory),-e(exists),-s(not empty). - Numeric comparisons:
-eq(equal),-ne(not equal),-gt(greater than),-lt(less than). - String comparisons:
=,!=(equal/not equal),-z(empty string),-n(non-empty string).
Example: Numeric Comparison
age=17
if [ $age -lt 18 ]; then
echo "Minor"
elif [ $age -eq 18 ]; then
echo "Just成年"
else
echo "Adult"
fi
2.5 Loops: Automating Repetitive Tasks
Loops let you run commands repeatedly. Bash supports for, while, and until loops.
For Loops: Iterate Over Lists
Loop through files, numbers, or command output:
#!/bin/bash
# Loop through numbers 1-5
for i in {1..5}; do
echo "Count: $i"
done
# Loop through .txt files in a directory
for file in *.txt; do
echo "Processing $file"
done
# Loop through output of a command (e.g., list of users)
for user in $(cut -d: -f1 /etc/passwd); do
echo "User: $user"
done
While Loops: Run Until a Condition Fails
#!/bin/bash
count=1
while [ $count -le 5 ]; do
echo "Loop iteration $count"
count=$((count + 1)) # Increment count
done
3. Advanced Bash Concepts
3.1 Functions: Reusing Code
Functions let you group commands into reusable blocks. Define them with function_name() { ... }.
Example: Greeting Function
#!/bin/bash
greet() {
local name=$1 # $1 is the first argument passed to the function
echo "Hello, $name!"
}
greet "Bob" # Output: Hello, Bob!
Key Points:
- Use
localto limit variable scope to the function. - Access arguments with
$1,$2, etc. ($@for all arguments).
3.2 Error Handling: Writing Robust Scripts
Prevent scripts from failing silently with these techniques:
set -e: Exit immediately if any command fails.set -u: Treat unset variables as errors (avoids bugs from typos).trap: Run cleanup commands (e.g., delete temp files) on script exit.
Example: Error-Resilient Script
#!/bin/bash
set -euo pipefail # Exit on error, unset variable, or pipe failure
temp_file=$(mktemp) # Create temporary file
# Clean up temp file on exit (even if script fails)
trap 'rm -f "$temp_file"' EXIT
echo "Working with $temp_file..."
# ... rest of script ...
3.3 Arrays: Managing Lists of Data
Arrays store multiple values in a single variable. Use () to define them, and ${array[i]} to access elements (indexes start at 0).
Example: Array Basics
#!/bin/bash
fruits=("apple" "banana" "cherry")
# Print all elements
echo "Fruits: ${fruits[@]}" # Output: Fruits: apple banana cherry
# Loop through array
for fruit in "${fruits[@]}"; do
echo "I like $fruit"
done
3.4 Regular Expressions: Pattern Matching
Use grep -E (extended regex) or [[ string =~ regex ]] in Bash to match patterns.
Example: Validate Email Format
#!/bin/bash
email="[email protected]"
if [[ $email =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]; then
echo "Valid email: $email"
else
echo "Invalid email: $email"
fi
4. Practical Automation Examples
4.1 File Management: Organizing Downloads Automatically
This script sorts files in ~/Downloads into folders by type (e.g., Images, Documents):
#!/bin/bash
set -euo pipefail
downloads_dir="$HOME/Downloads"
# Create target directories if they don't exist
mkdir -p "$downloads_dir"/{Images,Documents,Archives,Other}
# Move files by extension
find "$downloads_dir" -maxdepth 1 -type f | while read -r file; do
case "$file" in
*.jpg|*.jpeg|*.png|*.gif) mv -n "$file" "$downloads_dir/Images/" ;;
*.pdf|*.doc|*.docx|*.txt) mv -n "$file" "$downloads_dir/Documents/" ;;
*.zip|*.tar.gz|*.rar) mv -n "$file" "$downloads_dir/Archives/" ;;
*) mv -n "$file" "$downloads_dir/Other/" ;;
esac
done
echo "Downloads organized!"
4.2 System Monitoring: Disk Space Alerts
This script checks disk usage and sends an alert if a partition exceeds 90% usage:
#!/bin/bash
set -euo pipefail
# Check disk usage (excl. tmpfs)
df -h | grep -vE '^Filesystem|tmpfs|udev' | awk '{print $5 " " $1}' | while read -r usage partition; do
# Extract numeric value (e.g., "95%" → 95)
usage_num=${usage%?}
if [ "$usage_num" -ge 90 ]; then
echo "ALERT: Partition $partition is $usage full!" | mail -s "Disk Space Warning" [email protected]
fi
done
4.3 Log Processing: Analyzing Apache 404 Errors
Parse Apache logs to count 404 errors and list top URLs:
#!/bin/bash
log_file="/var/log/apache2/access.log"
echo "Top 10 404 URLs:"
grep " 404 " "$log_file" | awk '{print $7}' | sort | uniq -c | sort -nr | head -10
4.4 Backup Automation: Timestamped Rsync Backups
Use rsync to back up a directory to an external drive with timestamped folders:
#!/bin/bash
set -euo pipefail
source_dir="/home/alice/documents"
dest_dir="/mnt/backup_drive/documents_backups"
timestamp=$(date +%Y%m%d_%H%M%S)
backup_dir="$dest_dir/backup_$timestamp"
# Create backup
rsync -av --progress "$source_dir" "$backup_dir"
echo "Backup completed: $backup_dir"
# Optional: Keep only last 5 backups
ls -dt "$dest_dir"/backup_* | tail -n +6 | xargs rm -rf
5. Best Practices for Bash Scripting
- Comment Liberally: Explain why not just what the code does.
- Use Absolute Paths: Avoid relative paths (e.g.,
/home/aliceinstead of~/) for reliability. - Quote Variables: Always quote variables (
"$var") to handle spaces in filenames. - Test Rigorously: Run scripts with
bash -n script.shto check syntax, and test in a non-production environment. - Version Control: Store scripts in Git to track changes and revert if needed.
- Limit Scope: Keep scripts small and focused (e.g., separate backup and monitoring scripts).
6. Conclusion
Bash is a powerful tool for Linux automation, enabling you to streamline repetitive tasks, monitor systems, and build custom workflows with minimal effort. By mastering variables, loops, conditionals, and advanced concepts like error handling and arrays, you can write robust scripts that save time and reduce manual errors.
Start small—automate one task (e.g., organizing downloads), then expand to more complex workflows. With practice, you’ll leverage Bash to transform how you interact with Linux systems.
7. References
- GNU Bash Manual
- Bash Hackers Wiki
- Stack Overflow Bash Community
- Book: Learning the Bash Shell by Cameron Newham
- Book: Bash Cookbook by Carl Albing and JP Vossen
Happy scripting! 🚀