服务器不出事的时候,没人想得起它;出事的时候,才发现三个月没看过日志、磁盘早就满了、证书上周就过期了。
巡检是成本最低的保障。这篇给一份完整的巡检清单 + 可直接跑的自动化脚本,把「出事才发现」变成「出事前预警」。
需要云服务器可以看看财富云计算:一键开服面板,NAT 型无独立公网 IP,价格比独立 IP 机型省一半以上,主流游戏快速部署。
一、巡检清单:每天 5 分钟看这些
必看项(每天)
| 项 | 命令 | 正常标准 |
|---|---|---|
| 磁盘使用率 | df -h / | < 80% |
| 内存可用 | free -h | available > 20% |
| CPU 负载 | uptime | load < 核数 |
| 服务状态 | systemctl --failed | 无 failed |
| 备份是否成功 | 看备份日志 | 今天有备份记录 |
| 带宽/流量 | iftop 抽查 | 无异常峰值 |
每周看
| 项 | 命令/位置 | 关注点 |
|---|---|---|
| 安全日志 | lastb、fail2ban 状态 | 暴力破解尝试 |
| 错误日志 | journalctl -p err --since "7 days ago" | 反复出现的错误 |
| 端口变化 | ss -tulnp 对比基线 | 陌生监听 |
| 账号变化 | /etc/passwd 对比 | 陌生账号 |
| 证书到期 | openssl x509 -enddate | > 30 天 |
| 备份恢复演练 | 抽一次解压验证 | 备份可用 |
每月看
| 项 | 关注点 |
|---|---|
| 系统更新 | apt update && apt list --upgradable,排期更新 |
| 大文件清理 | /var/log、/tmp、旧内核 |
| 用户/权限审计 | sudo 列表、应用账号权限 |
| 成本回顾 | 带宽/流量/存储用量,该降配降配 |
二、自动化巡检脚本
把上面的清单写成一个脚本,每天定时跑,异常推送告警。
#!/bin/bash
#==================================================
# 服务器日常巡检脚本
# 输出巡检报告,异常项推送告警
# 用法: ./inspect.sh [--quiet 只输出异常]
#==================================================
WEBHOOK="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的key"
REPORT="/tmp/inspect-$(date +%Y%m%d).txt"
WARN=""
log() { echo "$1" >> "$REPORT"; }
warn() { WARN="$WARN\n$1"; log "⚠️ $1"; }
alert() {
[ -n "$WARN" ] && curl -s "$WEBHOOK" -H 'Content-Type: application/json' -d "{
\"msgtype\": \"text\",
\"text\": {\"content\": \"【巡检告警】$(hostname)$(echo -e $WARN)\"}
}"
}
echo "======== $(hostname) 巡检报告 $(date '+%F %T') ========" > "$REPORT"
# ===== 1. 磁盘 =====
log "--- 磁盘使用率 ---"
df -h | grep -vE "tmpfs|overlay" | awk 'NR>1 {print $6, $5}' | while read fs pct; do
p=${pct%\%}
if [ "$p" -ge 90 ]; then warn "磁盘 $fs 使用率 ${p}%(危险)";
elif [ "$p" -ge 80 ]; then warn "磁盘 $fs 使用率 ${p}%(关注)"; fi
done
df -h / >> "$REPORT" 2>&1
# ===== 2. 内存 =====
log "--- 内存 ---"
free -h >> "$REPORT"
AVAIL=$(free -m | awk 'NR==2 {print $7}')
TOTAL=$(free -m | awk 'NR==2 {print $2}')
PCT=$((AVAIL * 100 / TOTAL))
[ "$PCT" -lt 20 ] && warn "内存可用仅 ${PCT}%(${AVAIL}M/${TOTAL}M)"
SWAP_USED=$(free -m | awk 'NR==3 {print $3}')
[ "$SWAP_USED" -gt 512 ] && warn "Swap 已用 ${SWAP_USED}M,内存可能不足"
# ===== 3. 负载 =====
log "--- 负载 ---"
LOAD=$(uptime | awk -F'load average:' '{print $2}')
CORES=$(nproc)
log "负载:$LOAD (核数 $CORES)"
L1=$(echo "$LOAD" | awk -F, '{print $1}' | tr -d ' ')
awk "BEGIN{exit !($L1 > $CORES)}" && warn "1 分钟负载 $L1 超过核数 $CORES"
# ===== 4. 失败的服务 =====
log "--- 服务状态 ---"
FAILED=$(systemctl --failed --no-legend | wc -l)
if [ "$FAILED" -gt 0 ]; then
warn "有 $FAILED 个服务处于 failed 状态"
systemctl --failed --no-legend >> "$REPORT"
fi
# ===== 5. 端口基线对比 =====
log "--- 监听端口 ---"
CUR=$(ss -tuln | awk 'NR>1 {print $1, $5}' | sort)
echo "$CUR" >> "$REPORT"
BASE="/opt/scripts/port-baseline.txt"
if [ -f "$BASE" ]; then
NEW=$(comm -13 <(sort "$BASE") <(echo "$CUR"))
[ -n "$NEW" ] && warn "发现新监听端口:\n$NEW"
else
echo "$CUR" > "$BASE"; log "端口基线已建立"
fi
# ===== 6. 备份检查 =====
log "--- 备份检查 ---"
BK="/backup/mysql"
if [ -d "$BK" ]; then
LATEST=$(ls -1t "$BK"/*.sql.gz 2>/dev/null | head -1)
if [ -n "$LATEST" ]; then
AGE=$(( ($(date +%s) - $(stat -c %Y "$LATEST")) / 3600 ))
[ "$AGE" -gt 26 ] && warn "最新备份已 ${AGE} 小时前,备份可能没在跑"
log "最新备份: $LATEST (${AGE} 小时前)"
else
warn "备份目录为空!"
fi
fi
# ===== 7. 证书到期 =====
log "--- SSL 证书 ---"
for cert in /etc/letsencrypt/live/*/fullchain.pem; do
[ -f "$cert" ] || continue
END=$(openssl x64 -in "$cert" -noout -enddate 2>/dev/null || openssl x509 -in "$cert" -noout -enddate 2>/dev/null | cut -d= -f2)
DAYS=$(( ($(date -d "$END" +%s) - $(date +%s)) / 86400 ))
[ "$DAYS" -lt 14 ] && warn "证书 $cert ${DAYS} 天后过期"
done
# ===== 8. 安全: 暴力破解尝试 =====
log "--- SSH 登录失败 ---"
FAILS=$(grep -c "Failed password" /var/log/secure /var/log/auth.log 2>/dev/null | awk -F: '{s+=$2} END {print s}')
[ "${FAILS:-0}" -gt 100 ] && warn "SSH 失败登录 ${FAILS} 次,检查 fail2ban"
# ===== 9. 游戏服进程抽查 =====
log "--- 游戏服进程 ---"
for svc in palworld ark terraria; do
if systemctl list-unit-files | grep -q "$svc.service"; then
if ! systemctl is-active --quiet "$svc"; then
warn "游戏服 $svc 未运行!"
fi
fi
done
# ===== 输出 =====
log ""
log "======== 巡检结束 ========"
[ -n "$WARN" ] && alert
cat "$REPORT"挂定时任务
chmod +x /opt/scripts/inspect.sh
# 每天早上 9 点巡检,有异常才推送
crontab -e
0 9 * * * /opt/scripts/inspect.sh --quiet >/dev/null 2>&1三、告警渠道选择
| 渠道 | 延迟 | 成本 | 适合 |
|---|---|---|---|
| 企业微信/钉钉机器人 | 秒级 | 免费 | 团队协作,推荐 |
| 邮件 | 分钟级 | 免费 | 非紧急、日报 |
| 短信/电话 | 秒级 | 几分钱/条 | 致命告警(磁盘满、服务挂) |
| Server酱/Telegram | 秒级 | 免费 | 个人 |
告警分级建议:
- P1 电话:服务全挂、磁盘 95%+
- P2 企业微信:备份失败、服务重启、异常登录
- P3 日报:汇总巡检报告,早上看
别所有告警都推送——告警太多等于没有告警。分级 + 只推异常。
四、游戏服巡检专项
游戏服除了常规项,还要看:
# 1. 服务端进程存活(被 OOM 杀了最常见)
systemctl is-active palworld
# 2. 端口在监听
ss -ulnp | grep 8211
# 3. 存档最近更新时间(判断服务端是否真的在跑)
ls -la /opt/games/palworld/server/Pal/Saved/SaveGames/
# 4. 内存趋势(泄漏)
ps -o rss= -p $(pgrep -f PalServer)
# 5. SteamCMD 更新是否失败(看日志)
tail -20 /opt/games/palworld/server/Steam/logs/
# 6. 在线人数(从查询端口或 RCON)把这些加进巡检脚本的「游戏服进程抽查」部分。
五、巡检报告的可视化
纯文本报告看久了累,两个轻量方案:
# 方案1: 报告转 HTML(邮件发)
# 用 bash + 简单模板生成,或用 markdown 转
# 方案2: 历史数据存起来,用 Netdata/Grafana 看趋势
# 把 df/free/load 指标定时采集,存成文件
echo "$(date +%s) $(df / | awk 'NR==2 {print $5}') $(free -m | awk 'NR==2 {print $3}')" >> /var/log/metrics.log趋势比快照重要:磁盘从 60% 涨到 85% 用了两周,比某天突然 90% 更有预警价值。
六、常见问题
Q:crontab 里的脚本不执行?
环境变量问题。脚本用绝对路径、开头 export PATH=...、检查 /var/log/cron 或 journalctl -u cron。
Q:告警太频繁,烦了?
调高阈值(磁盘 80% 再报)、加防抖(连续两次异常才报)、分级推送。别把「关注级」和「危险级」混在一起。
Q:巡检发现端口变化但不知道是谁?ss -tulnp 看进程名和 PID,ls -l /proc/PID/exe 看可执行文件路径。陌生进程按应急流程处理。
Q:备份检查怎么知道备份成功?
看两件事:文件存在 + 时间戳是新的。更严的做法:备份脚本跑完写个状态文件,巡检读状态。
Q:脚本能同时管多台吗?
单机巡检脚本每台跑一个;想汇总多台,用 Ansible 批量跑(见Ansible 批量运维),或者部署 Prometheus 统一采集。
小结
巡检的核心是「自动化 + 分级告警」:每天脚本自动跑一遍清单,异常按级别推送,正常只进日报。配合每周的人工项(恢复演练、权限审计),服务器的可用性就有基本盘了。这套东西一两个小时搭好,之后每天省下来的心和避开的坑,远超投入。
更多运维内容见财富云计算知识库:crontab、监控体系、备份策略、Ansible 全系列。需要云服务器可以看看财富云计算:一键开服面板,NAT 型无独立公网 IP,价格比独立 IP 机型省一半以上。
延伸阅读
- 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
- 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
- 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
- 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
- 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
- RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
- 短链接服务搭建:Shlink 自托管,链接数据自己掌握
- 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道

[...]uptime # load做成 cron 每日邮件报告,模板见服务器日常巡检清单与自动化。监控告警体系见Prometheus 监控体系。排查口诀:先 uptime 看 load,再 top 找 CPU,ps 看状态位,iostat 看磁盘,dmesg 看内核,crontab 查根。按顺序来,没有查不到的问题。进程异常大多有迹可循:僵尸找爹、[...]
2026-10-15 回复
[...]mail -s "安全周报-$(hostname)-$(date +%F)" admin@example.com < $LOG挂 crontab 每周一凌晨跑,周一早上喝着咖啡看报告。更完整的巡检体系见服务器日常巡检清单与自动化。七、报告出来后的处理优先级发现动作系统二进制被改重装该包(apt install --reinstall),查入侵入口陌生 SUID 文件立刻定[...]
2026-10-15 回复
[...]0 9 * df -h | awk '$5+0 > 80 {print $0}' | mail -s "磁盘告警-$(hostname)" admin@example.com或上监控系统见Prometheus 监控体系,配磁盘使用率曲线,涨势看得见。巡检模板见服务器日常巡检清单与自动化。五、应急:磁盘 100% 时先救火满盘时很多命令都报错,按这个顺序腾空间:# [...]
2026-10-15 回复
[...]└─ 已经 OOM → dmesg 确认 → Swap 急救 → 重启 → 再走上面流程七、预防清单[ ] 关键服务配 MemoryMax 或 mem_limit,泄漏可控[ ] Swap 必配(小内存机器的保险丝)[ ] 关键进程(DB)调低 oom_score_adj,别被冤杀[ ] 内存监控告警:85% 持续 10 分钟[ ] 每周看一次 RSS 趋势曲线[ ] 新服务上线前跑一轮 valg[...]
2026-10-15 回复
[...]0 9 * df -h / | awk 'NR==2 && $5+0>80 {print "磁盘空间:"$0}'; df -i / | awk 'NR==2 && $5+0>80 {print "inode:"$0}' | mail -s "资源告警" admin@example.com[...]
2026-10-15 回复
[...]netsh advfirewall firewall add rule name="GameRange" dir=in action=allow protocol=UDP localport=26901-26903完整的 Windows 环境准备(远程桌面连接、运行库安装、SteamCMD 用法、开机自启、8 个常见坑)见:《Windows 云服务器开服通用前置教程》→ htt[...]
2026-10-18 回复