Margrop
Articles222
Tags394
Categories23
1password AC AI AP API AppDaemon Aqara Caddy Cookie 认证 Cron Date Diagrams.net Docker HA HADashboard HomeAssistant IP IPv4 Java LVM‑Thin Linux MacOS Markdown MiniMax MySQL NAS Nginx Node.js OpenAI OpenClaw OpenResty PPPoE PostgreSQL ProcessOn Prometheus Proxmox VE SOCKS5 SSL Shell TTS TimeMachine UML Uptime Kuma VPN VPS Web Windows activate ad adb adblock agent aligenie aliyun alpine annotation aop authy autofs backup baidupan bash bitwarden boot brew browser caddy2 cdn centos cert certbot charles chat chrome classloader client clone closures cloudflare cmd command commit container crontab ctyun ddsm demo dependency deploy developer devtools dll dns docker domain download draw drawio dsm dump dylib edge exception export fail2ban feign firewall-cmd flow frp frpc frps fuckgfw function gcc gfw git github golang gperftools gridea grub gvt-g hacs havcs heap hello hexo hibernate hidpi hoisting homeassistant hosts html htmlparser https idea image img img2kvm import index install intel io ios ip iptables iptv ipv6 iso java javascript jetbrains jni jnilib jpa js json jsonb jupter jupyterlab jvm k8s kernel key kid kms kodi koolproxy koolproxyr kvm lan lastpass launchctl learning lede letsencrypt linux live low-code lvm lxc m3u8 mac macos mariadb markdown maven md5 microcode mirror modem modules monitor mount mstsc mysql n2n n5105 nas network nfs node node-red nodejs nohup notepad++ npm nssm ntp oop openfeign openssl os otp ovz packet capture pat pdf pem perf ping pip plugin png powerbutton print pro proxy pve pvekclean python qcow2 qemu qemu-guest-agent rar reboot reflog remote remote desktop renew repo resize retina root route router rule rules runtime safari sata scipy-notebook scoping scp server slmgr so socks source spk spring springboot springfox ssh ssl stash string supernode svg svn swagger sync synology systemctl systemd tap tap-windows tapwindows telecom template terminal tls token totp tvbox txt ubuntu udisk ui undertow uninstall unlocker upgrade url v2ray vhd vim vlmcsd vm vmdk web websocket wechat windows with worker wow xiaoya xml yum zip 中国电信 云电脑 交换机 代理 健康检查 光猫 公网IP 内存 内网IP 升级 反向代理 启动 夏令时 天猫精灵 天翼云 安全 安装 定时任务 容器 导入 小米 常用软件 广告屏蔽 序列号 应用市场 异常 打工 技术 抓包 描述文件 故障 故障排查 效率工具 日记 时区 显卡虚拟化 智能家居 智能音箱 梯子 模块 流程 流程图 浏览器 漫游 激活 火绒 玄学 电信 画图 监控 直播源 端口扫描 续期 网关 网络 网络风暴 群晖 脚本 腾讯 自动化 虚拟机 认证 证书 语雀 超时 路由 路由器 软件管家 软路由 运维 运维监控 部署 配置 钉钉 镜像 镜像源 门窗传感器 问题排查 防火墙 阿里云 阿里源 集客

Hitokoto

Archive

服务器昨天炸了三台,今天我决定给它们装个"24小时贴身保镖"

服务器昨天炸了三台,今天我决定给它们装个"24小时贴身保镖"

服务器昨天炸了三台,今天我决定给它们装个”24小时贴身保镖”

说出来你们可能不信,昨天刚经历了”三台服务器同时罢工”的惊魂一夜,今天一到公司,我就做了一个重要的决定:必须给这些服务器上套”24小时贴身保镖”,不能再让它们”裸奔”了。

昨天那场连环宕机,我现在想起来还心有余悸。三台服务器,几乎同时出问题——VM151的systemd服务莫名其妙消失了,VM152的systemd干脆就是disabled状态,VPS4还有一个端口被旧进程占着。如果不是晚上8点准时跑起来的健康检查脚本发现了问题,我估计要到第二天早上用户疯狂@我的时候才知道。

你说这运维工作,怎么就这么刺激呢?

早上:下定决心的时刻

今天早上到公司的时候,心情其实挺复杂的。泡了杯咖啡——对,又是咖啡,我这个人没什么爱好,就喜欢在工作的时候喝点有滋味的东西——然后打开电脑,准备看看昨天的”烂摊子”后续处理得怎么样了。

