Advanced โฑ 30 min Lesson 13 of 13

๐Ÿ† Real-World Projects

Build real scripts: system info, log analyzer, automated backup, and best practices.

Putting It All Together

You've learned the building blocks. Now it's time to combine them into real, useful scripts. This lesson walks through three complete projects and covers best practices for production scripts.

Project 1: System Information Script

This script gathers and displays key information about the system โ€” perfect for quick server audits.

bash
#!/bin/bash
set -euo pipefail

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

section() {
    echo -e "\n${CYAN}โ•โ•โ• $1 โ•โ•โ•${NC}"
}

section "SYSTEM INFO"
echo "Hostname : $(hostname)"
echo "OS       : $(uname -s) $(uname -r)"
echo "Uptime   : $(uptime -p 2>/dev/null || uptime)"
echo "Date     : $(date)"

section "CPU"
echo "Model    : $(grep 'model name' /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)"
echo "Cores    : $(nproc)"
echo "Load Avg : $(cat /proc/loadavg | awk '{print $1, $2, $3}')"

section "MEMORY"
free -h | awk '
    /^Mem:/ {printf "Total: %s | Used: %s | Free: %s\n", $2, $3, $4}
    /^Swap:/ {printf "Swap:  %s | Used: %s | Free: %s\n", $2, $3, $4}
'

section "DISK"
df -h / | awk 'NR==2 {printf "Root: %s total, %s used (%s), %s free\n", $2, $3, $5, $4}'

section "NETWORK"
hostname -I 2>/dev/null | awk '{print "IP Address:", $1}' || echo "IP: N/A"

echo -e "\n${GREEN}โœ“ System check complete${NC}"

Project 2: Log Analyzer

Analyze web server access logs to find top visitors, most-requested pages, and error rates.

bash
#!/bin/bash
set -euo pipefail

LOGFILE="${1:?Usage: $0 <access.log>}"

if [[ ! -f "$LOGFILE" ]]; then
    echo "Error: File not found: $LOGFILE" >&2
    exit 1
fi

total=$(wc -l < "$LOGFILE")
echo "=== Log Analysis: $LOGFILE ==="
echo "Total requests: $total"
echo ""

echo "--- Top 10 IP Addresses ---"
awk '{print $1}' "$LOGFILE" | sort | uniq -c | sort -rn | head -10
echo ""

echo "--- Top 10 Requested URLs ---"
awk '{print $7}' "$LOGFILE" | sort | uniq -c | sort -rn | head -10
echo ""

echo "--- HTTP Status Code Breakdown ---"
awk '{print $9}' "$LOGFILE" | sort | uniq -c | sort -rn
echo ""

echo "--- Error Rate (4xx + 5xx) ---"
errors=$(awk '$9 ~ /^[45]/ {count++} END {print count+0}' "$LOGFILE")
if (( total > 0 )); then
    rate=$(echo "scale=2; $errors * 100 / $total" | bc)
    echo "$errors errors out of $total requests ($rate%)"
else
    echo "No requests to analyze."
fi

echo ""
echo "--- Requests Per Hour ---"
awk -F: '{print $2}' "$LOGFILE" | awk '{print $1}' | sort | uniq -c | sort -k2n

Project 3: Automated Backup Script

A production-ready backup script with rotation, logging, and error handling.

bash
#!/bin/bash
set -euo pipefail

# Configuration
SOURCE_DIR="${1:-$HOME/documents}"
BACKUP_DIR="${2:-$HOME/backups}"
MAX_BACKUPS=7
LOG_FILE="$BACKUP_DIR/backup.log"

# Setup
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="$BACKUP_DIR/backup_$TIMESTAMP.tar.gz"

log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

err() {
    log "ERROR: $1"
    exit 1
}

# Cleanup on exit
trap '[[ $? -ne 0 ]] && log "Backup FAILED"' EXIT

# Validate
[[ -d "$SOURCE_DIR" ]] || err "Source directory not found: $SOURCE_DIR"
mkdir -p "$BACKUP_DIR"

log "Starting backup of $SOURCE_DIR"

# Create backup
tar -czf "$BACKUP_FILE" -C "$(dirname "$SOURCE_DIR")" "$(basename "$SOURCE_DIR")" \
    2>> "$LOG_FILE"

# Verify
if [[ -f "$BACKUP_FILE" ]]; then
    size=$(du -h "$BACKUP_FILE" | cut -f1)
    log "Backup created: $BACKUP_FILE ($size)"
else
    err "Backup file was not created"
fi

# Rotate โ€” keep only the last N backups
backup_count=$(ls -1 "$BACKUP_DIR"/backup_*.tar.gz 2>/dev/null | wc -l)
if (( backup_count > MAX_BACKUPS )); then
    ls -1t "$BACKUP_DIR"/backup_*.tar.gz | tail -n +$((MAX_BACKUPS + 1)) | while read -r old; do
        log "Removing old backup: $old"
        rm -f "$old"
    done
fi

log "Backup complete. Total backups: $(ls -1 "$BACKUP_DIR"/backup_*.tar.gz | wc -l)"
๐Ÿ’ก Tip: Add this backup script to your crontab for automatic daily backups: 0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1

Best Practices Recap

  • Always use set -euo pipefail โ€” catch errors early.
  • Quote your variables โ€” "$var" prevents word splitting and glob expansion.
  • Use functions โ€” keep scripts modular and testable.
  • Log to stderr โ€” keep stdout clean for data, stderr for messages.
  • Use trap for cleanup โ€” always clean up temp files.
  • Add a usage/help function โ€” scripts should be self-documenting.
  • Use [[ ]] over [ ] โ€” fewer surprises with empty variables.
  • Use shellcheck โ€” a linting tool that catches common bugs.

Security Considerations

  • Never store passwords in scripts. Use environment variables or secret managers.
  • Be cautious with eval โ€” it executes arbitrary code and is a common injection vector.
  • Validate all user input before using it in commands.
  • Use mktemp for temporary files instead of hardcoded names.
  • Set restrictive permissions on scripts containing sensitive logic: chmod 700 script.sh.
โš ๏ธ Warning: Never use eval with untrusted input. A string like $(rm -rf /) inside an eval statement would be catastrophic.

Next Steps & Resources

  • ShellCheck (shellcheck.net) โ€” Lint your scripts online or install locally.
  • Advanced Bash-Scripting Guide โ€” The classic reference (tldp.org).
  • Explainshell (explainshell.com) โ€” Paste a command and get a breakdown.
  • Practice: Automate something you do manually. That's how real learning happens.

Try It Yourself: Build a Mini Script

Combine everything you've learned into a script that accepts a directory, counts files by extension, and reports the results.

Terminal

Congratulations! ๐ŸŽ‰

You've completed the entire BashHero curriculum! You've gone from your first echo to building production-ready scripts with error handling, automation, and real-world projects. The command line is now your playground. Keep practicing, keep automating, and keep learning!

๐Ÿงช Test Your Knowledge

Answer the questions below to check your understanding of this lesson.