网络监控脚本#

脚本说明#

网络监控脚本用于实时监控网络连接、流量、延迟等,并在异常时发送告警。

脚本代码#

#!/bin/bash

# 网络监控脚本
# 功能:实时监控网络状态和性能
# 作者:System Admin
# 日期:2026-01-01

set -euo pipefail

# 配置变量
LOG_FILE="/var/log/network_monitor.log"
ALERT_LOG="/var/log/network_alert.log"
INTERVAL=10
PING_TARGET="8.8.8.8"
PING_COUNT=3
PING_TIMEOUT=2
BANDWIDTH_THRESHOLD=1000000  # 带宽阈值(字节/秒)
CONNECTION_THRESHOLD=1000  # 连接数阈值
ALERT_EMAIL=""

# 颜色定义
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 "$ALERT_EMAIL" ]; then
        echo "$message" | mail -s "网络告警" "$ALERT_EMAIL"
    fi
    
    # 控制台输出
    echo -e "${RED}[ALERT]${NC} $message"
}

# 获取网络接口
get_interfaces() {
    ip -o link show | awk -F': ' '{print $2}' | grep -v "lo"
}

# 监控网络连接
monitor_connections() {
    log_info "监控网络连接"
    
    # 获取连接数
    local total=$(ss -s | grep "TCP:" | awk '{print $2}')
    local established=$(ss -s | grep "TCP:" | awk '{print $4}')
    local time_wait=$(ss -s | grep "TCP:" | awk '{print $6}')
    
    log_info "总连接数: $total"
    log_info "已建立连接: $established"
    log_info "TIME_WAIT连接: $time_wait"
    
    # 检查连接数阈值
    if [ $total -gt $CONNECTION_THRESHOLD ]; then
        send_alert "网络连接数过高: $total"
    fi
    
    # 显示连接状态分布
    ss -s
}

# 监控网络流量
monitor_traffic() {
    log_info "监控网络流量"
    
    local interfaces=($(get_interfaces))
    
    for interface in "${interfaces[@]}"; do
        # 获取初始流量
        local rx_bytes1=$(cat /sys/class/net/$interface/statistics/rx_bytes)
        local tx_bytes1=$(cat /sys/class/net/$interface/statistics/tx_bytes)
        local rx_packets1=$(cat /sys/class/net/$interface/statistics/rx_packets)
        local tx_packets1=$(cat /sys/class/net/$interface/statistics/tx_packets)
        
        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_packets2=$(cat /sys/class/net/$interface/statistics/rx_packets)
        local tx_packets2=$(cat /sys/class/net/$interface/statistics/tx_packets)
        
        # 计算流量速率
        local rx_rate=$((rx_bytes2 - rx_bytes1))
        local tx_rate=$((tx_bytes2 - tx_bytes1))
        local total_rate=$((rx_rate + tx_rate))
        
        local rx_packet_rate=$((rx_packets2 - rx_packets1))
        local tx_packet_rate=$((tx_packets2 - tx_packets1))
        
        log_info "接口 [$interface]:"
        log_info "  接收: ${rx_rate}B/s (${rx_packet_rate}pps)"
        log_info "  发送: ${tx_rate}B/s (${tx_packet_rate}pps)"
        log_info "  总计: ${total_rate}B/s"
        
        # 检查带宽阈值
        if [ $total_rate -gt $BANDWIDTH_THRESHOLD ]; then
            send_alert "网络流量过高 [$interface]: ${total_rate}B/s"
        fi
    done
}

# 监控网络延迟
monitor_latency() {
    log_info "监控网络延迟: $PING_TARGET"
    
    # 执行ping测试
    local ping_result=$(ping -c $PING_COUNT -W $PING_TIMEOUT $PING_TARGET 2>&1)
    
    # 提取延迟信息
    if echo "$ping_result" | grep -q "time="; then
        local avg_latency=$(echo "$ping_result" | grep "time=" | awk -F'/' '{print $5}')
        local packet_loss=$(echo "$ping_result" | grep "packet loss" | awk '{print $6}' | cut -d'%' -f1)
        
        log_info "平均延迟: ${avg_latency}ms"
        log_info "丢包率: ${packet_loss}%"
        
        # 检查延迟阈值
        if (( $(echo "$avg_latency > 100" | bc -l) )); then
            send_alert "网络延迟过高: ${avg_latency}ms"
        fi
        
        # 检查丢包率
        if (( $(echo "$packet_loss > 5" | bc -l) )); then
            send_alert "网络丢包率过高: ${packet_loss}%"
        fi
    else
        send_alert "无法ping通目标: $PING_TARGET"
    fi
}