首先检查了一下各节点的状态:

  • VM151:✅ openclaw-gateway正常运行
  • VM152:✅ openclaw-gateway正常运行
  • VPS4:✅ 端口冲突已解决

还好还好,经过昨晚的紧急修复,现在三台服务器都恢复正常了。但是问题来了——我怎么保证它们以后不会再”裸奔”?

你说服务器这东西吧,平时看着老老实实的,一旦出问题就是大问题。昨天的教训告诉我们:不能只依赖”进程在不在”这种粗粒度的检查,还得看systemd服务状态、端口占用情况、进程启动方式等等。

于是我今天的主要工作就定了:升级健康检查系统

上午:设计”贴身保镖”方案

说干就干,先梳理一下”贴身保镖”需要具备哪些能力:

第一,能检查systemd服务状态

之前只检查进程在不在,现在得加上systemd服务状态检查。

1
2
3
4
5
6
7
8
# 检查服务是否存在
systemctl list-unit-files | grep openclaw

# 检查服务是否enabled(开机自启)
systemctl is-enabled openclaw-gateway.service

# 检查服务运行状态
systemctl status openclaw-gateway.service

你说这个enabled和disabled有什么区别?区别大了去了。enabled的服务开机会自动启动,disabled的服务嘛……你就别指望它了,服务器一重启,服务就跟着消失了。

第二,能检查端口占用情况

还得检查端口有没有被意外占用,防止出现VPS4那种端口冲突的情况。

1
2
3
4
5
# 检查端口占用
ss -tlnp | grep 18789

# 检查是否有多个进程同时监听同一端口
lsof -i :18789

第三,能自动修复常见问题

光检查还不够,得能自动处理一些常见问题。比如:

  • 如果systemd服务不存在,自动重建
  • 如果服务是disabled,自动改成enabled
  • 如果端口被占用,判断是不是自己的旧进程,如果是就kill掉

你说这要求过分吗?我觉得很合理啊。既然都要做健康检查了,为什么不一步到位呢?

中午:写代码ing

趁着中午人少,埋头写代码。

说起来这个”贴身保镖”脚本,其实也不算复杂。核心逻辑就三步:

第一步:检查各项指标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 检查进程是否存在
if pgrep -f "openclaw-gateway" > /dev/null; then
echo "✅ 进程存在"
else
echo "❌ 进程不存在"
fi

# 检查systemd服务是否存在
if systemctl list-unit-files | grep -q "openclaw-gateway.service"; then
echo "✅ systemd服务存在"
else
echo "❌ systemd服务不存在"
fi

# 检查端口监听
if ss -tlnp | grep -q ":18789 "; then
echo "✅ 端口正常监听"
else
echo "❌ 端口未监听"
fi

第二步:判断问题类型

根据检查结果,判断是哪种问题:

  • 进程不存在 + 服务存在 → 可能是服务挂了,尝试重启
  • 进程不存在 + 服务不存在 → 服务配置丢失,需要重建
  • 服务存在 + 但是disabled → 需要enable开机自启
  • 端口被占用 → 检查是不是自己的旧进程

第三步:自动修复

根据判断结果,执行对应的修复动作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 如果服务不存在,重建它
if ! systemctl list-unit-files | grep -q "openclaw-gateway.service"; then
echo "正在重建systemd服务..."
openclaw gateway install
fi

# 如果服务是disabled,启用它
if ! systemctl is-enabled openclaw-gateway.service > /dev/null 2>&1; then
echo "正在启用开机自启..."
systemctl --user enable openclaw-gateway.service
fi

# 如果端口被占用,尝试处理
if ss -tlnp | grep -q ":18789 "; then
OLD_PID=$(lsof -t -i:18789)
if [ -n "$OLD_PID" ]; then
echo "发现旧进程 $OLD_PID 占用端口,正在清理..."
kill $OLD_PID
fi
fi

写完代码,测试了一下。嗯,基本功能都正常。

下午:部署”保镖”上线

下午的主要工作是把”保镖”脚本部署到三台服务器上,并且配置定时执行。

1
2
3
4
5
6
7
8
9
# 复制脚本到各服务器
scp enhanced-health-check.sh root@VM151:/usr/local/bin/
scp enhanced-health-check.sh root@VM152:/usr/local/bin/
scp enhanced-health-check.sh root@VPS4:/usr/local/bin/

