# Ollama + n8n 搭建本地服务器监控 Agent:自动发现问题、AI 分析、定时通知
上个月有回凌晨三点,手机突然狂震——甲骨文云的免费 ARM 服务器内存爆了,PHP-FPM 挂了,95bok.cn 直接 502。
我摸黑爬起来 SSH 上去重启服务,当时就一个念头:能不能让 AI 帮我盯这些,别让我半夜起来干活?
后来折腾了几天,用 n8n + Ollama 搭了个本地 Agent,还真跑起来了。今天把这个方案写下来,给同样被服务器折磨过的朋友参考。
先说思路
其实逻辑不复杂:
关键点:全部跑在本地,数据不出服务器,不用花钱调 GPT API。
环境
- Ubuntu 20.04 系统(24G 内存)
- Ubuntu 20.04
- Ollama 已经在跑(qwen2.5:7b)
- n8n 用 Docker 部署
- 硅基流动(siliconflow.cn)—— 提供免费额度,qwen2.5:7b 几乎免费
- DeepSeek —— 价格低,接口兼容 OpenAI
- 智谱 AI —— 国产,有免费额度
- 不占服务器资源——AI 运算在远端
- 速度快——不用等本地模型加载
- 灵活性高——随时换模型
- 选 Schedule 节点
- 触发间隔设为 每 30 分钟(或者每小时,看你需求)
- 凌晨可以设久一点,别把自己吵醒
- 执行
/opt/n8n/server-check.sh - 拿到服务器状态的 JSON
- 上周三 MySQL 半夜 OOM 被杀了,Agent 5 分钟内发现并通知我,还附带了
systemctl restart mysql的命令,我手机上点一下就恢复了 - 有次磁盘用了 87%,AI 提醒我清 Docker 的悬空镜像,一条命令省了 15G 空间
- 不用半夜爬起来看日志了
- qwen2.5:7b 分析一次大概要 5~10 秒,不算快但能接受
- 有时候 AI 会给一些”万金油”建议,比如”建议排查日志”,说了等于没说
- 30 分钟检查一次其实有点频繁,后来改成 1 小时了
- 模型选 phi3:3.8b,大概占 2.5G 内存(含 Ollama 开销)
- n8n 可以跟 Ollama 分开部署,n8n 放另一台机器,只通过 API 调 Ollama
- 检查频率拉长到 2~4 小时,别太频繁
- 关掉不必要的 Docker 容器,省内存
- 结合 OpenClaw 做更复杂的任务编排(比如自动备份 → 上传 → 验证完整性 → 发通知)
- 试试本地多模态模型(LLaVA),让 AI 能看截图判断页面是否正常
- 加个 Webhook 接口,Nginx 报错时自动触发检查而不是定时轮询
如果你用的是 8G 内存的小鸡,模型换成 qwen2.5:3b 或者 phi3:3.8b 就够了,7B 确实吃内存。
部署 n8n
之前没装过的话:
mkdir -p /opt/n8n && cd /opt/n8ncat > docker-compose.yml << 'EOF'
version: "3.8"
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
ports:
- "5678:5678"
volumes:
- n8n-data:/home/node/.n8n
environment:
- GENERIC_TIMEZONE=Asia/Shanghai
- TZ=Asia/Shanghai
volumes:
n8n-data:
EOF
docker compose up -d
装完访问 http://你的IP:5678,注册个账号进去。
注意: Ollama 默认只监听 127.0.0.1,n8n 在 Docker 里访问不到。两个办法:
# 方法一:让 Ollama 监听所有接口
sed -i '/[Service]/a Environment="OLLAMA_HOST=0.0.0.0"' /etc/systemd/system/ollama.service
systemctl daemon-reload && systemctl restart ollama
然后 n8n 里填 http://172.17.0.1:11434(Docker 网关地址)。
# 方法二:把 n8n 加入 host 网络(简单粗暴,但有安全隐患)
# docker-compose.yml 里加 network_mode: "host"
我用的方法一,稳妥一些。
API 方案(本地跑不动模型的替代方案)
说实话,如果你的服务器只有 2~4G 内存,本地跑 qwen2.5:7b 确实吃力。这时候用 API 更实际。
方案一:第三方 API
n8n 自带 OpenAI/Anthropic/Claude 节点,直接填 API Key 就行。国内的话可以考虑:
在 n8n 里选 OpenAI 节点,把 Base URL 改成对应服务商的地址,填上 Key 就能用。
方案二:自建 API 中转
如果你有自己的 API 服务(比如 OneAPI、NewAPI),可以在 n8n 里通过 HTTP Request 节点调用:
cat > /opt/n8n/api-check.sh << 'SCRIPT'
#!/bin/bash
# 通过 API 调用 AI 分析服务器状态
DATA=$(cat)curl -s https://your-api-server.com/v1/chat/completions
-H "Content-Type: application/json"
-H "Authorization: Bearer your-api-key"
-d "{
"model": "qwen2.5-7b-instruct",
"messages": [
{"role": "system", "content": "你是一个 Linux 运维助手。根据服务器状态数据,分析问题并给出修复建议。简洁回答。"},
{"role": "user", "content": "$DATA"}
]
}" | jq -r '.choices[0].message.content'
SCRIPT
chmod +x /opt/n8n/api-check.sh
# 测试
echo '{"memory": "90% used", "services_down": "mysql"}' | bash /opt/n8n/api-check.sh
这种方式的好处:
缺点就是要花钱(虽然现在很多平台有免费额度),而且数据会出服务器。如果你对隐私要求高,还是本地 Ollama 更安心。
写个检查脚本
先写个 Shell 脚本收集服务器状态:
cat > /opt/n8n/server-check.sh << 'SCRIPT'
#!/bin/bash
# 服务器健康检查脚本# CPU 使用率
CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8"%"}')
# 内存
MEM_TOTAL=$(free -m | awk '/Mem:/{print $2}')
MEM_USED=$(free -m | awk '/Mem:/{print $3}')
MEM_PCT=$(free -m | awk '/Mem:/{printf "%.1f%%", $3/$2*100}')
# 磁盘
DISK=$(df -h / | awk 'NR==2{print $5 " used (" $4 " available)"}')
# 关键服务状态
declare -a SERVICES=("nginx" "php-fpm" "mysql" "docker" "ollama")
DOWN_SERVICES=""
for svc in "${SERVICES[@]}"; do
if ! systemctl is-active --quiet "$svc" 2>/dev/null; then
DOWN_SERVICES="$DOWN_SERVICESn- $svc 已停止"
fi
done
# 最近5分钟高负载进程
TOP_PROCS=$(ps aux --sort=-%mem | head -6 | tail -5 | awk '{printf "- %s (内存 %.1f%%)n", $11, $4}')
# Docker 容器状态
DOCKER_STATUS=$(docker ps --format "table {{.Names}}t{{.Status}}" 2>/dev/null || echo "Docker 异常")
# 输出 JSON
cat << EOF
{
"cpu_usage": "$CPU",
"memory": "$MEM_USED / $MEM_TOTAL MB ($MEM_PCT)",
"disk": "$DISK",
"services_down": "$(echo -e $DOWN_SERVICES | tr 'n' ';')",
"top_memory_processes": "$(echo "$TOP_PROCS" | tr 'n' ';')",
"docker_containers": "$(echo "$DOCKER_STATUS" | tr 'n' ';')"
}
EOF
SCRIPT
chmod +x /opt/n8n/server-check.sh
跑一下看看效果:
bash /opt/n8n/server-check.sh
输出的 JSON 大概长这样:
{
"cpu_usage": "12.3%",
"memory": "8542 / 24123 MB (35.4%)",
"disk": "45% used (120G available)",
"services_down": "",
"top_memory_processes": "/usr/bin/java (内存 8.2%);/usr/sbin/mysqld (内存 6.1%);",
"docker_containers": "n8n Up 2 hours;ollama Up 5 days;"
}
在 n8n 里搭工作流
这一步跟搭乐高差不多。打开 n8n,新建 workflow,依次添加节点:
1. Schedule 触发器
2. Execute Command 节点
3. IF 判断节点
这里加个简单的判断:如果所有服务正常、内存低于 80%,就不通知了,省得没事骚扰我。
条件:memory 百分比 > 80 或者 services_down 不为空
4. Ollama Chat 节点(条件满足时才触发)
把异常数据丢给 AI 分析。System Prompt 我写的:
你是一个 Linux 运维助手。根据以下服务器状态数据,分析可能存在的问题,
并给出简洁的修复建议。用中文回答,不要废话,直接说问题和解决方案。如果所有指标正常,回复"一切正常"即可。
User Message 填的是上一步的 JSON 数据。
5. 通知节点
我用的 Telegram Bot(飞书/邮件/钉钉都行),把 AI 的分析结果发过来。
完整的工作流长这样:
Schedule → 检查脚本 → 判断异常?→ Ollama 分析 → 发通知给我
↓
没问题就结束
实际效果
跑了大概一周,说几个真实感受:
好的地方:
不太满意的地方:
进阶玩法
基础的搞定了,后面我又加了几个功能:
自动修复(谨慎使用)
# 在 n8n 里加一个 Execute Command 节点
# 只有 AI 判断"可以安全重启"时才执行case $SERVICE_DOWN in
"nginx") systemctl restart nginx ;;
"php-fpm") systemctl restart php8.2-fpm ;;
"mysql")
# MySQL 被杀通常是因为 OOM,先检查内存
if [ $(free -m | awk '/Mem:/{print $3/$2*100}') -lt 90 ]; then
systemctl restart mysql
fi
;;
esac
⚠️ 自动修复一定要加限制条件! 我加了内存使用率 < 90% 才允许重启 MySQL,不然刚重启又会被杀掉,死循环。
每日总结
除了实时监控,我还加了个每天早上 9 点的定时任务:
# 收集过去 24 小时的关键数据
cat > /opt/n8n/daily-report.sh << 'SCRIPT'
#!/bin/bash
# 简单版日报
echo "=== $(date '+%Y-%m-%d') 服务器日报 ==="
echo ""
echo "平均负载: $(uptime)"
echo ""
echo "昨日登录情况:"
last -20 | head -10
echo ""
echo "磁盘变化:"
df -h / | tail -1
echo ""
echo "Docker 容器:"
docker ps --format " {{.Names}} - {{.Status}}"
SCRIPT
把报告丢给 Ollama,让它总结成一两句话发给我。比如:
昨天服务器一切正常。凌晨 2 点有次内存飙到 85%,是 n8n 的工作流跑太多了,已清理。磁盘剩余 120G,正常。
给低配机器的建议
如果你用的是 1~2G 内存的小鸡:
实在跑不动的话,纯 Shell 脚本 + cron + 飞书 webhook 也能实现基础监控,只是少了 AI 分析这一步。
接下来想试的
Agent 目前只能”发现问题 → 通知我”,下一步想让它更主动一些:
有折腾过类似方案的朋友,欢迎聊聊你们怎么搞的。或者你们有什么想自动化的场景,我帮你试试能不能搭出来。