系统监控脚本#

脚本说明#

系统监控脚本用于实时监控系统资源使用情况,包括CPU、内存、磁盘、网络等,并在超过阈值时发送告警。

脚本代码#

#!/bin/bash

# 系统监控脚本
# 功能:监控系统资源使用情况并告警
# 作者:System Admin
# 日期:2026-01-01

set -euo pipefail

# 配置变量
LOG_FILE="/var/log/system_monitor.log"
ALERT_LOG="/var/log/system_alert.log"
EMAIL_RECIPIENT="admin@example.com"
CPU_THRESHOLD=80
MEMORY_THRESHOLD=80
DISK_THRESHOLD=90
NETWORK_THRESHOLD=1000000  # 网络流量阈值(字节/秒)
INTERVAL=60  # 监控间隔(秒)

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $@" | tee -a "$LOG_FILE"
}

log_info() {
    log "INFO" "$@"
}

log_error() {
    log "ERROR" "$@"
}

log_warning() {
    log "WARNING" "$@"
}

# 告警函数
send_alert() {
    local message=$1
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # 记录告警日志
    echo "[$timestamp] ALERT: $message" >> "$ALERT_LOG"
    
    # 发送邮件告警
    if [ -n "$EMAIL_RECIPIENT" ]; then
        echo "$message" | mail -s "系统告警" "$EMAIL_RECIPIENT"
    fi
    
    # 控制台输出
    echo -e "${RED}[ALERT]${NC} $message"
}

# 监控CPU使用率
monitor_cpu() {
    local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
    local cpu_usage_int=${cpu_usage%.*}
    
    log_info "CPU使用率: ${cpu_usage}%"
    
    if [ $cpu_usage_int -ge $CPU_THRESHOLD ]; then
        send_alert "CPU使用率过高: ${cpu_usage}%"
        return 1
    fi
    
    return 0
}

# 监控内存使用率
monitor_memory() {
    local total=$(free -m | grep Mem | awk '{print $2}')
    local used=$(free -m | grep Mem | awk '{print $3}')
    local usage=$((used * 100 / total))
    
    log_info "内存使用率: ${usage}% (已用: ${used}MB / 总计: ${total}MB)"
    
    if [ $usage -ge $MEMORY_THRESHOLD ]; then
        send_alert "内存使用率过高: ${usage}%"
        return 1
    fi
    
    return 0
}

# 监控磁盘使用率
monitor_disk() {
    local alert=0
    
    while read -r line; do
        local mount_point=$(echo "$line" | awk '{print $6}')
        local usage=$(echo "$line" | awk '{print $5}' | cut -d'%' -f1)
        
        log_info "磁盘使用率 [$mount_point]: ${usage}%"
        
        if [ $usage -ge $DISK_THRESHOLD ]; then
            send_alert "磁盘使用率过高 [$mount_point]: ${usage}%"
            alert=1
        fi
    done < <(df -h | grep -E '^/dev/')
    
    return $alert
}

# 监控网络流量
monitor_network() {
    local interface=$(ip route | grep default | awk '{print $5}' | head -n 1)
    
    if [ -z "$interface" ]; then
        log_warning "无法获取网络接口"
        return 0
    fi
    
    # 获取初始流量
    local rx_bytes1=$(cat /sys/class/net/$interface/statistics/rx_bytes)
    local tx_bytes1=$(cat /sys/class/net/$interface/statistics/tx_bytes)
    
    sleep 1
    
    # 获取1秒后的流量
    local rx_bytes2=$(cat /sys/class/net/$interface/statistics/rx_bytes)
    local tx_bytes2=$(cat /sys/class/net/$interface/statistics/tx_bytes)
    
    # 计算流量(字节/秒)
    local rx_rate=$((rx_bytes2 - rx_bytes1))
    local tx_rate=$((tx_bytes2 - tx_bytes1))
    local total_rate=$((rx_rate + tx_rate))
    
    log_info "网络流量 [$interface]: 接收: ${rx_rate}B/s, 发送: ${tx_rate}B/s"
    
    if [ $total_rate -ge $NETWORK_THRESHOLD ]; then
        send_alert "网络流量过高: ${total_rate}B/s"
        return 1
    fi
    
    return 0
}

# 监控进程
monitor_processes() {
    local process_count=$(ps aux | wc -l)
    log_info "进程数量: $process_count"
    
    # 检查僵尸进程
    local zombie_count=$(ps aux | grep -c "Z")
    if [ $zombie_count -gt 0 ]; then
        send_alert "发现僵尸进程: $zombie_count 个"
        return 1
    fi
    
    return 0
}

