feat: report version, handle remote upgrade via update-clawd.sh

Made-with: Cursor
This commit is contained in:
stswangzhiping
2026-04-30 18:18:30 +08:00
parent 5a5c3ca4b5
commit b4e0388c71
2 changed files with 98 additions and 4 deletions

View File

@@ -1,10 +1,13 @@
'use strict';
const fs = require('fs');
const fs = require('fs');
const path = require('path');
const { getNotifySocket } = require('./systemd-env');
const WebSocket = require('ws');
const { execFileSync, exec } = require('child_process');
const config = require('./config');
const CLAWD_VERSION = require(path.join(__dirname, '..', 'package.json')).version;
const log = require('./logger');
const { getBoxId } = require('./fingerprint');
const { collect } = require('./metrics');
@@ -371,6 +374,7 @@ class ClawClient {
box_id: this._boxId,
claw_id: this._cfg.claw_id ?? null,
token: this._cfg.token ?? null,
version: CLAWD_VERSION,
local_ip: getLocalIps(),
local_networks: getLocalNetworks(),
external_ip: this._externalIp ?? null,
@@ -392,6 +396,9 @@ class ClawClient {
case 'status_update':
this._applyStatus(msg);
break;
case 'upgrade':
this._handleUpgrade(msg);
break;
case 'error':
log.error('clawd', `服务器错误: ${msg.msg}`);
if (msg.msg === 'hardware_mismatch') {
@@ -598,6 +605,7 @@ class ClawClient {
type: 'heartbeat',
claw_id: this._cfg.claw_id,
token: this._cfg.token,
version: CLAWD_VERSION,
local_ip: getLocalIps(),
local_networks: getLocalNetworks(),
...this._dashInfo,
@@ -618,6 +626,80 @@ class ClawClient {
}
}
// ── 升级 ────────────────────────────────────────────────────────────────────
_sendUpgradeProgress(progress, step, failed = false, errorMsg = null) {
const msg = {
type: 'upgrade_progress',
claw_id: this._cfg.claw_id,
token: this._cfg.token,
progress,
step,
failed,
};
if (errorMsg) msg.error = errorMsg;
this._send(msg);
log.info('upgrade', `进度 ${progress}% - ${step}${failed ? ` [失败: ${errorMsg}]` : ''}`);
}
async _handleUpgrade(msg) {
const targetVersion = msg.version;
const installDir = path.dirname(__dirname); // /opt/clawd 或同等安装目录
const scriptPath = path.join(installDir, 'tools', 'update-clawd.sh');
log.info('upgrade', `收到升级命令: ${CLAWD_VERSION}${targetVersion}`);
this._sendUpgradeProgress(5, 'starting');
// 检查脚本是否存在
if (!fs.existsSync(scriptPath)) {
const err = `升级脚本不存在: ${scriptPath}`;
log.error('upgrade', err);
this._sendUpgradeProgress(0, 'failed', true, err);
return;
}
try {
await new Promise((resolve, reject) => {
const child = exec(`bash "${scriptPath}" --no-restart`, { timeout: 300_000 });
child.stdout.on('data', (data) => {
const line = data.toString().trim();
log.info('upgrade', line);
// 根据脚本输出关键字上报进度
if (line.includes('Fetching latest')) this._sendUpgradeProgress(20, '拉取更新中');
else if (line.includes('Already up to date')) this._sendUpgradeProgress(100, 'already_up_to_date');
else if (line.includes('Updating working tree')) this._sendUpgradeProgress(50, '更新文件中');
else if (line.includes('npm install')) this._sendUpgradeProgress(70, '安装依赖中');
else if (line.includes('No dependency')) this._sendUpgradeProgress(80, '无需安装依赖');
else if (line.includes('Current commit')) this._sendUpgradeProgress(90, '即将重启');
});
child.stderr.on('data', (data) => {
log.warn('upgrade', data.toString().trim());
});
child.on('close', (code) => {
if (code === 0) resolve();
else reject(new Error(`脚本退出码: ${code}`));
});
child.on('error', reject);
});
// 脚本执行成功,通知服务端完成,然后退出让 systemd 重启
this._sendUpgradeProgress(100, 'done');
log.info('upgrade', `升级至 v${targetVersion} 完成,即将重启...`);
// 延迟 1.5 秒确保进度消息送达,再退出
setTimeout(() => process.exit(0), 1500);
} catch (e) {
log.error('upgrade', `升级失败: ${e.message}`);
this._sendUpgradeProgress(0, 'failed', true, e.message);
}
}
// ── 工具 ────────────────────────────────────────────────────────────────────
_send(obj) {

View File

@@ -5,6 +5,13 @@ REPO_DIR="/opt/clawd"
REMOTE="origin"
BRANCH="main"
SERVICE="clawd.service"
NO_RESTART=false
for arg in "$@"; do
case "$arg" in
--no-restart) NO_RESTART=true ;;
esac
done
echo "==> clawd update start"
date
@@ -41,13 +48,18 @@ else
echo "==> No dependency changes, skip npm install"
fi
echo "==> Current commit:"
git log --oneline -1
if [ "$NO_RESTART" = true ]; then
echo "==> --no-restart: skip systemctl restart (caller handles restart)"
exit 0
fi
echo "==> Restarting service: $SERVICE"
systemctl restart "$SERVICE"
echo "==> Service status:"
systemctl status "$SERVICE" --no-pager -l || true
echo "==> Current commit:"
git log --oneline -1
echo "==> clawd update done"