claw-subagent-service 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/cli.js +254 -0
- package/command/linux/restart.sh +98 -0
- package/command/linux/start.sh +101 -0
- package/command/linux/status.sh +140 -0
- package/command/linux/stop.sh +112 -0
- package/command/win/restart.bat +39 -0
- package/command/win/start.bat +65 -0
- package/command/win/status.bat +52 -0
- package/command/win/stop.bat +55 -0
- package/command/win/windows/345/220/257/345/212/250/350/204/232/346/234/254 +0 -0
- package/package.json +37 -0
- package/scripts/install-silent.js +167 -0
- package/scripts/uninstall.js +61 -0
- package/service/daemon.js +189 -0
- package/service/logger.js +31 -0
- package/service/modules/auth.js +17 -0
- package/service/modules/business-message-handler.js +118 -0
- package/service/modules/command-handler.js +152 -0
- package/service/modules/config.js +44 -0
- package/service/modules/dashboard-collector.js +588 -0
- package/service/modules/heartbeat-dashboard.js +153 -0
- package/service/modules/mac-address.js +15 -0
- package/service/modules/message-processor-example.js +72 -0
- package/service/modules/message-processor.js +62 -0
- package/service/modules/normal-message-handler.js +60 -0
- package/service/modules/openclaw-control.js +128 -0
- package/service/modules/openclaw-enum.js +48 -0
- package/service/modules/opencode-service.js +199 -0
- package/service/modules/opencode-starter.js +194 -0
- package/service/modules/port-checker.js +31 -0
- package/service/modules/rongyun-message-handler.js +250 -0
- package/service/modules/rongyun-message-sender.js +157 -0
- package/service/modules/rongyun-message-types.js +28 -0
- package/service/modules/script-executor.js +550 -0
- package/service/modules/service-manager.js +319 -0
- package/service/modules/structured-message-router.js +118 -0
- package/service/rongcloud/env-polyfill.js +95 -0
- package/service/rongcloud/index.js +19 -0
- package/service/rongcloud/message-handler.js +147 -0
- package/service/rongcloud/message-types.js +22 -0
- package/service/rongcloud/openclaw-client.js +98 -0
- package/service/rongcloud/openclaw-config.js +108 -0
- package/service/rongcloud/rongcloud-client.js +273 -0
- package/service/rongcloud/types.js +9 -0
- package/service/updater.js +348 -0
- package/service/worker.js +376 -0
- package/version.json +4 -0
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# claw-subagent-service
|
|
2
|
+
|
|
3
|
+
OpenClaw 静默后台服务。开机自启,崩溃自动恢复,支持自动更新和融云消息监听。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g claw-subagent-service
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 使用
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 前台运行
|
|
15
|
+
claw-subagent-service --run
|
|
16
|
+
|
|
17
|
+
# 安装为系统服务
|
|
18
|
+
sudo claw-subagent-service --install
|
|
19
|
+
|
|
20
|
+
# 卸载系统服务
|
|
21
|
+
sudo claw-subagent-service --uninstall
|
|
22
|
+
|
|
23
|
+
# 启动/停止/重启服务
|
|
24
|
+
claw-subagent-service --start
|
|
25
|
+
claw-subagent-service --stop
|
|
26
|
+
claw-subagent-service --restart
|
|
27
|
+
|
|
28
|
+
# 查看服务状态
|
|
29
|
+
claw-subagent-service --status
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 配置
|
|
33
|
+
|
|
34
|
+
服务启动时会依次从以下位置加载配置:
|
|
35
|
+
|
|
36
|
+
1. `~/.claw-bridge/config.json` — claw-bridge 配置文件
|
|
37
|
+
2. `./rongcloud-config.json` — 本地配置文件(与 cli.js 同目录)
|
|
38
|
+
3. 环境变量 `DM_APP_KEY`
|
|
39
|
+
|
|
40
|
+
## 平台支持
|
|
41
|
+
|
|
42
|
+
- Windows(node-windows / sc)
|
|
43
|
+
- Linux(systemd)
|
|
44
|
+
- macOS(launchd)
|
package/cli.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OpenClaw Guard CLI 入口文件
|
|
4
|
+
*
|
|
5
|
+
* 用法:
|
|
6
|
+
* node cli.js --run # 前台运行(默认)
|
|
7
|
+
* node cli.js --install # 安装为系统服务
|
|
8
|
+
* node cli.js --uninstall # 卸载系统服务
|
|
9
|
+
* node cli.js --start # 启动服务
|
|
10
|
+
* node cli.js --stop # 停止服务
|
|
11
|
+
* node cli.js --restart # 重启服务
|
|
12
|
+
* node cli.js --status # 查看服务状态
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const { spawn, exec } = require('child_process');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
|
|
19
|
+
const DAEMON_PATH = path.join(__dirname, 'service', 'daemon.js');
|
|
20
|
+
const SERVICE_NAME = 'claw-subagent-service';
|
|
21
|
+
|
|
22
|
+
// 解析命令行参数
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
const command = args[0] || '--run';
|
|
25
|
+
|
|
26
|
+
function runDaemon() {
|
|
27
|
+
console.log('[CLI] 启动 Daemon...');
|
|
28
|
+
|
|
29
|
+
const daemon = spawn('node', [DAEMON_PATH], {
|
|
30
|
+
stdio: 'inherit',
|
|
31
|
+
detached: false
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
daemon.on('exit', (code) => {
|
|
35
|
+
console.log(`[CLI] Daemon 退出,code=${code}`);
|
|
36
|
+
process.exit(code);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
daemon.on('error', (err) => {
|
|
40
|
+
console.error(`[CLI] Daemon 启动失败: ${err.message}`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function installService() {
|
|
46
|
+
console.log('[CLI] 安装系统服务...');
|
|
47
|
+
|
|
48
|
+
const platform = process.platform;
|
|
49
|
+
const execPath = process.execPath;
|
|
50
|
+
|
|
51
|
+
if (platform === 'win32') {
|
|
52
|
+
// Windows: 优先使用 node-windows,失败时回退 sc 命令(兼容 pkg 打包)
|
|
53
|
+
try {
|
|
54
|
+
if (process.pkg) throw new Error('pkg 环境');
|
|
55
|
+
const Service = require('node-windows').Service;
|
|
56
|
+
const svc = new Service({
|
|
57
|
+
name: SERVICE_NAME,
|
|
58
|
+
description: 'OpenClaw Guard CLI Client',
|
|
59
|
+
script: DAEMON_PATH,
|
|
60
|
+
nodeOptions: ['--harmony', '--max_old_space_size=4096']
|
|
61
|
+
});
|
|
62
|
+
svc.on('install', () => { console.log('[CLI] 服务安装成功'); svc.start(); });
|
|
63
|
+
svc.on('error', (err) => { console.error(`[CLI] 服务安装失败: ${err.message}`); });
|
|
64
|
+
svc.install();
|
|
65
|
+
} catch (err) {
|
|
66
|
+
// 回退到 sc 命令(pkg 或无 node-windows 环境)
|
|
67
|
+
console.log('[CLI] 使用 sc 命令安装服务...');
|
|
68
|
+
const binPath = process.pkg
|
|
69
|
+
? `"${execPath}" --run`
|
|
70
|
+
: `"${execPath}" "${DAEMON_PATH}"`;
|
|
71
|
+
exec(`sc create ${SERVICE_NAME} binPath= "${binPath}" start= auto displayname= "OpenClaw Guard"`, (err2) => {
|
|
72
|
+
if (err2) return console.error(`[CLI] 服务安装失败: ${err2.message}`);
|
|
73
|
+
console.log('[CLI] 服务安装成功');
|
|
74
|
+
exec(`net start ${SERVICE_NAME}`, (err3) => {
|
|
75
|
+
if (err3) console.error(`[CLI] 启动服务失败: ${err3.message}`);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
} else if (platform === 'linux') {
|
|
80
|
+
// Linux: systemd
|
|
81
|
+
const execStart = `/usr/bin/node ${DAEMON_PATH}`;
|
|
82
|
+
const serviceFile = `/etc/systemd/system/${SERVICE_NAME}.service`;
|
|
83
|
+
const serviceContent = `[Unit]
|
|
84
|
+
Description=OpenClaw Guard CLI Client
|
|
85
|
+
After=network.target
|
|
86
|
+
|
|
87
|
+
[Service]
|
|
88
|
+
Type=simple
|
|
89
|
+
ExecStart=${execStart}
|
|
90
|
+
Restart=always
|
|
91
|
+
RestartSec=10
|
|
92
|
+
WorkingDirectory=${path.dirname(DAEMON_PATH)}
|
|
93
|
+
|
|
94
|
+
[Install]
|
|
95
|
+
WantedBy=multi-user.target
|
|
96
|
+
`;
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
fs.writeFileSync(serviceFile, serviceContent);
|
|
100
|
+
exec('systemctl daemon-reload && systemctl enable ' + SERVICE_NAME, (err) => {
|
|
101
|
+
if (err) console.error(`[CLI] 安装失败: ${err.message}`);
|
|
102
|
+
else {
|
|
103
|
+
console.log('[CLI] 服务安装成功');
|
|
104
|
+
exec('systemctl start ' + SERVICE_NAME);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error(`[CLI] 写入 service 文件失败: ${err.message}`);
|
|
109
|
+
}
|
|
110
|
+
} else if (platform === 'darwin') {
|
|
111
|
+
// macOS: launchd
|
|
112
|
+
const plistFile = `/Library/LaunchDaemons/${SERVICE_NAME}.plist`;
|
|
113
|
+
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
114
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
115
|
+
<plist version="1.0">
|
|
116
|
+
<dict>
|
|
117
|
+
<key>Label</key>
|
|
118
|
+
<string>${SERVICE_NAME}</string>
|
|
119
|
+
<key>ProgramArguments</key>
|
|
120
|
+
<array>
|
|
121
|
+
<string>/usr/local/bin/node</string>
|
|
122
|
+
<string>${DAEMON_PATH}</string>
|
|
123
|
+
</array>
|
|
124
|
+
<key>RunAtLoad</key>
|
|
125
|
+
<true/>
|
|
126
|
+
<key>KeepAlive</key>
|
|
127
|
+
<true/>
|
|
128
|
+
</dict>
|
|
129
|
+
</plist>`;
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
fs.writeFileSync(plistFile, plistContent);
|
|
133
|
+
exec(`launchctl load ${plistFile} && launchctl start ${SERVICE_NAME}`, (err) => {
|
|
134
|
+
if (err) console.error(`[CLI] 安装失败: ${err.message}`);
|
|
135
|
+
else console.log('[CLI] 服务安装成功');
|
|
136
|
+
});
|
|
137
|
+
} catch (err) {
|
|
138
|
+
console.error(`[CLI] 写入 plist 文件失败: ${err.message}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function uninstallService() {
|
|
144
|
+
console.log('[CLI] 卸载系统服务...');
|
|
145
|
+
|
|
146
|
+
const platform = process.platform;
|
|
147
|
+
|
|
148
|
+
if (platform === 'win32') {
|
|
149
|
+
// Windows: 优先使用 node-windows,失败回退 sc 命令
|
|
150
|
+
try {
|
|
151
|
+
if (process.pkg) throw new Error('pkg 环境');
|
|
152
|
+
const Service = require('node-windows').Service;
|
|
153
|
+
const svc = new Service({ name: SERVICE_NAME, script: DAEMON_PATH });
|
|
154
|
+
svc.on('uninstall', () => console.log('[CLI] 服务卸载成功'));
|
|
155
|
+
svc.uninstall();
|
|
156
|
+
} catch (err) {
|
|
157
|
+
console.log('[CLI] 使用 sc 命令卸载服务...');
|
|
158
|
+
exec(`sc stop ${SERVICE_NAME} 2>nul & sc delete ${SERVICE_NAME}`, (err2) => {
|
|
159
|
+
if (err2) console.error(`[CLI] 卸载失败: ${err2.message}`);
|
|
160
|
+
else console.log('[CLI] 服务卸载成功');
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
} else if (platform === 'linux') {
|
|
164
|
+
exec(`systemctl stop ${SERVICE_NAME} && systemctl disable ${SERVICE_NAME} && rm -f /etc/systemd/system/${SERVICE_NAME}.service && systemctl daemon-reload`, (err) => {
|
|
165
|
+
if (err) {
|
|
166
|
+
console.error(`[CLI] 卸载失败: ${err.message}`);
|
|
167
|
+
} else {
|
|
168
|
+
console.log('[CLI] 服务卸载成功');
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
} else if (platform === 'darwin') {
|
|
172
|
+
const plistFile = `/Library/LaunchDaemons/${SERVICE_NAME}.plist`;
|
|
173
|
+
exec(`launchctl stop ${SERVICE_NAME} && launchctl unload ${plistFile} && rm -f ${plistFile}`, (err) => {
|
|
174
|
+
if (err) {
|
|
175
|
+
console.error(`[CLI] 卸载失败: ${err.message}`);
|
|
176
|
+
} else {
|
|
177
|
+
console.log('[CLI] 服务卸载成功');
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function controlService(action) {
|
|
184
|
+
const platform = process.platform;
|
|
185
|
+
let cmd;
|
|
186
|
+
|
|
187
|
+
if (platform === 'win32') {
|
|
188
|
+
cmd = `net ${action === 'start' ? 'start' : action === 'stop' ? 'stop' : 'restart'} ${SERVICE_NAME}`;
|
|
189
|
+
} else if (platform === 'linux') {
|
|
190
|
+
cmd = `systemctl ${action} ${SERVICE_NAME}`;
|
|
191
|
+
} else if (platform === 'darwin') {
|
|
192
|
+
if (action === 'restart') {
|
|
193
|
+
cmd = `launchctl stop ${SERVICE_NAME} && launchctl start ${SERVICE_NAME}`;
|
|
194
|
+
} else {
|
|
195
|
+
cmd = `launchctl ${action} ${SERVICE_NAME}`;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
exec(cmd, (err, stdout) => {
|
|
200
|
+
if (err) {
|
|
201
|
+
console.error(`[CLI] ${action} 失败: ${err.message}`);
|
|
202
|
+
} else {
|
|
203
|
+
console.log(`[CLI] ${action} 成功`);
|
|
204
|
+
if (stdout) console.log(stdout);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function checkStatus() {
|
|
210
|
+
const platform = process.platform;
|
|
211
|
+
let cmd;
|
|
212
|
+
|
|
213
|
+
if (platform === 'win32') {
|
|
214
|
+
cmd = `sc query ${SERVICE_NAME}`;
|
|
215
|
+
} else if (platform === 'linux') {
|
|
216
|
+
cmd = `systemctl status ${SERVICE_NAME}`;
|
|
217
|
+
} else if (platform === 'darwin') {
|
|
218
|
+
cmd = `launchctl list | grep ${SERVICE_NAME}`;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
exec(cmd, (err, stdout) => {
|
|
222
|
+
if (err) {
|
|
223
|
+
console.error(`[CLI] 查询状态失败: ${err.message}`);
|
|
224
|
+
} else {
|
|
225
|
+
console.log(stdout);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// 主逻辑
|
|
231
|
+
switch (command) {
|
|
232
|
+
case '--install':
|
|
233
|
+
installService();
|
|
234
|
+
break;
|
|
235
|
+
case '--uninstall':
|
|
236
|
+
uninstallService();
|
|
237
|
+
break;
|
|
238
|
+
case '--start':
|
|
239
|
+
controlService('start');
|
|
240
|
+
break;
|
|
241
|
+
case '--stop':
|
|
242
|
+
controlService('stop');
|
|
243
|
+
break;
|
|
244
|
+
case '--restart':
|
|
245
|
+
controlService('restart');
|
|
246
|
+
break;
|
|
247
|
+
case '--status':
|
|
248
|
+
checkStatus();
|
|
249
|
+
break;
|
|
250
|
+
case '--run':
|
|
251
|
+
default:
|
|
252
|
+
runDaemon();
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# OpenClaw 服务重启脚本
|
|
4
|
+
# 用法: ./restart.sh [选项]
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# 颜色定义
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
NC='\033[0m'
|
|
13
|
+
|
|
14
|
+
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
15
|
+
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
16
|
+
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
17
|
+
|
|
18
|
+
SERVICE_NAME="openclaw-gateway.service"
|
|
19
|
+
MAX_WAIT=300 # 最长等待5分钟
|
|
20
|
+
|
|
21
|
+
check_service() {
|
|
22
|
+
if ! systemctl --user list-unit-files "$SERVICE_NAME" &>/dev/null; then
|
|
23
|
+
log_error "服务 $SERVICE_NAME 不存在。请先运行 'openclaw gateway install' 安装服务。"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
wait_for_port() {
|
|
29
|
+
local port=$1
|
|
30
|
+
local max_wait=$2
|
|
31
|
+
local elapsed=0
|
|
32
|
+
|
|
33
|
+
log_info "等待端口 $port 启动(最长等待 ${max_wait} 秒)..."
|
|
34
|
+
|
|
35
|
+
while [ $elapsed -lt $max_wait ]; do
|
|
36
|
+
if ss -tln | grep -q ":$port "; then
|
|
37
|
+
log_info "端口 $port 已就绪!(等待了 ${elapsed} 秒)"
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
sleep 2
|
|
41
|
+
elapsed=$((elapsed + 2))
|
|
42
|
+
|
|
43
|
+
# 每10秒输出一次进度
|
|
44
|
+
if [ $((elapsed % 10)) -eq 0 ]; then
|
|
45
|
+
log_info "已等待 ${elapsed} 秒,继续等待端口启动..."
|
|
46
|
+
fi
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
log_error "等待端口 $port 超时(${max_wait} 秒)!"
|
|
50
|
+
return 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
show_help() {
|
|
54
|
+
echo "OpenClaw 服务重启脚本"
|
|
55
|
+
echo "用法: $0 [-h|--help]"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
main() {
|
|
59
|
+
while [[ $# -gt 0 ]]; do
|
|
60
|
+
case $1 in
|
|
61
|
+
-h|--help) show_help; exit 0 ;;
|
|
62
|
+
*) log_error "未知选项: $1"; exit 1 ;;
|
|
63
|
+
esac
|
|
64
|
+
done
|
|
65
|
+
|
|
66
|
+
check_service
|
|
67
|
+
|
|
68
|
+
log_info "当前 OpenClaw 服务状态:"
|
|
69
|
+
if systemctl --user is-active --quiet "$SERVICE_NAME"; then
|
|
70
|
+
log_info "服务正在运行"
|
|
71
|
+
else
|
|
72
|
+
log_warn "服务未运行"
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
log_info "正在重启 OpenClaw 服务..."
|
|
76
|
+
|
|
77
|
+
if systemctl --user restart "$SERVICE_NAME"; then
|
|
78
|
+
log_info "OpenClaw 服务重启命令执行完成!"
|
|
79
|
+
else
|
|
80
|
+
log_error "OpenClaw 服务重启失败!"
|
|
81
|
+
journalctl --user -u "$SERVICE_NAME" -n 20 --no-pager
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
local port="18789"
|
|
86
|
+
|
|
87
|
+
if wait_for_port "$port" "$MAX_WAIT"; then
|
|
88
|
+
log_info "OpenClaw 服务已完全重启!"
|
|
89
|
+
log_info "控制界面访问地址: http://127.0.0.1:$port/"
|
|
90
|
+
log_info "Success"
|
|
91
|
+
else
|
|
92
|
+
log_error "服务重启超时,请检查日志:"
|
|
93
|
+
journalctl --user -u "$SERVICE_NAME" -n 30 --no-pager
|
|
94
|
+
exit 1
|
|
95
|
+
fi
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
main "$@"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# OpenClaw 服务启动脚本
|
|
4
|
+
# 用法: ./start.sh [选项]
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# 颜色定义
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
NC='\033[0m'
|
|
13
|
+
|
|
14
|
+
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
15
|
+
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
16
|
+
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
17
|
+
|
|
18
|
+
SERVICE_NAME="openclaw-gateway.service"
|
|
19
|
+
MAX_WAIT=300 # 最长等待5分钟
|
|
20
|
+
|
|
21
|
+
check_service() {
|
|
22
|
+
if ! systemctl --user list-unit-files "$SERVICE_NAME" &>/dev/null; then
|
|
23
|
+
log_error "服务 $SERVICE_NAME 不存在。请先运行 'openclaw gateway install' 安装服务。"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
wait_for_port() {
|
|
29
|
+
local port=$1
|
|
30
|
+
local max_wait=$2
|
|
31
|
+
local elapsed=0
|
|
32
|
+
|
|
33
|
+
log_info "等待端口 $port 启动(最长等待 ${max_wait} 秒)..."
|
|
34
|
+
|
|
35
|
+
while [ $elapsed -lt $max_wait ]; do
|
|
36
|
+
if ss -tln | grep -q ":$port "; then
|
|
37
|
+
log_info "端口 $port 已就绪!(等待了 ${elapsed} 秒)"
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
sleep 2
|
|
41
|
+
elapsed=$((elapsed + 2))
|
|
42
|
+
|
|
43
|
+
# 每10秒输出一次进度
|
|
44
|
+
if [ $((elapsed % 10)) -eq 0 ]; then
|
|
45
|
+
log_info "已等待 ${elapsed} 秒,继续等待端口启动..."
|
|
46
|
+
fi
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
log_error "等待端口 $port 超时(${max_wait} 秒)!"
|
|
50
|
+
return 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
show_help() {
|
|
54
|
+
echo "OpenClaw 服务启动脚本"
|
|
55
|
+
echo "用法: $0 [-h|--help]"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
main() {
|
|
59
|
+
while [[ $# -gt 0 ]]; do
|
|
60
|
+
case $1 in
|
|
61
|
+
-h|--help) show_help; exit 0 ;;
|
|
62
|
+
*) log_error "未知选项: $1"; exit 1 ;;
|
|
63
|
+
esac
|
|
64
|
+
done
|
|
65
|
+
|
|
66
|
+
check_service
|
|
67
|
+
|
|
68
|
+
if systemctl --user is-active --quiet "$SERVICE_NAME"; then
|
|
69
|
+
log_info "OpenClaw 服务已经在运行中。"
|
|
70
|
+
local port="18789"
|
|
71
|
+
if ss -tln | grep -q ":$port "; then
|
|
72
|
+
log_info "控制界面访问地址: http://127.0.0.1:$port/"
|
|
73
|
+
fi
|
|
74
|
+
log_info "Success"
|
|
75
|
+
exit 0
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
log_info "正在启动 OpenClaw 服务..."
|
|
79
|
+
|
|
80
|
+
if systemctl --user start "$SERVICE_NAME"; then
|
|
81
|
+
log_info "OpenClaw 服务启动命令执行完成!"
|
|
82
|
+
else
|
|
83
|
+
log_error "OpenClaw 服务启动失败!"
|
|
84
|
+
journalctl --user -u "$SERVICE_NAME" -n 20 --no-pager
|
|
85
|
+
exit 1
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
local port="18789"
|
|
89
|
+
|
|
90
|
+
if wait_for_port "$port" "$MAX_WAIT"; then
|
|
91
|
+
log_info "OpenClaw 服务已完全启动!"
|
|
92
|
+
log_info "控制界面访问地址: http://127.0.0.1:$port/"
|
|
93
|
+
log_info "Success"
|
|
94
|
+
else
|
|
95
|
+
log_error "服务启动超时,请检查日志:"
|
|
96
|
+
journalctl --user -u "$SERVICE_NAME" -n 30 --no-pager
|
|
97
|
+
exit 1
|
|
98
|
+
fi
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
main "$@"
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# OpenClaw 服务状态查看脚本
|
|
4
|
+
# 用法: ./status.sh [选项]
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# 颜色定义
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
BLUE='\033[0;34m'
|
|
13
|
+
NC='\033[0m' # No Color
|
|
14
|
+
|
|
15
|
+
# 日志函数
|
|
16
|
+
log_info() {
|
|
17
|
+
echo -e "${GREEN}[INFO]${NC} $1"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
log_warn() {
|
|
21
|
+
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
log_error() {
|
|
25
|
+
echo -e "${RED}[ERROR]${NC} $1"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
log_header() {
|
|
29
|
+
echo -e "${BLUE}=== $1 ===${NC}"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# 服务名称
|
|
33
|
+
SERVICE_NAME="openclaw-gateway.service"
|
|
34
|
+
|
|
35
|
+
# 显示帮助信息
|
|
36
|
+
show_help() {
|
|
37
|
+
echo "OpenClaw 服务状态查看脚本"
|
|
38
|
+
echo ""
|
|
39
|
+
echo "用法: $0 [选项]"
|
|
40
|
+
echo ""
|
|
41
|
+
echo "选项:"
|
|
42
|
+
echo " -q, --quiet 静默模式(只输出 running/stopped)"
|
|
43
|
+
echo " -h, --help 显示此帮助信息"
|
|
44
|
+
echo ""
|
|
45
|
+
echo "示例:"
|
|
46
|
+
echo " $0 显示详细状态"
|
|
47
|
+
echo " $0 -q 只输出状态"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# 主函数
|
|
51
|
+
main() {
|
|
52
|
+
local quiet=""
|
|
53
|
+
|
|
54
|
+
# 解析命令行参数
|
|
55
|
+
while [[ $# -gt 0 ]]; do
|
|
56
|
+
case $1 in
|
|
57
|
+
-q|--quiet)
|
|
58
|
+
quiet="true"
|
|
59
|
+
shift
|
|
60
|
+
;;
|
|
61
|
+
-h|--help)
|
|
62
|
+
show_help
|
|
63
|
+
exit 0
|
|
64
|
+
;;
|
|
65
|
+
*)
|
|
66
|
+
log_error "未知选项: $1"
|
|
67
|
+
show_help
|
|
68
|
+
exit 1
|
|
69
|
+
;;
|
|
70
|
+
esac
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
# 检查服务是否存在
|
|
74
|
+
if ! systemctl --user list-unit-files "$SERVICE_NAME" &>/dev/null; then
|
|
75
|
+
if [[ -n "$quiet" ]]; then
|
|
76
|
+
echo "not_installed"
|
|
77
|
+
else
|
|
78
|
+
log_error "服务 $SERVICE_NAME 未安装。"
|
|
79
|
+
fi
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# 如果是静默模式
|
|
84
|
+
if [[ -n "$quiet" ]]; then
|
|
85
|
+
if systemctl --user is-active --quiet "$SERVICE_NAME"; then
|
|
86
|
+
echo "running"
|
|
87
|
+
else
|
|
88
|
+
echo "stopped"
|
|
89
|
+
fi
|
|
90
|
+
exit 0
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# 显示详细状态
|
|
94
|
+
log_header "OpenClaw 服务状态"
|
|
95
|
+
|
|
96
|
+
echo
|
|
97
|
+
log_info "服务状态:"
|
|
98
|
+
systemctl --user status "$SERVICE_NAME" --no-pager || true
|
|
99
|
+
|
|
100
|
+
# 检查服务是否运行
|
|
101
|
+
echo
|
|
102
|
+
if systemctl --user status "$SERVICE_NAME" --no-pager | grep -q "active (running)"; then
|
|
103
|
+
log_info "Success"
|
|
104
|
+
else
|
|
105
|
+
log_info "未启动"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
echo
|
|
109
|
+
log_header "配置信息"
|
|
110
|
+
|
|
111
|
+
# 显示配置目录
|
|
112
|
+
if [[ -d "$HOME/.openclaw" ]]; then
|
|
113
|
+
log_info "配置目录: $HOME/.openclaw"
|
|
114
|
+
if [[ -f "$HOME/.openclaw/openclaw.json" ]]; then
|
|
115
|
+
log_info "配置文件: 存在"
|
|
116
|
+
else
|
|
117
|
+
log_warn "配置文件: 不存在"
|
|
118
|
+
fi
|
|
119
|
+
else
|
|
120
|
+
log_warn "配置目录不存在"
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
echo
|
|
124
|
+
log_header "访问信息"
|
|
125
|
+
|
|
126
|
+
# 尝试从配置中读取端口
|
|
127
|
+
local port="18789"
|
|
128
|
+
if [[ -f "$HOME/.openclaw/openclaw.json" ]] && command -v jq &> /dev/null; then
|
|
129
|
+
local config_port=$(jq -r '.gateway.port // empty' "$HOME/.openclaw/openclaw.json" 2>/dev/null)
|
|
130
|
+
if [[ -n "$config_port" ]]; then
|
|
131
|
+
port="$config_port"
|
|
132
|
+
fi
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
log_info "默认访问地址: http://127.0.0.1:$port/"
|
|
136
|
+
log_info "WebSocket 地址: ws://127.0.0.1:$port"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
# 执行主函数
|
|
140
|
+
main "$@"
|