服务器状态监控

背景介绍

我用Ubuntu 20.04搭建了一个小型的Linux服务器,并在局域网内用Windows电脑通过SSH连接这台服务器进行代码开发、编译等工作。服务器是通过一个USB无线网卡连接到路由器的WiFi。使用过程中经常遇到SSH连不上的情况,经过检查发现要么是服务器的WiFi断了,要么是服务器的某些核心进程卡死(怀疑也是断网导致的),且我设置了WiFi重连服务也不起作用。于是决定写一个状态监控服务,时刻盯着这台服务器的状态,一旦发现异常就尝试恢复。经过一番摸索,总结了下面这套十分奏效的方案。

实现步骤

1、创建一体化监控脚本

bash 复制代码
sudo touch /usr/local/bin/unified-watchdog.sh

粘贴以下核心脚本(请仔细阅读注释,特别是需要你确认的配置项):

bash 复制代码
#!/bin/bash
# 一体化监控服务 v3.0
# 设计原则:网络监控与系统心跳在独立子进程中运行,完全隔离

LOG_DIR="/var/log/unified-watchdog"
mkdir -p "$LOG_DIR"
NET_LOG="$LOG_DIR/network.log"
SYS_LOG="$LOG_DIR/system.log"
MAIN_LOG="$LOG_DIR/main.log"

# ========== 【请确认】你的网络配置 ==========
WIFI_INTERFACE="xxxxxxxxxxxxxxx"   # 你的WiFi网卡接口名
CONNECTION_NAME="xxxxxxxx"         # 你的WiFi名称
TEST_HOST="192.168.10.58"          # 你的Windows电脑IP(用于测试)
GATEWAY="192.168.10.1"             # 你的路由器网关IP(用`ip route show default`查看)
# ==========================================

log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$MAIN_LOG"
}

# 函数:网络监控进程(专注于WiFi恢复)
network_monitor() {
    log "网络监控子进程启动"
    echo "$(date) 网络监控启动" >> "$NET_LOG"
    
    local last_problem=""
    local healthy_count=0
    
    while true; do
        # 诊断当前网络状态(分层诊断)
        local problem=""
        
        # 1. 物理层检查
        if ! ip link show "$WIFI_INTERFACE" 2>/dev/null | grep -q "state UP"; then
            problem="PHY_DOWN"
        # 2. 网络层检查
        elif ! ping -c 2 -W 1 -I "$WIFI_INTERFACE" "$GATEWAY" >/dev/null 2>&1; then
            problem="GATEWAY_UNREACHABLE"
        # 3. 传输层检查(TCP连通性)
        elif ! timeout 3 curl -s --interface "$WIFI_INTERFACE" http://connect.rom.miui.com/generate_204 >/dev/null 2>&1; then
            problem="INTERNET_BLOCKED"
        fi
        
        # 根据问题类型执行恢复
        if [ -n "$problem" ]; then
            echo "$(date) 检测到问题: $problem" >> "$NET_LOG"
            
            # 避免对同一问题重复恢复
            if [ "$problem" != "$last_problem" ] || [ $healthy_count -gt 3 ]; then
                case $problem in
                    PHY_DOWN)
                        echo "$(date) 执行: 重启接口" >> "$NET_LOG"
                        ip link set "$WIFI_INTERFACE" down
                        sleep 2
                        ip link set "$WIFI_INTERFACE" up
                        ;;
                    GATEWAY_UNREACHABLE)
                        echo "$(date) 执行: 刷新DHCP" >> "$NET_LOG"
                        nmcli connection down "$CONNECTION_NAME"
                        sleep 3
                        nmcli connection up "$CONNECTION_NAME"
                        ;;
                    INTERNET_BLOCKED)
                        echo "$(date) 执行: 刷新DNS和路由" >> "$NET_LOG"
                        systemctl restart systemd-resolved
                        sleep 2
                        ;;
                esac
                last_problem="$problem"
                healthy_count=0
            fi
        else
            # 网络健康
            if [ -n "$last_problem" ]; then
                echo "$(date) 网络恢复健康" >> "$NET_LOG"
                last_problem=""
            fi
            ((healthy_count++))
        fi
        
        # 动态检查间隔:有问题时检查密,健康时检查疏
        if [ -n "$problem" ]; then
            sleep 15
        elif [ $healthy_count -lt 5 ]; then
            sleep 20
        else
            sleep 45  # 长期健康后降低检查频率
        fi
    done
}