# 监控网络接口状态
monitor_interface_status() {
    log_info "监控网络接口状态"
    
    local interfaces=($(get_interfaces))
    
    for interface in "${interfaces[@]}"; do
        local status=$(ip link show "$interface" | grep -o "state [A-Z]*" | awk '{print $2}')
        local carrier=$(cat /sys/class/net/$interface/carrier 2>/dev/null || echo "0")
        
        log_info "接口 [$interface]: 状态=$status, 载波=$carrier"
        
        # 检查接口状态
        if [ "$status" != "UP" ]; then
            send_alert "网络接口 [$interface] 状态异常: $status"
        fi
        
        if [ "$carrier" = "0" ]; then
            send_alert "网络接口 [$interface] 无载波信号"
        fi
    done
}

# 监控DNS解析
monitor_dns() {
    log_info "监控DNS解析"
    
    local dns_servers=("8.8.8.8" "1.1.1.1" "114.114.114.114")
    local test_domain="www.google.com"
    
    for dns in "${dns_servers[@]}"; do
        local start_time=$(date +%s.%N)
        
        if nslookup "$test_domain" "$dns" > /dev/null 2>&1; then
            local end_time=$(date +%s.%N)
            local resolve_time=$(echo "$end_time - $start_time" | bc)
            
            log_info "DNS [$dns]: 解析成功 (${resolve_time}s)"
        else
            send_alert "DNS解析失败: $dns"
        fi
    done
}

# 监控网络端口
monitor_ports() {
    log_info "监控网络端口"
    
    local ports=(22 80 443 3306 3389)
    
    for port in "${ports[@]}"; do
        local listening=$(ss -tln | grep -c ":$port ")
        
        if [ $listening -gt 0 ]; then
            log_info "端口 $port: 监听中"
        else
            log_warning "端口 $port: 未监听"
        fi
    done
}

# 生成网络报告
generate_report() {
    local date=$(date +%Y-%m-%d)
    local report_file="/tmp/network_report_$date.txt"
    
    {
        echo "网络监控报告"
        echo "============"
        echo "生成时间: $(date)"
        echo ""
        
        echo "===== 网络接口 ====="
        ip addr
        echo ""
        
        echo "===== 路由表 ====="
        ip route
        echo ""
        
        echo "===== 连接统计 ====="
        ss -s
        echo ""
        
        echo "===== 监听端口 ====="
        ss -tln
        echo ""
        
        echo "===== 网络统计 ====="
        cat /proc/net/netstat
    } > "$report_file"
    
    log_info "网络报告已生成: $report_file"
}

# 主监控循环
main() {
    log_info "===== 开始网络监控 ====="
    log_info "监控间隔: ${INTERVAL}秒"
    
    # 生成初始报告
    generate_report
    
    # 监控循环
    while true; do
        log_info "===== 执行网络监控检查 ====="
        
        # 执行各项监控
        monitor_interface_status
        monitor_connections
        monitor_traffic
        monitor_latency
        monitor_dns
        monitor_ports
        
        # 等待下一次监控
        sleep $INTERVAL
    done
}

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

# 执行主函数
main "$@"

使用说明#

  1. 修改配置变量:

    • LOG_FILE: 日志文件路径
    • ALERT_LOG: 告警日志路径
    • INTERVAL: 监控间隔(秒)
    • PING_TARGET: ping测试目标
    • BANDWIDTH_THRESHOLD: 带宽阈值(字节/秒)
    • CONNECTION_THRESHOLD: 连接数阈值
    • ALERT_EMAIL: 告警邮件接收者
  2. 添加执行权限:

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

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

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

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

功能特点#

  • 网络接口状态监控
  • 网络连接监控
  • 网络流量监控
  • 网络延迟监控
  • DNS解析监控
  • 网络端口监控
  • 可配置的告警阈值
  • 详细的监控日志
  • 网络报告生成

依赖项#

  • ip: 用于网络接口管理
  • ss: 用于网络连接查看
  • ping: 用于延迟测试
  • nslookup: 用于DNS测试
  • bc: 用于数值计算
  • mail: 用于邮件告警(可选)

注意事项#

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