Exercises
Chapter 46: Practical Exercises
Section titled “Chapter 46: Practical Exercises”Overview
Section titled “Overview”This chapter provides hands-on exercises to practice bash scripting skills for real-world DevOps, SRE, and SysAdmin scenarios.
Exercise 1: System Health Check Script
Section titled “Exercise 1: System Health Check Script”Problem
Section titled “Problem”Create a script that checks system health:
- CPU usage
- Memory usage
- Disk usage
- Top 5 processes by memory
Solution
Section titled “Solution”#!/usr/bin/env bash
check_cpu() { top -bn1 | grep "Cpu(s)" | awk '{print "CPU: " $2}'}
check_memory() { free -h | awk '/^Mem:/ {print "Memory: " $3 "/" $2}'}
check_disk() { df -h | awk '/\/$/ {print "Disk: " $3 " used of " $2}'}
check_top_processes() { echo "Top 5 processes:" ps aux --sort=-%mem | awk 'NR<=6 {print $11, $6"MB"}'}
echo "=== System Health Check ==="check_cpucheck_memorycheck_diskcheck_top_processesExercise 2: Log File Analyzer
Section titled “Exercise 2: Log File Analyzer”Problem
Section titled “Problem”Create a script to analyze Apache/Nginx logs:
- Count requests by IP
- Find most visited pages
- Show error count
Solution
Section titled “Solution”#!/usr/bin/env bash
LOG_FILE="${1:-/var/log/nginx/access.log}"
echo "=== Log Analysis ==="echo "Requests by IP:"awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -5
echo -e "\nMost visited pages:"awk '{print $7}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -5
echo -e "\nError count:"grep -c " 5[0-9][0-9] " "$LOG_FILE"Exercise 3: Automated Backup Script
Section titled “Exercise 3: Automated Backup Script”Problem
Section titled “Problem”Create a backup script that:
- Backs up specified directories
- Creates timestamped archives
- Cleans up old backups
Solution
Section titled “Solution”#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/backup"SOURCE_DIRS=("/home" "/etc" "/var/www")DAYS_TO_KEEP=7
timestamp=$(date +%Y%m%d_%H%M%S)backup_file="$BACKUP_DIR/backup_$timestamp.tar.gz"
mkdir -p "$BACKUP_DIR"
tar -czf "$backup_file" "${SOURCE_DIRS[@]}"
echo "Backup created: $backup_file"
# Cleanup old backupsfind "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +$DAYS_TO_KEEP -delete
echo "Old backups cleaned up"Exercise 4: User Management Script
Section titled “Exercise 4: User Management Script”Problem
Section titled “Problem”Create a script for user management:
- Add new users with home directory
- List all users
- Lock/unlock accounts
Solution
Section titled “Solution”#!/usr/bin/env bash
add_user() { local username="$1" sudo useradd -m "$username" echo "User $username created"}
list_users() { awk -F: '{print $1, $6}' /etc/passwd}
lock_user() { sudo usermod -L "$1" echo "User $1 locked"}
unlock_user() { sudo usermod -U "$1" echo "User $1 unlocked"}
case "$1" in add) add_user "$2" ;; list) list_users ;; lock) lock_user "$2" ;; unlock) unlock_user "$2" ;;esacExercise 5: Network Diagnostics Script
Section titled “Exercise 5: Network Diagnostics Script”Problem
Section titled “Problem”Create a network diagnostics script:
- Check connectivity to hosts
- Show listening ports
- Display network interface info
Solution
Section titled “Solution”#!/usr/bin/env bash
check_hosts() { local hosts=("google.com" "8.8.8.8" "cloudflare.com") for host in "${hosts[@]}"; do if ping -c 1 "$host" &>/dev/null; then echo "✓ $host is reachable" else echo "✗ $host is unreachable" fi done}
list_ports() { echo "Listening ports:" ss -tuln | awk 'NR>1 {print $1, $5}' | column -t}
network_info() { ip addr show | awk '/inet / {print "IP:", $2}' ip route | awk '/default / {print "Gateway:", $3}'}
echo "=== Network Diagnostics ==="check_hostsecholist_portsechonetwork_infoExercise 6: Docker Container Manager
Section titled “Exercise 6: Docker Container Manager”Problem
Section titled “Problem”Create a script to manage Docker containers:
- Start/Stop/Restart containers
- Show container status
- View logs
Solution
Section titled “Solution”#!/usr/bin/env bash
container_status() { docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"}
start_container() { docker start "$1" && echo "Started: $1"}
stop_container() { docker stop "$1" && echo "Stopped: $1"}
restart_container() { docker restart "$1" && echo "Restarted: $1"}
view_logs() { docker logs --tail 50 "$1"}
case "$1" in status) container_status ;; start) start_container "$2" ;; stop) stop_container "$2" ;; restart) restart_container "$2" ;; logs) view_logs "$2" ;;esacExercise 7: SSL Certificate Checker
Section titled “Exercise 7: SSL Certificate Checker”Problem
Section titled “Problem”Create a script to check SSL certificates:
- Check certificate expiry
- Show days remaining
- Alert if expiring soon
Solution
Section titled “Solution”<function_code> #!/usr/bin/env bash
check_ssl() { local domain=“$1” local port=”${2:-443}”
local expiry=$(echo | openssl s_client -servername "$domain" -connect "$domain:$port" 2>/dev/null | openssl x509 -noout -enddate)
if [ -z "$expiry" ]; then echo "Error: Could not get certificate for $domain" return 1fi
local expiry_date=$(echo "$expiry" | cut -d= -f2)local expiry_epoch=$(date -d "$expiry_date" +%s)local now_epoch=$(date +%s)local days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
echo "Domain: $domain"echo "Expires: $expiry_date"echo "Days remaining: $days_left"
if [ "$days_left" -lt 30 ]; then echo "⚠ WARNING: Certificate expires in less than 30 days!" return 1fi
echo "✓ Certificate is valid"}
for domain in ”$@”; do check_ssl “$domain” echo ”---” done </function_code>
Exercise 8: Database Backup Script
Section titled “Exercise 8: Database Backup Script”Problem
Section titled “Problem”Create a script to backup databases:
- Backup MySQL/PostgreSQL
- Compress and encrypt
- Upload to remote storage
solution
Section titled “solution”#!/usr/bin/env bash
set -euo pipefail
DB_TYPE="${DB_TYPE:-mysql}"DB_NAME="${DB_NAME:-mydb}"DB_USER="${DB_USER:-root}"BACKUP_DIR="/backup/db"REMOTE_HOST="backup-server"
timestamp=$(date +%Y%m%d_%H%M%S)backup_file="$BACKUP_DIR/${DB_NAME}_${timestamp}.sql.gz"
mkdir -p "$BACKUP_DIR"
backup_mysql() { mysqldump -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" | gzip > "$backup_file"}
backup_postgres() { pg_dump -U "$DB_USER" "$DB_NAME" | gzip > "$backup_file"}
if [ "$DB_TYPE" = "mysql" ]; then backup_mysqlelif [ "$DB_TYPE" = "postgres" ]; then backup_postgresfi
echo "Database backup created: $backup_file"
# Upload to remotescp "$backup_file" "$REMOTE_HOST:/backups/"
echo "Backup uploaded to remote"Summary
Section titled “Summary”In this chapter, you completed:
- ✅ System health check script
- ✅ Log file analyzer
- ✅ Automated backup script
- ✅ User management script
- ✅ Network diagnostics
- ✅ Docker container manager
- ✅ SSL certificate checker
- ✅ Database backup script
Next Steps
Section titled “Next Steps”Practice these exercises and modify them for your specific use cases. Refer back to earlier chapters for detailed explanations of specific commands and techniques.
Previous Chapter: Interview Questions End of Guide