# 函数:系统心跳监控进程(绝不操作网络)
system_heartbeat() {
    log "系统心跳子进程启动"
    echo "$(date) 系统心跳启动" >> "$SYS_LOG"
    
    local stall_count=0
    local max_stalls=180  # 3分钟无响应才触发恢复
    
    while true; do
        # 仅测试最基本系统功能(不涉及网络)
        # 1. 测试文件系统响应
        if ! touch /tmp/.heartbeat_test 2>/dev/null; then
            echo "$(date) 警告: 文件系统响应慢" >> "$SYS_LOG"
            ((stall_count++))
        # 2. 测试内核proc接口响应
        elif ! timeout 1 cat /proc/uptime >/dev/null 2>&1; then
            echo "$(date) 警告: 内核接口响应慢" >> "$SYS_LOG"
            ((stall_count++))
        # 3. 测试进程调度(简单计算)
        elif ! expr 1 + 1 >/dev/null 2>&1; then
            echo "$(date) 警告: 进程调度异常" >> "$SYS_LOG"
            ((stall_count++))
        else
            # 系统正常
            if [ $stall_count -gt 0 ]; then
                echo "$(date) 系统恢复响应" >> "$SYS_LOG"
                stall_count=0
            fi
        fi
        
        # 仅在持续卡死时才采取行动
        if [ $stall_count -ge $max_stalls ]; then
            echo "$(date) 警报: 系统持续无响应,执行安全重启" >> "$SYS_LOG"
            # 只重启非关键服务,避免影响网络
            systemctl --no-block restart systemd-journald
            sleep 10
            # 如果仍无响应,计划延迟重启(给手动干预机会)
            if ! timeout 2 cat /proc/uptime >/dev/null 2>&1; then
                echo "$(date) 计划5分钟后重启系统" >> "$SYS_LOG"
                shutdown -r +5 "系统看门狗触发安全重启"
            fi
            stall_count=0
        fi
        
        sleep 5  # 系统检查间隔较短,但恢复阈值很高
    done
}

# 主进程:启动并监控两个子进程
log "一体化监控服务启动"
echo "==========================================" >> "$MAIN_LOG"
echo "服务启动时间: $(date)" >> "$MAIN_LOG"
echo "网络接口: $WIFI_INTERFACE" >> "$MAIN_LOG"
echo "连接名称: $CONNECTION_NAME" >> "$MAIN_LOG"
echo "==========================================" >> "$MAIN_LOG"

# 启动网络监控子进程(后台运行)
network_monitor &
NET_PID=$!
log "网络监控PID: $NET_PID"

# 启动系统心跳子进程(后台运行)
system_heartbeat &
SYS_PID=$!
log "系统心跳PID: $SYS_PID"

# 主进程监控子进程状态
while true; do
    if ! kill -0 $NET_PID 2>/dev/null; then
        log "网络监控进程异常退出,重启中..."
        network_monitor &
        NET_PID=$!
    fi
    
    if ! kill -0 $SYS_PID 2>/dev/null; then
        log "系统心跳进程异常退出,重启中..."
        system_heartbeat &
        SYS_PID=$!
    fi
    
    # 主进程每30秒记录一次状态
    sleep 30
    if [ $(( $(date +%s) % 300 )) -lt 30 ]; then
        log "运行中: 网络PID=$NET_PID, 系统PID=$SYS_PID"
    fi
done

2、设置权限和Systemd服务

bash 复制代码
# 设置脚本权限
sudo chmod +x /usr/local/bin/unified-watchdog.sh

# 创建服务文件
sudo touch /etc/systemd/system/unified-watchdog.service

粘贴以下服务配置:

bash 复制代码
[Unit]
Description=Unified WiFi and System Watchdog Service
After=network.target NetworkManager.service
Wants=NetworkManager.service

[Service]
Type=simple
ExecStart=/usr/local/bin/unified-watchdog.sh
Restart=always
RestartSec=10
User=root

# 资源限制,确保服务不会占用过多系统资源
CPUQuota=10%
MemoryLimit=50M
IOWeight=10

# 日志配置
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=unified-watchdog

[Install]
WantedBy=multi-user.target

3、启用并测试新服务

bash 复制代码
# 1. 查看服务状态
sudo systemctl status unified-watchdog.service

# 2. 查看各模块日志
sudo tail -20 /var/log/unified-watchdog/main.log    # 主进程日志
sudo tail -20 /var/log/unified-watchdog/network.log # 网络监控日志
sudo tail -20 /var/log/unified-watchdog/system.log  # 系统心跳日志


# 3. 停止服务(如需调整配置)
sudo systemctl stop unified-watchdog.service

4、结束

相关推荐
等什么君!2 小时前
练习-部署nginx和部署tomcat
运维·nginx·docker
IDC02_FEIYA2 小时前
Discuz!论坛注册验证邮箱收不到邮件怎么办?邮件检测发送成功,但是收发邮箱都未看到邮件
linux·服务器·阿里云
TTBIGDATA2 小时前
【Knox】Apache Knox 2.1.0 ,开启Kerberos 后,Invalid keystore format 问题处理
运维·开源·ambari·hdp·kerberos·knox·bigtop
_OP_CHEN2 小时前
【Linux系统编程】(二十一)吃透 Linux “一切皆文件” 与缓冲区:从底层逻辑到实战封装
linux·操作系统·glibc·c/c++·缓冲区·linux文件·io库
Jtti2 小时前
怎么避免国外服务器的丢包问题?
运维·服务器
源远流长jerry2 小时前
dpdk之tcp代码案例
服务器·网络·tcp/ip
m0_737302582 小时前
腾讯云TDSQL-C+CVM,软硬协同驱动数据库性能革命
服务器
2501_945837432 小时前
腾讯云星星海S7,风冷液冷双适配引领绿色算力
服务器
147API2 小时前
用 clawdbot 做自动化:任务编排、触发器与可观测性
运维·自动化·clawdbot