Skip to content

Practical Examples

Overview

This chapter demonstrates how to apply the knowledge learned earlier to daily work through practical examples.

System Management Scripts

System Information Report

bash
#!/bin/bash
# system-info.sh - System information report script

echo "======================================"
echo "       System Information Report"
echo "       $(date '+%Y-%m-%d %H:%M:%S')"
echo "======================================"

echo -e "\n[System Information]"
echo "Hostname: $(hostname)"
echo "System: $(uname -s) $(uname -r)"
echo "Architecture: $(uname -m)"
echo "Uptime: $(uptime -p)"

echo -e "\n[CPU Information]"
echo "CPU: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d: -f2)"
echo "Cores: $(nproc)"
echo "Load: $(cat /proc/loadavg | awk '{print $1, $2, $3}')"

echo -e "\n[Memory Information]"
free -h | awk 'NR==2{printf "Total: %s, Used: %s, Available: %s\n", $2, $3, $7}'

echo -e "\n[Disk Usage]"
df -h | grep -E '^/dev' | awk '{printf "%-15s %s Used (%s)\n", $1, $3, $5}'

echo -e "\n[Network Interfaces]"
ip -4 addr show | grep -E 'inet ' | awk '{print $NF": "$2}'

echo -e "\n[Logged In Users]"
who | awk '{print $1" from "$5" logged in at "$3" "$4}'

Log Cleanup Script

bash
#!/bin/bash
# clean-logs.sh - Clean old log files

LOG_DIR="/var/log"
DAYS=30
DRY_RUN=false

# Parse arguments
while getopts "d:n" opt; do
    case $opt in
        d) DAYS=$OPTARG ;;
        n) DRY_RUN=true ;;
        *) echo "Usage: $0 [-d days] [-n dry-run]"; exit 1 ;;
    esac
done

echo "Cleaning log files older than $DAYS days..."
echo "Directory: $LOG_DIR"
echo "Dry run: $DRY_RUN"
echo

# Find old logs
files=$(find "$LOG_DIR" -type f -name "*.log*" -mtime +$DAYS 2>/dev/null)

if [ -z "$files" ]; then
    echo "No files found to clean"
    exit 0
fi

total_size=0
count=0

while IFS= read -r file; do
    size=$(du -b "$file" 2>/dev/null | cut -f1)
    total_size=$((total_size + size))
    count=$((count + 1))

    if [ "$DRY_RUN" = true ]; then
        echo "[Dry run] Would delete: $file ($(du -h "$file" | cut -f1))"
    else
        rm -f "$file"
        echo "Deleted: $file"
    fi
done <<< "$files"

echo
echo "Total $count files, $(numfmt --to=iec $total_size)"

Batch User Creation

bash
#!/bin/bash
# create-users.sh - Batch user creation

# User list file format: username:password:group
USER_FILE="users.txt"

if [ ! -f "$USER_FILE" ]; then
    echo "Error: $USER_FILE not found"
    exit 1
fi

