atuibot 今天给我发了条消息,大意是:哥,我的 Gateway 版本落后了。
我心想不对啊,上周不是刚跑过升级脚本吗?openclaw --version 一敲——2026.2.26,没毛病。再看 Gateway app 版本——2026.2.6-3。
差了快一个月的版本。CLI 和 Gateway 明明是同一个 npm 包,怎么版本号能不一样?
升级脚本长这样
服务器上有个 openclaw-safe-upgrade.sh,之前写的,一直在用:
#!/bin/bash
set -e
# 1.9G 的小鸡,不先停 Gateway 会 OOM
systemctl stop openclaw-gateway || pkill -9 openclaw-gateway || true
sleep 2
# 删旧装新
rm -rf /usr/lib/node_modules/openclaw
npm cache clean --force
npm install -g openclaw --ignore-scripts
# 拉起来
systemctl start openclaw-gateway || openclaw gateway --daemon
每次跑完 openclaw --version 都能看到新版本号,我就以为万事大吉了。
systemd 环境变量在搞鬼
翻了一下 atuibot 的 systemd unit 文件,原来 openclaw gateway install 首次安装时会生成这么个东西:
[Unit]
Description=OpenClaw Gateway (v2026.2.6-3)
[Service]
ExecStart="/usr/bin/node" "/usr/lib/node_modules/openclaw/dist/index.js" gateway --port 18789
Environment=OPENCLAW_SERVICE_VERSION=2026.2.6-3
看到没,OPENCLAW_SERVICE_VERSION 是写死在 unit 文件里的。Gateway 进程启动时读这个环境变量,然后上报给 openclaw status。
npm 把磁盘上的 JS 文件换了新的,systemctl 也确实重启了进程,跑的代码八成已经是新版。但 unit 文件从首次安装之后就没人动过,版本号一直停在 2026.2.6-3。
相当于换了发动机,铭牌还贴着出厂那张。
修的时候又踩了一脚
知道问题在哪之后,我想着顺便直接升到最新的 2026.3.1。
先 npm install -g openclaw@2026.3.1 --ignore-scripts,没问题。然后想用 openclaw update --yes 让它自己刷新 unit 文件——结果这命令在小内存机器上会炸。它内部尝试再跑一次 npm 全局安装,已经存在的目录 rename 不掉,报 ENOTEMPTY。更离谱的是它把 /usr/bin/openclaw 的软链给删了,命令直接 command not found。
只好再来一遍 npm install -g openclaw@2026.3.1 --ignore-scripts 把包装回去,然后用真正管用的办法:
openclaw gateway install --force
systemctl --user daemon-reload
systemctl --user start openclaw-gateway
gateway install --force 会用当前版本重新生成 unit 文件。跑完验证:
CLI 版本: 2026.3.1
Gateway app 版本: 2026.3.1
对上了。
改过的升级脚本
原来的脚本差两行,补上就行:
#!/bin/bash
# OpenClaw 安全升级(阿里云小内存 VPS 适用)
set -e
CURRENT=$(openclaw --version 2>/dev/null || echo 'not installed')
echo "当前: $CURRENT"
# 内存不够 500M 就警告
AVAIL=$(free -m | awk 'NR==2{print $7}')
if [ "$AVAIL" -lt 500 ]; then
echo "[WARN] 可用内存 ${AVAIL}MB,建议释放后再升"
read -p '继续? (y/N) ' -n 1 -r
echo
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
fi
# 停服务腾内存
systemctl --user stop openclaw-gateway 2>/dev/null || true
sleep 2
# 清理残留 + 安装
rm -rf /usr/lib/node_modules/openclaw
rm -rf /usr/lib/node_modules/.openclaw-*
npm cache clean --force
npm install -g openclaw --ignore-scripts
# 重建 systemd unit —— 之前漏的就是这两行
openclaw gateway install --force
systemctl --user daemon-reload
# 启动
systemctl --user start openclaw-gateway
sleep 5
echo "升级完成: $CURRENT → $(openclaw --version)"
openclaw status 2>&1 | grep -E "Gateway|Update"
openclaw update 在大内存机器上应该没问题,但 2G 的阿里云 ECS 跑它容易翻车。手动控制流程反而稳。
关于 openclaw update 为什么不行
这命令设计上是想一把梭的:更新 npm 包 + 刷新 systemd + 重启服务。但它内部跑 npm 时不会先停 Gateway,小内存机器同时跑 Gateway + npm install 直接 OOM。就算内存够,如果当前版本已经是最新,npm rename 旧目录会撞上 ENOTEMPTY,然后整个更新流程报错退出——npm 包可能已经被删了一半,openclaw 命令直接没了。
所以在阿里云 1-2G 的小鸡上,老老实实停服务、手动装、手动刷 unit,三步走反而最不容易出事。
atuibot 跑了几个月才暴露这个问题。不是因为它一直没升级,是因为即使 Gateway 版本号报错了,服务本身也能正常跑。等到 atuibot 自己都看不下去了来提醒我,我才意识到升级脚本少了一步。有时候"能跑"和"跑对了"之间,就差一个环境变量的距离。