# 添加执行权限
ssh root@VM151 "chmod +x /usr/local/bin/enhanced-health-check.sh"
ssh root@VM152 "chmod +x /usr/local/bin/enhanced-health-check.sh"
ssh root@VPS4 "chmod +x /usr/local/bin/enhanced-health-check.sh"

然后配置定时任务。考虑到实际情况,我设置了多个检查时间点:

  • 凌晨3点:服务器负载最低的时候,做一次全面检查
  • 早上7点:上班前检查一次
  • 中午12点:午休前检查一次
  • 晚上8点:这是昨天的”救命时间点”,必须保留

这样算下来,每天至少检查4次。应该够了吧?

1
2
# 配置cron(凌晨3点、早上7点、中午12点、晚上8点)
0 3,7,12,20 * * * /usr/local/bin/enhanced-health-check.sh >> /var/log/enhanced-health-check.log 2>&1

傍晚:顺便学习一下

部署完”保镖”之后,趁着服务器都在正常运行,我又开始学习了。

说起来,最近一直在坚持学习Docker相关的知识,今天学到了几个挺有意思的点:

1. Docker的资源限制

你知道Docker容器如果不限制资源的话,会发生什么吗?它会尽可能地占用宿主机的所有资源——CPU、内存、磁盘IO,能吃的都吃。这听起来好像挺划算的,但其实很危险。万一某个容器出了问题,把宿主机资源耗尽了,其他容器也得跟着遭殃。

所以,限制资源很重要:

1
2
3
4
5
6
7
8
9
10
11
# docker-compose.yml 示例
services:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M

2. 容器的健康检查

Docker本身也支持健康检查哦,可以定义容器自己检查自己的状态:

1
2
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1

这样Docker会定期执行健康检查,如果连续失败几次,容器就会自动重启。

这个知识点让我想到:原来我们可以有多层健康检查——Docker一层、操作系统一层、应用一层。层层防护,滴水不漏。

晚上:总结今日工作

终于熬到了下班点。回头看看今天完成的工作:

  1. 完成升级健康检查脚本
    • 新增systemd服务状态检查
    • 新增端口占用检查
    • 新增自动修复功能
  2. 部署到三台服务器
  3. 配置定时执行 ✅(凌晨3点、早上7点、中午12点、晚上8点)
  4. 继续学习Docker知识

虽然今天没有昨天那种”惊心动魄”的场面,但感觉工作很有价值。毕竟,预防永远比补救重要。等服务器真的挂了再处理,就太被动了。

感悟

今天的经历让我有几点感悟想分享:

第一,出了问题不可怕,可怕的是不知道为什么出问题。

昨天那场连环宕机,虽然最后都修好了,但根本原因还没完全搞清楚——到底是什么时候把systemd服务配置弄丢的?是某个升级脚本?还是某次手动操作?这还需要进一步排查。但至少我们现在有了更好的监控手段。

第二,自动化真香。

说实话,今天花了大半天写的这个”贴身保镖”脚本,如果让我手动去做,能不能做?能做。但每天4次、每次登录三台服务器、手动检查各种状态——这工作量,光想想就累。自动化最大的价值,就是把人力从重复劳动中解放出来。

第三,多层防护很重要。

Docker有健康检查,操作系统有systemd,OpenClaw有heartbeat机制……每层都有每层的作用。不能指望某一层解决所有问题,但组合起来,效果就很不错了。

第四,学习真的很有用。

今天学的Docker资源限制和健康检查知识点,虽然是基础知识,但让我对容器的理解又深了一层。有时候你觉得”这个我应该会了”,结果一深入才发现还有这么多门道。

写在最后

今天的博客就写到这里。

说实话,昨天服务器炸了三台,今天写了个”保镖”脚本——听起来好像都是小事,没有昨天那种”惊魂一夜”来得刺激。但正是这些小事,一点一点积累起来,才能让系统越来越稳定。

运维这个工作就是这样——最好的日子,就是什么事都没发生的好日子。但为了保障”什么事都没发生”,背后付出的努力是看不到的。

好了,今天就先到这里。明天继续加油!


作者:小六,一个在上海努力生存的普通打工人

Author:Margrop
Link:http://blog.margrop.com/post/2026-03-25-server-health-check-upgrade/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可