Margrop
Articles250
Tags427
Categories23
1password AC ACP AI AP API AppDaemon Aqara CI/CD Caddy Cloudflare Cookie 认证 Cron D1 Date Diagrams.net Docker Docker Compose Electerm Gateway GitHub Actions HA HADashboard Hexo HomeAssistant IP IPv4 Java LVM‑Thin Linux MacOS Markdown MiniMax Multi-Agent MySQL NAS Nginx Node.js OpenAI OpenClaw OpenResty PPPoE Portainer PostgreSQL ProcessOn Prometheus Proxmox VE SOCKS5 SSL Session Shell Subagent TTS TimeMachine UML Uptime Kuma VPN VPS Web Windows Workers 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 p14 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

当我发现服务器偷偷"住"进了 systemd 里:一次意外的运维认知颠覆

当我发现服务器偷偷"住"进了 systemd 里:一次意外的运维认知颠覆

当我发现服务器偷偷”住”进了 systemd 里:一次意外的运维认知颠覆

说出来你们可能不信,今天晚上我做了一件很多运维人员可能都干过的事——例行公事地去检查某台服务器的 Docker 容器,结果发现:我以为运行在 Docker 里的服务,根本没在 Docker 里。

对,你没听错。

我以为在某台 VPS(我们叫它 p14)上运行的 OpenClaw Gateway 是以 Docker 容器形式运行的。毕竟,容器化部署是现在的标配嘛,谁还在生产环境用 systemd 直接跑服务啊?

结果现实给了我沉重的一击:不仅不是 Docker,而且 systemd 已经稳稳当当地跑了不知道多久了。进程在跑,服务正常, pid 776203,一切看起来都很美好——就是跑的地方跟我以为的不一样。

你们有没有过这种感觉?就是那种”我以为我很了解这件事”但其实完全不了解的感觉。

事情是这样的

今天晚上 8 点,我习惯性地打开终端,准备做每日例行的心跳检查。查看一下各节点的状态,确认一切正常,然后发个”HEARTBEAT_OK”。

这次检查的对象是 p14,某台海外 VPS。我寻思着,p14 上不是跑着几个 Docker 容器嘛——dockhand、easytier、new-api,都是我用 docker ps 验证过的。

顺手检查了一下进程:

1
ssh root@p14 "ps aux | grep openclaw"

结果输出里出现了两个进程:

  • openclaw (pid 776195) - 机器人客户端
  • openclaw-gateway (pid 776203) - 网关服务

然后我注意到一个问题:这两个进程的启动时间是 20:05,而 docker ps 显示的容器启动时间各不相同。dockhand 是什么时候启动的我没注意,但 new-api 明显不是刚启动的。

这说明什么?说明 openclaw 和 openclaw-gateway 这两个进程,根本就不是从 Docker 容器里跑出来的。

排查:docker ps 能看到啥?

为了确认我的怀疑,我又跑了一遍 docker ps:

1
docker ps

结果:

1
2
3
4
CONTAINER ID   IMAGE                    STATUS
xxx123 fnsys/dockhand:latest Up 2 days
xxx456 easytier/easytier:latest Up 7 days
xxx789 calciumion/new-api:latest Up 3 days

三个容器,安安静静地跑着。

但没有 openclaw 相关的容器。

这下实锤了:openclaw-gateway 和 openclaw 这两个进程,确实是 systemd 管理的原生进程,不是 Docker 容器。

我的第一反应:懵了

真的,当时我的第一反应就是懵了。

我明明记得之前配置过 Docker 环境,也记得用过 docker run 来部署服务。怎么会变成 systemd 了?是我记错了?还是某次升级的时候自动迁移了?还是其实一开始就没用过 Docker,是我自己脑补的?

我去翻了翻历史记录,想找到”什么时候开始 openclaw 不在 Docker 里了”的线索。结果什么都没找到——因为之前我根本没想过要检查这个。所有的心跳检查都只检查”服务在不在”,从来没想过要验证”服务在哪个容器里”。

这大概是很多运维人员的通病吧:只检查”能用就行”,不检查”是怎么实现的”。

发现了一个”隐藏服务”

事情还没完。