# 监控系统负载
monitor_load() {
    local load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | cut -d',' -f1)
    local cpu_count=$(nproc)
    local load_threshold=$((cpu_count * 2))
    
    log_info "系统负载: $load (CPU核心数: $cpu_count)"
    
    if (( $(echo "$load > $load_threshold" | bc -l) )); then
        send_alert "系统负载过高: $load"
        return 1
    fi
    
    return 0
}

# 监控服务状态
monitor_services() {
    local services=("nginx" "mysql" "ssh" "cron")
    local alert=0
    
    for service in "${services[@]}"; do
        if systemctl is-active --quiet "$service"; then
            log_info "服务状态 [$service]: 运行中"
        else
            send_alert "服务未运行: $service"
            alert=1
        fi
    done
    
    return $alert
}

# 生成监控报告
generate_report() {
    local date=$(date +%Y-%m-%d)
    local report_file="/tmp/system_report_$date.txt"
    
    {
        echo "系统监控报告"
        echo "生成时间: $(date)"
        echo ""
        
        echo "===== CPU信息 ====="
        lscpu | grep -E "Model name|CPU\(s\)|Thread"
        echo ""
        
        echo "===== 内存信息 ====="
        free -h
        echo ""
        
        echo "===== 磁盘信息 ====="
        df -h
        echo ""
        
        echo "===== 网络信息 ====="
        ip addr
        echo ""
        
        echo "===== 系统负载 ====="
        uptime
        echo ""
        
        echo "===== 进程信息 ====="
        ps aux --sort=-%cpu | head -10
        echo ""
        
        echo "===== 服务状态 ====="
        systemctl list-units --type=service --state=running
    } > "$report_file"
    
    log_info "监控报告已生成: $report_file"
}

# 主监控循环
main() {
    log_info "===== 开始系统监控 ====="
    log_info "监控间隔: ${INTERVAL}秒"
    
    # 生成初始报告
    generate_report
    
    # 监控循环
    while true; do
        log_info "===== 执行监控检查 ====="
        
        local alerts=0
        
        # 执行各项监控
        monitor_cpu || alerts=$((alerts + 1))
        monitor_memory || alerts=$((alerts + 1))
        monitor_disk || alerts=$((alerts + 1))
        monitor_network || alerts=$((alerts + 1))
        monitor_processes || alerts=$((alerts + 1))
        monitor_load || alerts=$((alerts + 1))
        monitor_services || alerts=$((alerts + 1))
        
        # 汇总结果
        if [ $alerts -eq 0 ]; then
            log_info "所有监控项正常"
        else
            log_warning "发现 $alerts 个告警"
        fi
        
        # 等待下一次监控
        sleep $INTERVAL
    done
}

# 信号处理
trap 'log_info "接收到退出信号,停止监控"; exit 0' SIGINT SIGTERM

# 执行主函数
main "$@"

使用说明#

  1. 修改配置变量:

    • LOG_FILE: 日志文件路径
    • ALERT_LOG: 告警日志路径
    • EMAIL_RECIPIENT: 告警邮件接收者
    • CPU_THRESHOLD: CPU使用率阈值(%)
    • MEMORY_THRESHOLD: 内存使用率阈值(%)
    • DISK_THRESHOLD: 磁盘使用率阈值(%)
    • NETWORK_THRESHOLD: 网络流量阈值(字节/秒)
    • INTERVAL: 监控间隔(秒)
  2. 添加执行权限:

    chmod +x system_monitor.sh
  3. 执行脚本:

    ./system_monitor.sh
  4. 后台运行:

    nohup ./system_monitor.sh > /dev/null 2>&1 &
  5. 设置为系统服务:

    sudo cp system_monitor.sh /usr/local/bin/
    sudo chmod +x /usr/local/bin/system_monitor.sh
    
    # 创建systemd服务文件
    sudo tee /etc/systemd/system/system-monitor.service > /dev/null <<EOF
    [Unit]
    Description=System Monitor Service
    After=network.target
    
    [Service]
    Type=simple
    ExecStart=/usr/local/bin/system_monitor.sh
    Restart=always
    RestartSec=10
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    sudo systemctl daemon-reload
    sudo systemctl enable system-monitor
    sudo systemctl start system-monitor

功能特点#

  • 实时监控CPU、内存、磁盘、网络等资源
  • 可配置的告警阈值
  • 多种告警方式(日志、邮件)
  • 详细的监控日志
  • 系统报告生成
  • 服务状态监控
  • 进程监控
  • 系统负载监控

依赖项#

  • bc: 用于浮点数计算
  • mail: 用于发送邮件告警
  • systemd: 用于服务管理(可选)

注意事项#

  1. 根据实际情况调整监控阈值
  2. 确保邮件服务配置正确
  3. 定期检查告警日志
  4. 监控脚本会持续运行,注意资源消耗
  5. 建议在测试环境验证后再部署到生产环境