while IFS=: read -r username password group; do
    # Skip comments and empty lines
    [[ "$username" =~ ^#.*$ || -z "$username" ]] && continue

    # Check if user exists
    if id "$username" &>/dev/null; then
        echo "User $username already exists, skipping"
        continue
    fi

    # Create group (if doesn't exist)
    if ! getent group "$group" &>/dev/null; then
        groupadd "$group"
        echo "Created group: $group"
    fi

    # Create user
    useradd -m -g "$group" -s /bin/bash "$username"
    echo "$username:$password" | chpasswd

    # Force password change on first login
    chage -d 0 "$username"

    echo "Created user: $username (group: $group)"
done < "$USER_FILE"

echo "Done!"

Backup Scripts

Incremental Backup Script

bash
#!/bin/bash
# incremental-backup.sh - Incremental backup script

BACKUP_DIR="/backup"
SOURCE_DIR="/var/www"
SNAPSHOT_FILE="${BACKUP_DIR}/.snapshot"
DATE=$(date +%Y%m%d)

mkdir -p "$BACKUP_DIR"

# Determine backup type
if [ ! -f "$SNAPSHOT_FILE" ]; then
    # Full backup
    BACKUP_FILE="${BACKUP_DIR}/full_${DATE}.tar.gz"
    echo "Performing full backup..."
    tar -czf "$BACKUP_FILE" -g "$SNAPSHOT_FILE" "$SOURCE_DIR"
else
    # Incremental backup
    BACKUP_FILE="${BACKUP_DIR}/incr_${DATE}_$(date +%H%M%S).tar.gz"
    echo "Performing incremental backup..."
    tar -czf "$BACKUP_FILE" -g "$SNAPSHOT_FILE" "$SOURCE_DIR"
fi

if [ $? -eq 0 ]; then
    echo "Backup successful: $BACKUP_FILE"
    echo "Size: $(du -h "$BACKUP_FILE" | cut -f1)"
else
    echo "Backup failed!"
    exit 1
fi

# Clean backups older than 30 days
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete
echo "Cleaned old backups"

Database Backup

bash
#!/bin/bash
# mysql-backup.sh - MySQL database backup

DB_USER="backup_user"
DB_PASS="password"
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7

mkdir -p "$BACKUP_DIR"

# Get all databases
databases=$(mysql -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|sys)")

for db in $databases; do
    BACKUP_FILE="${BACKUP_DIR}/${db}_${DATE}.sql.gz"

    echo "Backing up database: $db"
    mysqldump -u"$DB_USER" -p"$DB_PASS" --single-transaction "$db" | gzip > "$BACKUP_FILE"

    if [ ${PIPESTATUS[0]} -eq 0 ]; then
        echo "  Success: $BACKUP_FILE ($(du -h "$BACKUP_FILE" | cut -f1))"
    else
        echo "  Failed: $db"
    fi
done

# Clean old backups
echo "Cleaning backups older than $RETENTION_DAYS days..."
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete

echo "Backup complete!"

Monitoring Scripts

Disk Space Monitoring

bash
#!/bin/bash
# disk-monitor.sh - Disk space monitoring

THRESHOLD=80
ALERT_EMAIL="admin@example.com"

check_disk() {
    df -h | grep -E '^/dev' | while read -r line; do
        partition=$(echo "$line" | awk '{print $1}')
        usage=$(echo "$line" | awk '{print $5}' | tr -d '%')
        mount_point=$(echo "$line" | awk '{print $6}')

        if [ "$usage" -ge "$THRESHOLD" ]; then
            echo "Warning: $mount_point ($partition) usage ${usage}%"

            # Send email alert
            if command -v mail &>/dev/null; then
                echo "Disk alert: $mount_point usage ${usage}%" | \
                    mail -s "Disk Space Alert - $(hostname)" "$ALERT_EMAIL"
            fi
        fi
    done
}

echo "Disk space check - $(date)"
echo "Alert threshold: ${THRESHOLD}%"
echo "========================"
check_disk

Service Monitoring

bash
#!/bin/bash
# service-monitor.sh - Service monitoring script

SERVICES=("nginx" "mysql" "redis")
LOG_FILE="/var/log/service-monitor.log"

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

check_and_restart() {
    local service=$1

    if ! systemctl is-active --quiet "$service"; then
        log "Warning: $service is stopped, attempting restart..."
        systemctl restart "$service"
        sleep 5

        if systemctl is-active --quiet "$service"; then
            log "Success: $service restarted"
        else
            log "Error: $service restart failed!"
        fi
    fi
}

log "Starting service check..."
for service in "${SERVICES[@]}"; do
    check_and_restart "$service"
done
log "Service check complete"

Log Analysis

Web Log Analysis

bash
#!/bin/bash
# analyze-access-log.sh - Analyze Nginx access logs

LOG_FILE="/var/log/nginx/access.log"
TOP_N=10

echo "=== Web Log Analysis ==="
echo "Log file: $LOG_FILE"
echo "Analysis time: $(date)"
echo

echo "--- Top $TOP_N IPs by visit count ---"
awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -n $TOP_N
echo

echo "--- Top $TOP_N visited pages ---"
awk '{print $7}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -n $TOP_N
echo

echo "--- HTTP status code statistics ---"
awk '{print $9}' "$LOG_FILE" | sort | uniq -c | sort -rn
echo

echo "--- Hourly visit counts ---"
awk '{print $4}' "$LOG_FILE" | cut -d: -f2 | sort | uniq -c
echo

echo "--- Traffic statistics ---"
total_bytes=$(awk '{sum += $10} END {print sum}' "$LOG_FILE")
echo "Total traffic: $(numfmt --to=iec $total_bytes 2>/dev/null || echo "$total_bytes bytes")"

Deployment Scripts

Simple Deployment Script

bash
#!/bin/bash
# deploy.sh - Application deployment script

APP_NAME="myapp"
DEPLOY_DIR="/var/www/$APP_NAME"
REPO_URL="git@github.com:user/myapp.git"
BRANCH="main"
BACKUP_DIR="/backup/deployments"

set -e  # Exit on error

log() {
    echo "[$(date '+%H:%M:%S')] $1"
}

# Create backup
backup() {
    if [ -d "$DEPLOY_DIR" ]; then
        local backup_file="${BACKUP_DIR}/${APP_NAME}_$(date +%Y%m%d_%H%M%S).tar.gz"
        mkdir -p "$BACKUP_DIR"
        log "Creating backup: $backup_file"
        tar -czf "$backup_file" -C "$(dirname $DEPLOY_DIR)" "$(basename $DEPLOY_DIR)"
    fi
}

# Pull code
pull_code() {
    if [ -d "$DEPLOY_DIR/.git" ]; then
        log "Updating code..."
        cd "$DEPLOY_DIR"
        git fetch origin
        git checkout "$BRANCH"
        git pull origin "$BRANCH"
    else
        log "Cloning repository..."
        git clone -b "$BRANCH" "$REPO_URL" "$DEPLOY_DIR"
    fi
}

# Install dependencies
install_deps() {
    cd "$DEPLOY_DIR"
    if [ -f "package.json" ]; then
        log "Installing Node.js dependencies..."
        npm install --production
    elif [ -f "requirements.txt" ]; then
        log "Installing Python dependencies..."
        pip install -r requirements.txt
    fi
}

# Restart service
restart_service() {
    log "Restarting service..."
    systemctl restart "$APP_NAME"
}

# Main flow
main() {
    log "Starting deployment of $APP_NAME..."
    backup
    pull_code
    install_deps
    restart_service
    log "Deployment complete!"
}

main

Useful One-Liners

bash
# Find large files
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null

# Count lines of code
find . -name "*.py" | xargs wc -l | tail -1

# Batch rename files
for f in *.txt; do mv "$f" "${f%.txt}.md"; done

# Monitor command output changes
watch -n 1 "ss -s"

# Find and delete empty directories
find . -type d -empty -delete

# Show directory sizes sorted
du -sh */ | sort -h

# Find recently modified files
find . -type f -mtime -1 -ls

# Batch compress images
for f in *.jpg; do convert "$f" -quality 80 "compressed_$f"; done

# Generate random password
openssl rand -base64 16

# Check if port is open
timeout 1 bash -c '</dev/tcp/localhost/80' && echo "Open" || echo "Closed"

Summary

This chapter demonstrated multiple practical Shell script examples:

  • System Management: Information reports, log cleanup, user management
  • Backup Scripts: Incremental backups, database backups
  • Monitoring Scripts: Disk monitoring, service monitoring
  • Log Analysis: Web log statistics
  • Deployment Scripts: Automated deployment

These scripts can be modified and extended according to actual needs. Through practice, you will better master Shell scripting.


Previous: Environment Variables

Back: Index

Content is for learning and research only.