我用Claude Code写了个服务器巡检工具,它真的理解了我的代码
我用Claude Code写了个服务器巡检工具,它真的理解了我的代码
作者:Koen
7年Java后端 → 全栈独立开发者
1. 为什么要写
我以前做Java后端的时候,服务器巡检这件事基本靠两种方式:一是登录机器手动看,二是等报警系统叫。
听起来也没什么问题,但真放到个人服务器、独立项目、小团队环境里,就会发现很难受。
比如我自己的服务器上跑了一堆东西:业务容器、MySQL、Redis、Nginx/OpenResty、各种自动化脚本、Agent服务、定时任务、Webhook推送。平时没事的时候它们都很安静,一旦出问题,通常不是一个点坏了,而是一串连锁反应。
磁盘快满了,日志开始刷爆;
某个容器挂了,反代还活着,但业务已经打不开;
定时任务失败了,没人知道;
接口偶发超时,等用户反馈已经晚了。
我最早的处理方式很原始:
df -h
free -h
docker ps
docker logs xxx --tail=100
systemctl status xxx
每次都要敲一遍,越敲越烦。
后来我想,与其每次人工排查,不如写一个巡检工具,每天定时跑一次,把服务器状态整理成一份报告。如果有异常,就直接推送给我;如果没异常,就安静别烦我。
需求很简单:
- 检查CPU、内存、磁盘
- 检查Docker容器状态
- 检查关键端口和服务
- 检查最近的错误日志
- 输出一份人能看懂的报告
- 异常时推送通知
- 尽量不要引入复杂依赖
如果按以前的方式,我大概会先建个Java项目,写配置文件,搞定时任务,接日志框架,再封装一堆检测类。不是不能写,但有点杀鸡用牛刀。
这类工具最适合shell + python。
shell负责拿系统信息,Python负责分析和生成报告。简单、直接、可维护。
于是我把这个需求丢给了Claude Code。
2. Claude Code怎么理解需求
我给Claude Code的第一版描述大概是这样的:
帮我写一个服务器巡检工具。
运行环境是Ubuntu服务器。
用shell收集系统状态,用python分析结果并生成报告。
需要检查:
- CPU负载
- 内存使用率
- 磁盘使用率
- Docker容器状态
- 关键端口监听情况
- 最近系统错误日志
- 最近Docker容器错误日志
输出Markdown报告。
如果发现异常,输出ALERTS数量和异常原因。
脚本要适合放到cron里每天执行。
这个提示词不算复杂,但我发现Claude Code处理这种任务有个特点:它不会只写一个脚本,而是会先理解"这个东西要怎么长期运行"。
它给我的第一版方案是三层:
check.sh # 主入口,负责采集和调度
analyze.py # 分析采集结果,生成报告
reports/ # 存放历史报告
我觉得这个拆分挺合理。
因为shell做系统采集很方便,比如:
df -h
free -m
uptime
docker ps -a
ss -lntp
journalctl -p err
但shell不适合做复杂判断和格式化报告。你当然可以用awk、sed硬写,但写到后面基本没人想维护。
Python刚好补上这部分。
Claude Code还主动考虑了几个点:
- 报告文件按日期命名
- 保留最近N份报告,避免无限增长
- 检测项要有阈值
- 异常数量要结构化输出
- cron执行时不能依赖交互环境
- 命令失败不能让整个脚本直接崩掉
这点让我挺满意。它不是简单给你一坨"能跑"的代码,而是会按一个小工具的形态去组织。
当然,第一版肯定不能直接上线。AI写运维脚本,必须人工过一遍。尤其是涉及磁盘、容器、日志、权限的地方,不能盲信。
3. 代码实现:shell + python巡检脚本
最后我保留了两个核心脚本。
第一个是check.sh,负责采集数据。
简化版大概长这样:
#!/usr/bin/env bash
set -u
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
REPORT_DIR="$BASE_DIR/reports"
TMP_DIR="$BASE_DIR/tmp"
mkdir -p "$REPORT_DIR" "$TMP_DIR"
SNAPSHOT="$TMP_DIR/snapshot.txt"
{
echo "===== BASIC ====="
date
hostname
uptime
echo
echo "===== DISK ====="
df -h
echo
echo "===== MEMORY ====="
free -m
echo
echo "===== DOCKER ====="
if command -v docker >/dev/null 2>&1; then
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
else
echo "docker not installed"
fi
echo
echo "===== PORTS ====="
ss -lntp || true
echo
echo "===== SYSTEM ERRORS ====="
journalctl -p err -n 80 --no-pager 2>/dev/null || true
} > "$SNAPSHOT"
python3 "$BASE_DIR/analyze.py" "$SNAPSHOT" "$REPORT_DIR"
这里我没有追求特别复杂。
运维脚本最重要的不是炫技,而是稳定。能在cron里跑,路径固定,失败可控,输出清楚,这就够了。
第二个是analyze.py,负责分析和生成报告。
核心逻辑类似这样:
#!/usr/bin/env python3
import sys
import re
from datetime import datetime
from pathlib import Path
DISK_WARN = 80
DISK_CRITICAL = 90
MEM_WARN = 80
def parse_disk(snapshot: str):
alerts = []
for line in snapshot.splitlines():
parts = line.split()
if len(parts) < 6:
continue
usage = parts[4]
mount = parts[5]
if not usage.endswith("%"):
continue
try:
percent = int(usage.rstrip("%"))
except ValueError:
continue
if percent >= DISK_CRITICAL:
alerts.append(f"磁盘严重告警:{mount} 使用率 {percent}%")
elif percent >= DISK_WARN:
alerts.append(f"磁盘预警:{mount} 使用率 {percent}%")
return alerts
def parse_docker(snapshot: str):
alerts = []
docker_section = (
snapshot.split("===== DOCKER =====")[-1]
.split("===== PORTS =====")[0]
)
for line in docker_section.splitlines():
lower = line.lower()
if "exited" in lower or "dead" in lower or "restarting" in lower:
alerts.append(f"Docker容器异常:{line.strip()}")
return alerts
def generate_report(snapshot: str, alerts: list[str]):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
lines = [f"# 服务器巡检报告", "",
f"- 巡检时间:{now}", f"- 异常数量:{len(alerts)}", ""]
if alerts:
lines.append("## 异常列表")
lines.append("")
for item in alerts:
lines.append(f"- {item}")
lines.append("")
else:
lines.append("## 巡检结果")
lines.append("")
lines.append("当前未发现明显异常。")
lines.append("")
return "\n".join(lines)
shell只负责"拿事实":
df -h
free -m
docker ps -a
ss -lntp
journalctl -p err
Python负责"做判断":
if percent >= DISK_CRITICAL:
alerts.append(...)
最终输出也比较适合自动化系统读取:
REPORT=/path/to/reports/healthcheck-20260623-090000.md
ALERTS=2
ALERT: 磁盘预警:/ 使用率 83%
ALERT: Docker容器异常:api Exited (1) 2 hours ago
实际输出示例:这就是我SRE每日巡检脚本的格式。每天09:00自动跑,正常就静默,异常才推送。ALERTS=0时连报告都不发,只有异常了你才知道。
这样后面要接企业微信、Telegram、飞书、邮件都很方便。只要判断ALERTS > 0,再把报告推送出去就行。
我后来又加了一个报告清理逻辑,避免报告目录无限增长:
find "$REPORT_DIR" -name "healthcheck-*.md" -type f | sort | head -n -14 | xargs -r trash
这里我更推荐用trash而不是rm。巡检报告虽然不是核心数据,但能不硬删就别硬删。运维脚本里最怕一个路径变量为空,然后rm给你表演魔术。
4. 遇到的坑
这个工具看起来简单,但实际跑起来还是踩了几个坑。
第一个坑是cron环境变量太少。
你在终端里能跑,不代表cron里能跑。比如docker命令可能找不到,python3路径可能不一样,甚至当前目录都不是你以为的目录。
所以脚本里最好不要写相对路径:
BASE_DIR="$(cd "$(dirname "$0")" && pwd)"
命令也尽量做存在性检查:
if command -v docker >/dev/null 2>&1; then
docker ps -a
else
echo "docker not installed"
fi
第二个坑是权限。
journalctl和docker ps在某些机器上需要权限。你用自己的用户手动跑没问题,换成cron用户就失败了。
解决方式有两个:
一种是把脚本放到有权限的用户下跑。
另一种是给固定命令配置sudo免密。
但我不建议一上来就给整个脚本sudo权限。巡检脚本权限越大,出错时伤害也越大。
第三个坑是日志太多。
第一次我让脚本抓最近几百行错误日志,结果报告巨大,推送消息直接爆了。
后来改成两层:
- 报告文件里保留较完整内容
- 推送消息里只放摘要
比如推送内容只放:
服务器巡检发现 2 个异常:
1. 磁盘预警:/ 使用率 83%
2. Docker容器异常:api Exited (1) 2 hours ago
完整报告:/home/xxx/reports/healthcheck-xxx.md
第四个坑是AI喜欢写得太"完整"。
Claude Code很容易主动加配置文件、日志模块、通知模块、彩色输出、命令行参数。不是不好,但这个工具的核心目标是稳定巡检,不是做一个平台。
所以我会明确告诉它:
不要引入复杂框架。
不要做Web界面。
不要使用数据库。
脚本必须能直接在Ubuntu服务器运行。
优先稳定和可维护。
AI写代码时,边界越清楚,结果越靠谱。
第五个坑是阈值不能太敏感。
比如内存使用率在Linux上本来就容易看起来很高,因为系统会用空闲内存做缓存。如果简单按used / total判断,很容易误报。
更合理的方式是看available,或者用 (total - available) / total 来算。
5. 效果对比
写这个工具前,我的服务器巡检基本靠想起来。
有时候几天不看,一看发现某个容器已经重启几十次;有时候磁盘快满了,还是业务异常后才发现;还有时候定时任务失败了,但因为没通知,等于失败了个寂寞。
写完之后,流程变成这样:
每天定时执行 check.sh
↓
采集系统状态
↓
Python分析异常
↓
生成Markdown报告
↓
ALERTS > 0 时推送通知
↓
无异常就静默
最明显的变化是:我不用主动想"今天要不要看看服务器"。
它每天自己看。
如果没问题,我不需要知道。
如果有问题,它会把异常点列出来。
这比传统监控系统轻很多,也比纯手工靠谱很多。
当然,它替代不了Prometheus、Grafana、Zabbix这类完整监控方案。它没有时序数据,没有复杂图表,也没有多维度指标聚合。
但对独立开发者、小服务器、个人项目来说,这种轻量巡检工具反而刚好。
我不需要一个很重的平台来告诉我"磁盘80%了"。
我只需要每天有个脚本认真扫一遍,然后在该提醒我的时候提醒我。
Claude Code在这个过程里最大的价值,不是"帮我写了几行脚本"。
它真正省时间的地方在于:把一个模糊想法快速变成了可运行的工具骨架。
我不用从空文件开始想目录结构,不用纠结shell和Python怎么分工,也不用一点点补边界处理。它先给出一个可用版本,我再按自己的服务器环境调整。
这个协作方式很像带一个初级但手速很快的同事。
你不能完全放手,但你可以让它先干起来。你负责判断方向、补安全边界、做最终验收。
6. 总结
这次用Claude Code写服务器巡检工具,我最大的感受是:AI很适合写这种"需求明确、边界清楚、反馈快"的运维小工具。
它不需要特别复杂的架构,也不需要上来就工程化到极致。先让工具跑起来,先解决每天巡检的问题,再慢慢补通知、报告清理、异常分类、服务白名单,这个节奏更舒服。
如果你也有自己的服务器,我建议从一个最简单的巡检脚本开始:
df -h
free -m
docker ps -a
journalctl -p err -n 50
然后让AI帮你把这些输出整理成报告。
不要一开始就做大而全的监控系统。很多时候,一个每天自动运行、异常才提醒你的脚本,就已经能解决80%的问题。
最后我也给自己定了个原则:服务器上凡是我重复手动检查超过三次的东西,都应该脚本化;凡是脚本化后还需要我判断的东西,都可以让AI先分析一遍。
Koen的一句话总结: Claude Code没有替我"运维服务器",但它帮我把那些重复、琐碎、容易忘的巡检动作,变成了一个每天自动上班的小工具。
更多推荐


所有评论(0)