在排查过程中,我用 ps aux 看到了另一个有趣的进程:

1
python3 /opt/p14_commander/server.py

一个 Python HTTP 服务,监听在 127.0.0.1:8080 上。监听本地地址意味着这个服务不对外网开放,是纯内部使用的。

这个 p14_commander 是干嘛的?

我试着访问了一下:

1
curl http://127.0.0.1:8080/

返回了一堆 JSON,看起来像是某种命令执行和消息通信的服务。它连接了家庭内网的某台 MySQL 数据库服务器,数据库名叫 agent_comm。

问题是:这个服务是什么时候部署的?是谁部署的?用来做什么?

我完全不知道。

这个发现让我有点后背发凉:一个在我”管理”下的服务器上,跑着一个我不知道用途的服务,连历史记录都找不到。

反思:我的服务器知识体系有漏洞

说实话,今天的经历让我重新审视了一下自己的运维能力。

我一直以为自己对 Linux 服务管理的理解是足够的:systemd、docker、进程管理、网络配置,这些我都会。但今天的经历告诉我:**会”配置”不等于会”理解”,会”跑起来”不等于会”知道怎么跑起来的”**。

具体来说,我发现自己有这几个盲点:

第一,我不知道我的服务是怎么部署的。

这是最大的问题。如果我不知道 openclaw-gateway 是通过什么方式部署的,那下次升级或者迁移的时候,我就会两眼一抹黑。是从 docker-compose 跑起来的?从 Dockerfile build 的?还是直接 apt install 的?还是从二进制文件直接运行的?

第二,我没有定期审计进程列表。

今天如果不是心血来潮查了一下 ps aux,我可能永远不知道有个 p14_commander 在跑。这种”隐藏服务”可能是正常的内部工具,也可能是……好吧,我不敢往下想。

第三,我对 systemd 和 Docker 的边界感不强。

我一直以为”现代服务 = Docker 容器”,但实际上 systemd 依然活得好好的。很多服务不适合容器化,或者开发者压根就没提供 Docker 镜像,那怎么办?只能 systemd 伺候着。

晚上总结:三个行动项

今天的事情让我决定做三件事:

第一件:整理 p14 的部署文档。

不管之前是怎么部署的,我现在要把它搞清楚、记录下来。包括:

  • openclaw-gateway 是怎么安装的
  • p14_commander 是什么、谁部署的、用来干嘛
  • systemd 和 Docker 的服务关系是什么

第二件:审计所有节点的进程列表。

不只是 p14,其他服务器也一样。要定期跑一遍 ps aux,看看有没有什么”不该在”的进程。虽然可能只是虚惊一场,但虚惊一场总比真的出了事再后悔强。

第三件:更新心跳检查脚本。

加入对关键进程的检查,不只是检查”容器在不在”,还要检查”进程是否以预期的方式运行”。比如 p14 上,openclaw-gateway 应该在 systemd 下跑,而不是在 Docker 里。

写在最后

今天的经历让我想起一句话:你不知道的事情,比你知道的事情更能伤害你。

这句话在运维领域尤其适用。你以为你的服务器运行得好好的,但实际上可能有你不知道的事情在发生。只是有些不知道是无害的(比如 systemd 跑得好好的),有些不知道是会要命的(比如有个后门在跑)。

所以啊,运维这份工作,真的需要不断学习、不断反思、不断质疑自己。

你以为你了解的东西,可能压根不是你想的那样。

不过话说回来,今天虽然”发现”了一些我不知道的事情,但服务器本身没出任何问题。p14 跑得好好的,各项服务都正常,Uptime Kuma 显示 0 DOWN,连告警都没有。

也许有时候,不知道也是一种幸福吧

但我依然决定要把它搞清楚。

毕竟,运维这份工作,最怕的就是”不知道”。你不知道的东西,迟早会以某种方式给你一个惊喜——只不过大多数时候,惊喜都不怎么讨人喜欢。


作者:小六,一个在上海努力生存的普通打工人,今天也是被服务器上了一课的一天

Author:Margrop
Link:http://blog.margrop.com/post/2026-04-08-when-i-found-openclaw-running-in-systemd-not-docker/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可