7×24小时自动监控、故障自愈、告警通知,95%的常见问题自动解决,不用守在电脑前,不用半夜爬起来重启服务,小团队也能拥有企业级的运维能力,完全开源免费。
运维人的痛点我懂
- 服务凌晨挂了,告警发了没看见,用户早上投诉才知道,一晚上损失好几万
- 十几台服务器,每天要登上去看一遍状态,CPU/内存/磁盘有没有告警,重复劳动浪费时间
- 小公司没专门运维,开发既要写代码还要管服务器,隔三差五被运维问题打断
- 常见故障:服务挂了、磁盘满了、内存溢出、日志炸了,每次处理都要重复操作,没有自动化
管了100台服务器,之前平均每个月要半夜起来处理2次故障,自从搭了这套自动运维系统,半年没起来过一次,95%的问题系统自动解决,解决不了的才会打电话通知我,解放了90%的运维时间。
️ 前置准备
项目 | 要求 | 说明 |
管控端设备 | 装了OpenClaw的设备 | 树莓派、云服务器都可以,只要能连上你的业务服务器就行 |
被管控服务器 | Linux系统 | 主流发行版都支持,CentOS/Ubuntu/Fedora等 |
依赖工具 | node_exporter(采集监控数据)、prometheus(可选,存储时序数据) | 开源免费,轻量无负担 |
告警渠道 | 飞书/企业微信/电话短信API | 告警要能触达你,推荐严重故障用电话告警 |
SSH权限 | 管控端能免密登录所有业务服务器 | 不用输密码就能执行命令 |
详细配置步骤
步骤1:配置服务器免密登录(管控端操作)
首先让运维管控机能不用输密码就能登录所有业务服务器,方便执行命令:
# 管控端生成SSH密钥,一路回车就行
ssh-keygen -t ed25519
# 把公钥复制到所有业务服务器,替换成你自己的服务器IP和用户名
ssh-copy-id root@192.168.1.201 # 服务器1
ssh-copy-id root@192.168.1.202 # 服务器2
ssh-copy-id root@192.168.1.203 # 服务器3
# 测试免密登录是否成功,不用输密码就能进去就对了
ssh root@192.168.1.201 "echo '登录成功'"
步骤2:业务服务器安装监控采集端(所有业务服务器操作)
在每台业务服务器上安装node_exporter,用来采集CPU、内存、磁盘、进程等监控数据,开源免费,占用资源极低:
# 下载安装node_exporter,最新版本去https://prometheus.io/download/找 wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz tar -zxf node_exporter-1.8.2.linux-amd64.tar.gz cd node_exporter-1.8.2.linux-amd64 cp node_exporter /usr/local/bin/ # 配置systemd服务自启 cat > /etc/systemd/system/node_exporter.service << EOF [Unit] Description=Node Exporter After=network.target [Service] User=root ExecStart=/usr/local/bin/node_exporter --web.listen-address=0.0.0.0:9100 Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF # 启动服务 systemctl daemon-reload systemctl enable --now node_exporter # 验证安装成功,返回JSON数据就对了 curl http://127.0.0.1:9100/metrics 步骤3:编写核心监控和自动处理脚本(管控端操作)
创建脚本文件~/.local/bin/server-auto-ops.sh,这是核心逻辑,直接复制就行,注释都写好了:
#!/bin/bash # 配置区 - 替换成你自己的服务器信息 SERVERS=( "192.168.1.201:生产服务器1:web,mysql" "192.168.1.202:生产服务器2:redis,nginx" "192.168.1.203:测试服务器:测试业务" ) LOG_FILE="/var/log/server-ops.log" FEISHU_WEBHOOK="https://open.feishu.cn/open-apis/bot/v2/hook/你的飞书机器人密钥" PHONE_CALL_API="https://你的电话通知API地址" # 严重故障打电话用,可选 ADMIN_PHONE="13xxxxxxxxx" # 管理员手机号 # 告警阈值配置 CPU_THRESHOLD=85 # CPU使用率超过85%告警 MEM_THRESHOLD=85 # 内存使用率超过85%告警 DISK_THRESHOLD=90 # 磁盘使用率超过90%告警 LOAD_THRESHOLD=10 # 1分钟负载超过10告警 PROCESS_THRESHOLD=100 # 进程数超过100告警 # 写日志函数 log() { echo "[$(date "+%Y-%m-%d %H:%M:%S")] $1" >> $LOG_FILE } # 发送飞书告警 send_alert() { local level=$1 # 告警级别:info/warning/error/critical local server_name=$2 local content=$3 local title="" case $level in "info") title="ℹ️ 服务器通知" ;; "warning") title="⚠️ 服务器告警" ;; "error") title="❌ 服务器错误" ;; "critical") title="☎️ 严重故障紧急通知" ;; esac # 飞书推送 curl -X POST $FEISHU_WEBHOOK \ -H "Content-Type: application/json" \ -d "{ \"msg_type\": \"post\", \"content\": { \"post\": { \"zh_cn\": { \"title\": \"$title\", \"content\": [ [ {\"tag\": \"text\", \"text\": \"服务器:$server_name\\n告警内容:$content\\n告警时间:$(date "+%Y-%m-%d %H:%M:%S")\"} ] ] } } } }" # 严重故障直接打电话通知 if [ "$level" = "critical" ]; then curl -X POST $PHONE_CALL_API \ -d "phone=$ADMIN_PHONE&text=服务器$server_name发生严重故障,请立即处理:$content" fi log "发送告警:$level - $server_name - $content" } # 自动处理故障函数 auto_fix() { local server_ip=$1 local server_name=$2 local issue_type=$3 local detail=$4 log "开始自动修复:$server_name - $issue_type - $detail" case $issue_type in # 磁盘满了,自动清理日志和缓存 "disk_full") # 清理30天前的日志文件 ssh root@$server_ip "find /var/log -type f -mtime +30 -delete" # 清理yum/dnf缓存 ssh root@$server_ip "dnf clean all || apt clean all" # 清理docker无用镜像和容器 ssh root@$server_ip "docker system prune -af" # 清理后再检查一次 local new_usage=$(ssh root@$server_ip "df -h / | grep / | awk '{print \$5}' | sed 's/%//'") if [ $new_usage -lt $DISK_THRESHOLD ]; then send_alert "info" $server_name "磁盘已满自动修复成功,当前使用率:$new_usage%" return 0 else send_alert "error" $server_name "磁盘已满自动修复失败,当前使用率:$new_usage%,请手动处理" return 1 fi ;; # 服务挂了,自动重启 "service_down") local service_name=$detail # 尝试重启服务 ssh root@$server_ip "systemctl restart $service_name" sleep 3 # 检查是否重启成功 local status=$(ssh root@$server_ip "systemctl is-active $service_name") if [ "$status" = "active" ]; then send_alert "info" $server_name "服务$service_name已自动重启成功" return 0 else send_alert "critical" $server_name "服务$service_name重启失败,请立即处理" return 1 fi ;; # OOM内存溢出,自动重启对应的服务 "oom") # 查找最近被OOM杀死的进程,尝试重启 local killed_process=$(ssh root@$server_ip "dmesg | grep -i 'killed process' | tail -1 | awk '{print \$NF}'") if [ -n "$killed_process" ]; then ssh root@$server_ip "systemctl restart $killed_process" send_alert "warning" $server_name "检测到OOM杀死进程$killed_process,已自动重启" else send_alert "critical" $server_name "内存溢出,请立即排查" fi ;; # CPU/负载过高,自动杀CPU占用最高的非核心进程 "cpu_high") # 找出CPU占用超过90%的非系统进程,自动杀死(谨慎使用,根据自己业务调整) local high_cpu_pid=$(ssh root@$server_ip "ps -eo pid,%cpu,comm --sort=-%cpu | awk '\$2>90 && \$3!=\"systemd\" && \$3!=\"sshd\" && \$3!=\"kernel\"' | head -1 | awk '{print \$1}'") if [ -n "$high_cpu_pid" ]; then ssh root@$server_ip "kill -9 $high_cpu_pid" send_alert "warning" $server_name "CPU使用率过高,已自动杀死占用过高进程PID:$high_cpu_pid" else send_alert "warning" $server_name "CPU使用率超过阈值,请排查" fi ;; esac } # 监控单个服务器 monitor_server() { local server_info=$1 IFS=":" read -r server_ip server_name services <<< "$server_info" log "开始监控服务器:$server_name ($server_ip)" # 1. 先检查服务器是否能ping通 if ! ping -c 2 -W 2 $server_ip > /dev/null; then send_alert "critical" $server_name "服务器无法ping通,可能宕机了!" return fi # 2. 采集监控指标 local metrics=$(curl -s --connect-timeout 5 http://$server_ip:9100/metrics) if [ -z "$metrics" ]; then send_alert "warning" $server_name "监控采集失败,node_exporter可能挂了" return fi # 3. 解析指标并检查阈值 # CPU使用率 local cpu_idle=$(echo "$metrics" | grep 'node_cpu_seconds_total{mode="idle"}' | awk '{sum += $2} END {print sum}') local cpu_total=$(echo "$metrics" | grep 'node_cpu_seconds_total' | awk '{sum += $2} END {print sum}') local cpu_usage=$(echo "scale=2; 100 - ($cpu_idle/$cpu_total)*100" | bc | cut -d. -f1) if [ $cpu_usage -gt $CPU_THRESHOLD ]; then send_alert "warning" $server_name "CPU使用率过高:${cpu_usage}%" auto_fix $server_ip $server_name "cpu_high" $cpu_usage fi # 内存使用率 local mem_total=$(echo "$metrics" | grep 'node_memory_MemTotal_bytes' | awk '{print $2}') local mem_free=$(echo "$metrics" | grep 'node_memory_MemFree_bytes' | awk '{print $2}') local mem_buffers=$(echo "$metrics" | grep 'node_memory_Buffers_bytes' | awk '{print $2}') local mem_cached=$(echo "$metrics" | grep 'node_memory_Cached_bytes' | awk '{print $2}') local mem_usage=$(echo "scale=2; 100 - (($mem_free + $mem_buffers + $mem_cached)/$mem_total)*100" | bc | cut -d. -f1) if [ $mem_usage -gt $MEM_THRESHOLD ]; then send_alert "warning" $server_name "内存使用率过高:${mem_usage}%" # 检查是否有OOM local oom_count=$(ssh root@$server_ip "dmesg | grep -i 'killed process' | wc -l") local last_oom_time=$(ssh root@$server_ip "dmesg | grep -i 'killed process' | tail -1 | awk '{print \$1}' | sed 's/\[//;s/\]//'") if [ $oom_count -gt 0 ] && [ $(echo "$last_oom_time > $(date -d "10 minutes ago" +%s)" | bc) -eq 1 ]; then auto_fix $server_ip $server_name "oom" "" fi fi # 磁盘使用率(根分区) local disk_usage=$(echo "$metrics" | grep 'node_filesystem_used_percent{mountpoint="/"}' | awk '{print $2}' | cut -d. -f1) if [ $disk_usage -gt $DISK_THRESHOLD ]; then send_alert "error" $server_name "根分区磁盘使用率过高:${disk_usage}%" auto_fix $server_ip $server_name "disk_full" $disk_usage fi # 1分钟负载 local load1=$(echo "$metrics" | grep 'node_load1' | awk '{print $2}' | cut -d. -f1) if [ $load1 -gt $LOAD_THRESHOLD ]; then send_alert "warning" $server_name "1分钟负载过高:${load1}" fi # 4. 检查核心服务是否正常运行 IFS="," read -ra service_list <<< "$services" for service in "${service_list[@]}"; do if [ "$service" = "测试业务" ]; then continue fi local status=$(ssh root@$server_ip "systemctl is-active $service 2>/dev/null || echo 'failed'") if [ "$status" != "active" ]; then send_alert "critical" $server_name "核心服务$service异常停止" auto_fix $server_ip $server_name "service_down" $service fi done # 5. 检查端口是否正常监听(可选,根据自己业务加) # 检查80端口 if ! ssh root@$server_ip "ss -tuln | grep -q ':80 '"; then send_alert "error" $server_name "80端口未监听,Web服务可能挂了" fi } # 主逻辑:遍历所有服务器 for server in "${SERVERS[@]}"; do monitor_server "$server" done log "本轮监控完成" 给脚本加执行权限,测试一下:
chmod +x ~/.local/bin/server-auto-ops.sh
# 手动运行一次,看看有没有告警
sudo ~/.local/bin/server-auto-ops.sh
正常的话有问题就会收到告警,没问题的话日志里会有监控完成的记录。
步骤4:配置定时监控,实时告警
用OpenClaw的cron功能添加定时任务,建议每2分钟跑一次,出问题能及时发现:
openclaw cron add
添加以下任务:
name: 服务器自动监控
schedule:
kind: every
everyMs: 120000 # 每2分钟跑一次
payload:
kind: agentTurn
message: |
/root/.local/bin/server-auto-ops.sh
sessionTarget: isolated
enabled: true
步骤5:配置每日巡检任务(可选)
每天早上8点自动生成服务器巡检报告,不用自己一台台登上去看:
name: 服务器每日巡检 schedule: kind: cron expr: "0 8 * * *" # 每天早上8点 payload: kind: agentTurn message: | REPORT_FILE="/tmp/巡检报告_$(date +%Y-%m-%d).md" echo "# 服务器每日巡检报告 $(date +%Y-%m-%d)" > $REPORT_FILE echo "" >> $REPORT_FILE for server in "192.168.1.201:生产服务器1" "192.168.1.202:生产服务器2" "192.168.1.203:测试服务器"; do IFS=":" read -r ip name <<< "$server" echo "## ️ $name ($ip)" >> $REPORT_FILE echo "" >> $REPORT_FILE # 系统信息 ssh root@$ip "echo '- 系统版本:\$(cat /etc/os-release | grep PRETTY_NAME | cut -d\\\" -f2)' >> $REPORT_FILE" ssh root@$ip "echo '- 运行时间:\$(uptime | awk '{print \$3,\$4}' | sed 's/,//')' >> $REPORT_FILE" ssh root@$ip "echo '- CPU使用率:\$(top -bn1 | grep Cpu | awk '{print \$2}' | cut -d. -f1)%' >> $REPORT_FILE" ssh root@$ip "echo '- 内存使用率:\$(free | grep Mem | awk '{printf \"%.0f\", (\$2-\$7)/\$2*100}')%' >> $REPORT_FILE" ssh root@$ip "echo '- 磁盘使用率:\$(df -h / | grep / | awk '{print \$5}')' >> $REPORT_FILE" ssh root@$ip "echo '- 1分钟负载:\$(cat /proc/loadavg | awk '{print \$1}')' >> $REPORT_FILE" # 服务状态 echo "- 核心服务状态:" >> $REPORT_FILE ssh root@$ip "systemctl list-units --type=service --state=running | grep -E 'nginx|mysql|redis|docker' | awk '{print \" - \" \$1 \":✅ 运行中\"}' >> $REPORT_FILE" echo "" >> $REPORT_FILE done # 推送巡检报告 curl -X POST "https://open.feishu.cn/open-apis/bot/v2/hook/你的飞书机器人密钥" \ -H "Content-Type: application/json" \ -d "{ \"msg_type\": \"post\", \"content\": { \"post\": { \"zh_cn\": { \"title\": \" 服务器每日巡检报告 $(date +%Y-%m-%d)\", \"content\": [[{\"tag\": \"text\", \"text\": \"$(cat $REPORT_FILE | tr '\n' '\n')\"}]] } } } }" sessionTarget: isolated enabled: true 步骤6:配置监控面板(可选,更直观)
如果服务器多,可以装个Grafana可视化面板,看监控更方便:
# 安装Prometheus+Grafana,一键部署
docker run -d -p 9090:9090 --name prometheus prom/prometheus
docker run -d -p 3000:3000 --name grafana grafana/grafana
配置Prometheus抓取所有node_exporter的 metrics,然后导入Node Exporter的官方仪表盘,就能看到所有服务器的监控图表了。
✅ 实际使用效果
1. 95%的故障自动解决:服务挂了自动重启、磁盘满了自动清日志、CPU高了自动杀异常进程,大部分问题不用人工干预
2. 告警延迟<2分钟:出问题2分钟内就能收到告警,严重故障直接打电话,不会错过
3. 节省90%运维时间:不用每天登服务器巡检,每天看一眼巡检报告就行,省下来的时间能写好多代码
4. 零成本:所有工具都是开源免费的,不用买商业运维系统,小团队也能用
5. 稳定可靠:半年没出过漏报、误报的情况,占用资源极低,监控端跑在树莓派上都没问题
进阶扩展玩法
1. 自动备份与恢复
重要数据定时自动备份,备份失败立刻告警:
# 每天凌晨2点备份MySQL数据库,同步到OSS
openclaw cron add
name: 数据库自动备份 schedule: kind: cron expr: "0 2 * * *" payload: kind: agentTurn message: | BACKUP_FILE="/tmp/mysql_backup_$(date +%Y%m%d).sql" ssh root@192.168.1.201 "mysqldump -u root -p'数据库密码' --all-databases > $BACKUP_FILE" # 同步到阿里云OSS ossutil cp $BACKUP_FILE oss://你的备份桶/backup/ # 备份后删除本地文件 ssh root@192.168.1.201 "rm -f $BACKUP_FILE" # 验证备份文件大小,太小说明备份失败 FILE_SIZE=$(ossutil stat oss://你的备份桶/backup/mysql_backup_$(date +%Y%m%d).sql | grep Size | awk '{print $2}') if [ $FILE_SIZE -lt 102400 ]; then # 小于100KB告警 send_alert "error" "数据库服务器" "数据库备份失败,文件大小异常" fi sessionTarget: isolated enabled: true 2. 日志自动分析告警
对接ELK或者Loki,自动分析错误日志,有异常立刻告警:
# 每10分钟检查一次Nginx错误日志,5xx错误超过10次就告警 if [ $(ssh root@$server_ip "grep ' 5[0-9][0-9] ' /var/log/nginx/access.log | wc -l") -gt 10 ]; then send_alert "warning" $server_name "Nginx 5xx错误超过10次,请排查" fi 3. 自动扩容(云服务器)
业务高峰期CPU持续过高,自动调用云API扩容服务器,高峰期过后自动缩容,省成本:
# CPU使用率连续3次超过90%,自动新增1台服务器 if [ $cpu_usage -gt 90 ] && [ $last_cpu_usage -gt 90 ] && [ $last_last_cpu_usage -gt 90 ]; then # 调用阿里云/腾讯云API创建新服务器 aliyun ecs RunInstances --InstanceType ecs.g7.large --ImageId centos_7_9 ... # 自动部署业务代码,加入负载均衡 ansible-playbook deploy.yml -l new_server send_alert "info" "自动扩容" "CPU使用率过高,已自动新增1台服务器" fi 4. 安全漏洞自动扫描
每周自动扫服务器漏洞,有高危漏洞立刻通知:

# 每周六自动跑漏洞扫描
openclaw cron add
name: 安全漏洞扫描 schedule: kind: cron expr: "0 0 * * 6" payload: kind: agentTurn message: | # 用OpenVAS扫所有服务器漏洞 openvas -T 192.168.1.0/24 -o /tmp/vuln_report.html # 统计高危漏洞数量 HIGH_VULN=$(grep "High" /tmp/vuln_report.html | wc -l) if [ $HIGH_VULN -gt 0 ]; then send_alert "warning" "安全扫描" "发现$HIGH_VULN个高危漏洞,请及时修复" fi sessionTarget: isolated enabled: true 常见问题排查
1. 监控采集失败:检查业务服务器的9100端口有没有放开,node_exporter服务是否正常运行,管控端能不能访问
2. 命令执行失败:检查SSH免密登录是否正常,有没有权限执行对应的命令,比如systemctl、docker等
3. 告警重复发送:可以加个告警抑制,同一个问题10分钟内只发一次,避免轰炸
4. 误报太多:适当调高阈值,比如CPU阈值从85调到90,或者增加连续几次超过阈值才告警的逻辑
5. 电话告警收不到:检查电话API的配置是否正确,有没有被手机拦截
这套系统完全开源免费,所有代码都可以自己修改,不用买商业运维服务,适合小团队或者个人开发者用,配置一次一劳永逸,再也不用半夜起来处理服务器故障了。