Shell自动化脚本

脚本基础规范

Shebang和编码

#!/bin/bash
# -*- coding: utf-8 -*-
# @Author: YourName
# @Date:   $(date +%Y-%m-%d)
# @Last Modified: $(date +%Y-%m-%d %H:%M:%S)
# @Description: Script description
 
set -euo pipefail   # 严格模式:出错退出,未定义变量报错,管道失败检测
IFS=$'\n\t'         # 内部字段分隔符设置

脚本结构模板

#!/bin/bash
 
# 全局变量定义
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT_NAME="$(basename "$0")"
LOG_FILE="/var/log/${SCRIPT_NAME%.*}.log"
 
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
 
# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}
 
log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}
 
log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}
 
log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}
 
# 错误处理函数
error_exit() {
    log_error "$1"
    exit 1
}
 
# 检查root权限
check_root() {
    if [[ $EUID -ne 0 ]]; then
        error_exit "This script must be run as root"
    fi
}
 
# 检查命令是否存在
command_exists() {
    command -v "$1" >/dev/null 2>&1
}
 
# 主函数
main() {
    log_info "Starting $SCRIPT_NAME"
    
    # 参数检查
    if [[ $#--lt-1-| -lt 1 ]]; then
        echo "Usage: $0 <parameter>"
        exit 1
    fi
    
    # 主要逻辑
    # TODO: Add your code here
    
    log_success "Script completed successfully"
}
 
# 脚本入口
main "$@"

系统管理自动化

系统监控脚本

#!/bin/bash
# system_monitor.sh - 系统监控脚本
 
# 获取系统信息
get_system_info() {
    local hostname=$(hostname)
    local uptime=$(uptime -p)
    local load=$(uptime | awk -F'load average:' '{print $2}')
    local memory=$(free -h | grep Mem | awk '{printf "%.1f%%", $3/$2*100}')
    local disk=$(df -h / | tail -1 | awk '{print $5}')
    
    cat << EOF
========================================
系统监控报告 - $(date '+%Y-%m-%d %H:%M:%S')
========================================
主机名: $hostname
运行时间: $uptime
负载: $load
内存使用率: $memory
磁盘使用率: $disk
========================================
EOF
}
 
# 检查服务状态
check_services() {
    local services=("ssh" "nginx" "mysql")
    
    echo "服务状态检查:"
    for service in "${services[@]}"; do
        if systemctl is-active --quiet "$service"; then
            echo "✓ $service 运行正常"
        else
            echo "✗ $service 服务异常"
        fi
    done
}
 
# 发送告警邮件
send_alert() {
    local subject="$1"
    local body="$2"
    local recipient="admin@example.com"
    
    echo "$body" | mail -s "$subject" "$recipient"
}

日志分析自动化

#!/bin/bash
# log_analyzer.sh - 日志分析脚本
 
# 分析Nginx访问日志
analyze_nginx_logs() {
    local log_file="/var/log/nginx/access.log"
    local report_file="/tmp/nginx_report_$(date +%Y%m%d).txt"
    
    if [[ ! -f "$log_file" ]]; then
        log_error "Nginx access log not found: $log_file"
        return 1
    fi
    
    {
        echo "=== Nginx访问日志分析报告 ==="
        echo "分析时间: $(date)"
        echo ""
        
        echo "=== 访问统计 ==="
        echo "总访问次数: $(wc -l < "$log_file")"
        echo ""
        
        echo "=== TOP 10 IP地址 ==="
        awk '{print $1}' "$log_file" | sort | uniq -c | sort -nr | head -10
        echo ""
        
        echo "=== TOP 10 访问页面 ==="
        awk '{print $7}' "$log_file" | sort | uniq -c | sort -nr | head -10
        echo ""
        
        echo "=== 状态码分布 ==="
        awk '{print $9}' "$log_file" | sort | uniq -c | sort -nr
        echo ""
        
        echo "=== 响应时间分析 ==="
        awk '{print $NF}' "$log_file" | awk '{count++; sum+=$1; if($1>max) max=$1} END {print "平均响应时间: " sum/count "s", "最大响应时间: " max "s"}'
        
    } > "$report_file"
    
    log_info "Nginx分析报告已生成: $report_file"
}
 
# 错误日志监控
monitor_error_logs() {
    local log_file="/var/log/nginx/error.log"
    local error_count=$(grep -c "$(date +%Y/%m/%d)" "$log_file" 2>/dev/null || echo 0)
    
    if [[ $error_count -gt 100 ]]; then
        send_alert "Nginx错误日志告警" "今日错误数量: $error_count"
    fi
}

备份自动化脚本

#!/bin/bash
# backup_automation.sh - 自动化备份脚本
 
# 配置变量
BACKUP_DIR="/backup"
RETENTION_DAYS=7
EXCLUDE_FILE="/etc/backup_exclude.lst"
 
# MySQL数据库备份
backup_mysql() {
    local db_name="$1"
    local backup_file="$BACKUP_DIR/mysql/${db_name}_$(date +%Y%m%d_%H%M%S).sql.gz"
    
    mkdir -p "$(dirname "$backup_file")"
    
    mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --single-transaction --routines --triggers "$db_name" | gzip > "$backup_file"
    
    if [[ ${PIPESTATUS[0]} -eq 0 ]]; then
        log_success "MySQL数据库备份成功: $db_name"
    else
        log_error "MySQL数据库备份失败: $db_name"
    fi
}
 
# 文件系统备份
backup_filesystem() {
    local source_dir="$1"
    local backup_name="$(basename "$source_dir")"
    local backup_file="$BACKUP_DIR/filesystem/${backup_name}_$(date +%Y%m%d_%H%M%S).tar.gz"
    
    mkdir -p "$(dirname "$backup_file")"
    
    tar -czf "$backup_file" --exclude-from="$EXCLUDE_FILE" -C "$(dirname "$source_dir")" "$backup_name"
    
    if [[ $? -eq 0 ]]; then
        log_success "文件系统备份成功: $source_dir"
    else
        log_error "文件系统备份失败: $source_dir"
    fi
}
 
# 清理旧备份
cleanup_old_backups() {
    find "$BACKUP_DIR" -type f -mtime +$RETENTION_DAYS -delete
    log_info "清理超过 $RETENTION_DAYS 天的旧备份"
}
 
# 备份完整性验证
verify_backup() {
    local backup_file="$1"
    
    if [[ "$backup_file" =~ \.gz$ ]]; then
        if gunzip -t "$backup_file" 2>/dev/null; then
            log_success "备份文件完整性验证通过: $backup_file"
            return 0
        else
            log_error "备份文件完整性验证失败: $backup_file"
            return 1
        fi
    elif [[ "$backup_file" =~ \.tar\.gz$ ]]; then
        if tar -tzf "$backup_file" >/dev/null 2>&1; then
            log_success "备份文件完整性验证通过: $backup_file"
            return 0
        else
            log_error "备份文件完整性验证失败: $backup_file"
            return 1
        fi
    fi
}

批量操作脚本

批量服务器管理

#!/bin/bash
# batch_server_manager.sh - 批量服务器管理
 
# 服务器列表
SERVERS=(
    "192.168.1.10:22:user1"
    "192.168.1.11:22:user2"
    "192.168.1.12:22:user3"
)
 
# 批量执行命令
batch_execute() {
    local command="$1"
    
    for server in "${SERVERS[@]}"; do
        IFS=':' read -r ip port user <<< "$server"
        
        log_info "在 $ip 上执行命令: $command"
        
        ssh -p "$port" "$user@$ip" "$command" >> "/tmp/batch_exec_${ip}.log" 2>&1
        
        if [[ $? -eq 0 ]]; then
            log_success "$ip: 命令执行成功"
        else
            log_error "$ip: 命令执行失败"
        fi
    done
}
 
# 批量文件传输
batch_scp() {
    local local_file="$1"
    local remote_path="$2"
    
    for server in "${SERVERS[@]}"; do
        IFS=':' read -r ip port user <<< "$server"
        
        log_info "传输文件到 $ip"
        scp -P "$port" "$local_file" "$user@$ip:$remote_path"
        
        if [[ $? -eq 0 ]]; then
            log_success "$ip: 文件传输成功"
        else
            log_error "$ip: 文件传输失败"
        fi
    done
}
 
# 批量系统更新
batch_update() {
    for server in "${SERVERS[@]}"; do
        IFS=':' read -r ip port user <<< "$server"
        
        log_info "更新 $ip 系统"
        
        ssh -p "$port" "$user@$ip" '
            if command -v apt >/dev/null; then
                sudo apt update && sudo apt upgrade -y
            elif command -v yum >/dev/null; then
                sudo yum update -y
            fi
        ' >> "/tmp/batch_update_${ip}.log" 2>&1
        
        if [[ $? -eq 0 ]]; then
            log_success "$ip: 系统更新成功"
        else
            log_error "$ip: 系统更新失败"
        fi
    done
}

批量用户管理

#!/bin/bash
# batch_user_manager.sh - 批量用户管理
 
# 创建批量用户
create_users() {
    local user_list_file="$1"
    
    while IFS=',' read -r username fullname groups; do
        # 检查用户是否已存在
        if id "$username" >/dev/null 2>&1; then
            log_warn "用户 $username 已存在,跳过创建"
            continue
        fi
        
        # 创建用户
        useradd -m -c "$fullname" -G "$groups" "$username"
        
        # 生成随机密码
        local password=$(openssl rand -base64 12)
        echo "$username:$password" | chpasswd
        
        # 强制首次登录修改密码
        chage -d 0 "$username"
        
        log_success "用户 $username 创建成功"
        
        # 保存密码到文件
        echo "$username,$password" >> "/tmp/new_users_passwords.csv"
    done < "$user_list_file"
}
 
# 批量删除用户
delete_users() {
    local user_list_file="$1"
    
    while IFS=',' read -r username; do
        # 检查用户是否存在
        if ! id "$username" >/dev/null 2>&1; then
            log_warn "用户 $username 不存在,跳过删除"
            continue
        fi
        
        # 删除用户及家目录
        userdel -r "$username"
        log_success "用户 $username 删除成功"
    done < "$user_list_file"
}
 
# 批量修改用户权限
modify_user_permissions() {
    local username="$1"
    local action="$2"  # add or remove
    local group="$3"
    
    if [[ "$action" == "add" ]]; then
        usermod -aG "$group" "$username"
        log_success "用户 $username 添加到组 $group"
    elif [[ "$action" == "remove" ]]; then
        gpasswd -d "$username" "$group"
        log_success "用户 $username 从组 $group 移除"
    fi
}

定时任务管理

自动化任务脚本

#!/bin/bash
# cron_manager.sh - 定时任务管理器
 
# 添加定时任务
add_cron_job() {
    local schedule="$1"
    local command="$2"
    local comment="$3"
    
    # 检查任务是否已存在
    if crontab -l 2>/dev/null | grep -q "$command"; then
        log_warn "定时任务已存在: $command"
        return 1
    fi
    
    # 添加新任务
    (crontab -l 2>/dev/null; echo "$schedule $command # $comment") | crontab -
    log_success "添加定时任务成功: $schedule $command"
}
 
# 删除定时任务
remove_cron_job() {
    local command="$1"
    
    # 删除包含指定命令的行
    crontab -l 2>/dev/null | grep -v "$command" | crontab -
    log_success "删除定时任务成功: $command"
}
 
# 备份所有定时任务
backup_cron_jobs() {
    local backup_file="/backup/crontab_$(date +%Y%m%d_%H%M%S).txt"
    
    mkdir -p "$(dirname "$backup_file")"
    crontab -l > "$backup_file"
    
    log_success "定时任务备份完成: $backup_file"
}

💡 脚本开发建议:

  • 始终使用 set -euo pipefail 开启严格模式
  • 添加详细的错误处理和日志记录
  • 使用函数封装重复逻辑
  • 添加参数检查和帮助信息
  • 定期测试和维护脚本

🔗 相关笔记: 02.06_Shell脚本 10.02_Ansible自动化 11.01_性能优化