claw-subagent-service 0.0.127 → 0.0.129
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/command/linux/start.sh
CHANGED
|
@@ -17,6 +17,14 @@ log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
|
17
17
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
18
18
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
19
19
|
|
|
20
|
+
# 调试模式:如果 DEBUG=1,输出更多日志
|
|
21
|
+
DEBUG="${DEBUG:-0}"
|
|
22
|
+
debug_log() {
|
|
23
|
+
if [ "$DEBUG" = "1" ]; then
|
|
24
|
+
echo -e "${YELLOW}[DEBUG]${NC} $1"
|
|
25
|
+
fi
|
|
26
|
+
}
|
|
27
|
+
|
|
20
28
|
SERVICE_NAME="openclaw-gateway.service"
|
|
21
29
|
MAX_WAIT=300 # 最长等待5分钟
|
|
22
30
|
PORT="18789"
|
|
@@ -187,10 +195,13 @@ start_docker() {
|
|
|
187
195
|
fi
|
|
188
196
|
|
|
189
197
|
# 检查 openclaw 命令是否存在
|
|
198
|
+
debug_log "检查 openclaw 命令..."
|
|
190
199
|
if ! command -v openclaw &>/dev/null; then
|
|
191
200
|
log_error "openclaw 命令未找到,请先安装 OpenClaw。"
|
|
201
|
+
log_error "PATH: $PATH"
|
|
192
202
|
exit 1
|
|
193
203
|
fi
|
|
204
|
+
debug_log "openclaw 命令存在: $(which openclaw)"
|
|
194
205
|
|
|
195
206
|
# 确保日志目录存在
|
|
196
207
|
local log_dir="/tmp/openclaw"
|
|
@@ -201,10 +212,41 @@ start_docker() {
|
|
|
201
212
|
|
|
202
213
|
log_info "正在启动 OpenClaw 服务..."
|
|
203
214
|
|
|
204
|
-
# 使用 nohup
|
|
205
|
-
|
|
215
|
+
# 使用 nohup 后台启动,指定 host 为 0.0.0.0(Docker 环境需要)
|
|
216
|
+
# 注意:openclaw gateway 可能需要不同的参数格式
|
|
217
|
+
log_info "执行命令: nohup openclaw gateway --port $PORT --host 0.0.0.0"
|
|
218
|
+
debug_log "当前工作目录: $(pwd)"
|
|
219
|
+
debug_log "当前用户: $(whoami)"
|
|
220
|
+
debug_log "环境变量 PATH: $PATH"
|
|
221
|
+
|
|
222
|
+
# 先检查 openclaw 版本
|
|
223
|
+
debug_log "openclaw 版本信息:"
|
|
224
|
+
openclaw --version 2>&1 | head -5 || true
|
|
225
|
+
|
|
226
|
+
# 检查 openclaw gateway help,确认参数格式
|
|
227
|
+
debug_log "openclaw gateway help 信息:"
|
|
228
|
+
openclaw gateway --help 2>&1 | head -20 || true
|
|
229
|
+
|
|
230
|
+
# 尝试启动,如果失败则尝试其他参数格式
|
|
231
|
+
log_info "尝试启动 openclaw gateway..."
|
|
232
|
+
nohup openclaw gateway --port "$PORT" --host 0.0.0.0 > "$log_file" 2>&1 &
|
|
233
|
+
|
|
234
|
+
# 等待 2 秒检查进程是否启动
|
|
235
|
+
sleep 2
|
|
236
|
+
local started_pid=$!
|
|
237
|
+
if ! ps -p "$started_pid" > /dev/null 2>&1; then
|
|
238
|
+
log_warn "进程 $started_pid 已退出,尝试其他启动方式..."
|
|
239
|
+
# 尝试不带 --host 参数
|
|
240
|
+
nohup openclaw gateway --port "$PORT" > "$log_file" 2>&1 &
|
|
241
|
+
started_pid=$!
|
|
242
|
+
sleep 2
|
|
243
|
+
if ! ps -p "$started_pid" > /dev/null 2>&1; then
|
|
244
|
+
log_error "所有启动方式均失败,请检查日志:$log_file"
|
|
245
|
+
exit 1
|
|
246
|
+
fi
|
|
247
|
+
fi
|
|
206
248
|
|
|
207
|
-
log_info "OpenClaw 服务启动命令已发送(PID:
|
|
249
|
+
log_info "OpenClaw 服务启动命令已发送(PID: $started_pid)"
|
|
208
250
|
log_info "日志文件: $log_file"
|
|
209
251
|
|
|
210
252
|
# 等待端口就绪
|
package/package.json
CHANGED
|
@@ -181,25 +181,40 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
|
|
|
181
181
|
|
|
182
182
|
async function executeCommand(command, window, sendResponse) {
|
|
183
183
|
const cmdName = getCommandName(command);
|
|
184
|
-
console.log(`[OpenClawControl] ${cmdName}
|
|
184
|
+
console.log(`[OpenClawControl] ====== 开始执行 ${cmdName} 命令 ======`);
|
|
185
|
+
console.log(`[OpenClawControl] 命令代码: ${command}`);
|
|
186
|
+
console.log(`[OpenClawControl] 平台: ${process.platform}`);
|
|
185
187
|
|
|
186
188
|
let result;
|
|
187
189
|
|
|
188
190
|
// 优先尝试 ServiceManager(systemd 模式)
|
|
189
191
|
if (process.platform === 'linux' || process.platform === 'darwin') {
|
|
192
|
+
console.log(`[OpenClawControl] 尝试使用 ServiceManager...`);
|
|
190
193
|
result = await manageWithServiceManager(command);
|
|
194
|
+
if (result) {
|
|
195
|
+
console.log(`[OpenClawControl] ServiceManager 结果: ${result.status} - ${result.message}`);
|
|
196
|
+
} else {
|
|
197
|
+
console.log(`[OpenClawControl] ServiceManager 不可用,回退到脚本方式`);
|
|
198
|
+
}
|
|
191
199
|
}
|
|
192
200
|
|
|
193
201
|
// 如果 ServiceManager 失败或不是 Linux/macOS,使用脚本方式
|
|
194
202
|
let scriptOutput = '';
|
|
195
203
|
if (!result) {
|
|
204
|
+
console.log(`[OpenClawControl] 使用脚本方式执行...`);
|
|
196
205
|
const scriptResult = await executeWithScript(command);
|
|
197
206
|
result = scriptResult.result;
|
|
198
207
|
scriptOutput = scriptResult.output;
|
|
208
|
+
console.log(`[OpenClawControl] 脚本执行结果: ${result.status} - ${result.message}`);
|
|
209
|
+
if (scriptOutput) {
|
|
210
|
+
console.log(`[OpenClawControl] 脚本输出长度: ${scriptOutput.length}`);
|
|
211
|
+
}
|
|
199
212
|
}
|
|
200
213
|
|
|
201
214
|
// 验证结果(传递脚本输出用于后备检查)
|
|
215
|
+
console.log(`[OpenClawControl] 开始验证命令结果...`);
|
|
202
216
|
result = await verifyCommandResult(command, result, scriptOutput);
|
|
217
|
+
console.log(`[OpenClawControl] 验证后结果: ${result.status} - ${result.message}`);
|
|
203
218
|
|
|
204
219
|
// 输出日志
|
|
205
220
|
if (result.status === OpenClawServiceStatus.START_SUCCESS ||
|
|
@@ -221,33 +236,41 @@ async function executeCommand(command, window, sendResponse) {
|
|
|
221
236
|
|
|
222
237
|
// 获取操作后的真实状态
|
|
223
238
|
let realStatus = result.status;
|
|
239
|
+
let realMessage = result.message;
|
|
224
240
|
if (command === OpenClawCommandEnum.STOP || command === OpenClawCommandEnum.START || command === OpenClawCommandEnum.RESTART) {
|
|
225
241
|
try {
|
|
242
|
+
console.log(`[OpenClawControl] 检测操作后的真实状态...`);
|
|
226
243
|
const { getOpenClawStatus } = require('./port-checker');
|
|
227
244
|
const portStatus = await getOpenClawStatus(18789);
|
|
245
|
+
console.log(`[OpenClawControl] 端口状态: ${portStatus}`);
|
|
228
246
|
// 更新真实状态
|
|
229
247
|
if (command === OpenClawCommandEnum.STOP) {
|
|
230
248
|
realStatus = portStatus === 1 ? OpenClawServiceStatus.RUNNING : OpenClawServiceStatus.STOP_SUCCESS;
|
|
249
|
+
realMessage = portStatus === 1 ? '停止失败: 服务仍在运行' : '服务已停止';
|
|
231
250
|
} else if (command === OpenClawCommandEnum.START) {
|
|
232
251
|
realStatus = portStatus === 1 ? OpenClawServiceStatus.START_SUCCESS : OpenClawServiceStatus.ERROR;
|
|
252
|
+
realMessage = portStatus === 1 ? '服务已启动' : '启动失败: 服务未运行';
|
|
233
253
|
} else if (command === OpenClawCommandEnum.RESTART) {
|
|
234
254
|
realStatus = portStatus === 1 ? OpenClawServiceStatus.RESTART_SUCCESS : OpenClawServiceStatus.ERROR;
|
|
255
|
+
realMessage = portStatus === 1 ? '服务已重启' : '重启失败: 服务未运行';
|
|
235
256
|
}
|
|
236
|
-
console.log(`[OpenClawControl]
|
|
257
|
+
console.log(`[OpenClawControl] 操作后真实状态: portStatus=${portStatus}, realStatus=${realStatus}, message=${realMessage}`);
|
|
237
258
|
} catch (e) {
|
|
238
259
|
console.error(`[OpenClawControl] 真实状态检测失败: ${e.message}`);
|
|
239
260
|
}
|
|
240
261
|
}
|
|
241
262
|
|
|
263
|
+
console.log(`[OpenClawControl] 发送响应: status=${httpStatus}, message=${realMessage}`);
|
|
242
264
|
sendResponse({
|
|
243
265
|
type: 'command_result',
|
|
244
266
|
command,
|
|
245
267
|
status: httpStatus,
|
|
246
|
-
message:
|
|
268
|
+
message: realMessage,
|
|
247
269
|
service_status: realStatus
|
|
248
270
|
});
|
|
249
271
|
}
|
|
250
272
|
|
|
273
|
+
console.log(`[OpenClawControl] ====== ${cmdName} 命令执行完成 ======`);
|
|
251
274
|
return result;
|
|
252
275
|
}
|
|
253
276
|
|
|
@@ -27,7 +27,13 @@ function checkPortListening(port, host = '127.0.0.1') {
|
|
|
27
27
|
resolve(false);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
try {
|
|
31
|
+
sock.connect(port, host);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.error(`[PortChecker] 连接异常: ${err.message}`);
|
|
34
|
+
sock.destroy();
|
|
35
|
+
resolve(false);
|
|
36
|
+
}
|
|
31
37
|
});
|
|
32
38
|
}
|
|
33
39
|
|
|
@@ -150,6 +156,27 @@ async function getOpenClawStatus(port = 18789) {
|
|
|
150
156
|
const processExists = checkProcessExists();
|
|
151
157
|
if (processExists) {
|
|
152
158
|
console.warn(`[PortChecker] 警告: openclaw 进程存在,但端口 ${port} 未监听。服务可能未正确启动或已崩溃。`);
|
|
159
|
+
// 尝试获取进程详细信息
|
|
160
|
+
try {
|
|
161
|
+
const { execSync } = require('child_process');
|
|
162
|
+
const psOutput = execSync('ps aux | grep -v grep | grep openclaw', { encoding: 'utf8', timeout: 5000 }).trim();
|
|
163
|
+
console.log(`[PortChecker] 进程详细信息:\n${psOutput}`);
|
|
164
|
+
|
|
165
|
+
// 尝试获取进程监听的端口
|
|
166
|
+
const pid = psOutput.split(/\s+/)[1];
|
|
167
|
+
if (pid) {
|
|
168
|
+
try {
|
|
169
|
+
const netstatOutput = execSync(`netstat -tlnp 2>/dev/null | grep ${pid} || ss -tlnp 2>/dev/null | grep ${pid}`, { encoding: 'utf8', timeout: 5000 }).trim();
|
|
170
|
+
if (netstatOutput) {
|
|
171
|
+
console.log(`[PortChecker] 进程 ${pid} 监听的端口:\n${netstatOutput}`);
|
|
172
|
+
}
|
|
173
|
+
} catch (e) {
|
|
174
|
+
// 忽略错误
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} catch (e) {
|
|
178
|
+
// 忽略错误
|
|
179
|
+
}
|
|
153
180
|
}
|
|
154
181
|
|
|
155
182
|
console.log(`[PortChecker] 端口 ${port} 检测为未运行`);
|
|
@@ -164,9 +164,27 @@ class RongyunMessageHandler {
|
|
|
164
164
|
// 异步命令不在这里响应,因为已经提前响应了
|
|
165
165
|
// 但我们可以在这里记录执行结果
|
|
166
166
|
this.logInfo(`[RongyunMessageHandler] 命令执行完成: command=${command}, status=${response.status}, message=${response.message}`);
|
|
167
|
+
}).then(() => {
|
|
168
|
+
// 命令执行完成后,立即释放锁
|
|
169
|
+
this.commandLock = false;
|
|
170
|
+
if (this.commandLockTimer) {
|
|
171
|
+
clearTimeout(this.commandLockTimer);
|
|
172
|
+
this.commandLockTimer = null;
|
|
173
|
+
}
|
|
167
174
|
}).catch(err => {
|
|
168
175
|
this.logError(`[RongyunMessageHandler] 命令执行失败: ${err.message}`);
|
|
176
|
+
// 执行失败后也要释放锁
|
|
177
|
+
this.commandLock = false;
|
|
178
|
+
if (this.commandLockTimer) {
|
|
179
|
+
clearTimeout(this.commandLockTimer);
|
|
180
|
+
this.commandLockTimer = null;
|
|
181
|
+
}
|
|
169
182
|
});
|
|
183
|
+
|
|
184
|
+
// 异步命令立即返回,不等待执行完成
|
|
185
|
+
if (isAsyncCommand) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
170
188
|
} catch (e) {
|
|
171
189
|
const msg = e instanceof Error ? e.message : String(e);
|
|
172
190
|
this.logError(`命令执行异常: ${msg}`);
|
|
@@ -176,7 +194,7 @@ class RongyunMessageHandler {
|
|
|
176
194
|
status: 'error',
|
|
177
195
|
message: msg
|
|
178
196
|
}, requestId, sourceId);
|
|
179
|
-
|
|
197
|
+
// 同步命令执行异常时释放锁
|
|
180
198
|
this.commandLock = false;
|
|
181
199
|
if (this.commandLockTimer) {
|
|
182
200
|
clearTimeout(this.commandLockTimer);
|
|
@@ -88,15 +88,22 @@ class ScriptExecutor {
|
|
|
88
88
|
const scriptPath = path.join(this.scriptDir, scriptName);
|
|
89
89
|
|
|
90
90
|
try {
|
|
91
|
+
console.log(`[ScriptExecutor] 开始执行脚本: ${scriptPath}`);
|
|
91
92
|
const { stdout, stderr, exitCode } = await this.runScript(scriptPath);
|
|
92
93
|
const fullOutput = stdout + stderr;
|
|
93
94
|
|
|
94
95
|
// 调试日志:记录脚本实际输出
|
|
95
|
-
console.log(`[ScriptExecutor]
|
|
96
|
-
console.log(`[ScriptExecutor] ${scriptName} 输出:\n${fullOutput}`);
|
|
96
|
+
console.log(`[ScriptExecutor] 执行脚本完成: ${scriptPath}`);
|
|
97
97
|
console.log(`[ScriptExecutor] ${scriptName} 退出码: ${exitCode}`);
|
|
98
|
+
console.log(`[ScriptExecutor] ${scriptName} 输出长度: ${fullOutput.length}`);
|
|
99
|
+
if (fullOutput.length > 0) {
|
|
100
|
+
console.log(`[ScriptExecutor] ${scriptName} 输出:\n${fullOutput}`);
|
|
101
|
+
} else {
|
|
102
|
+
console.log(`[ScriptExecutor] ${scriptName} 无输出`);
|
|
103
|
+
}
|
|
98
104
|
|
|
99
105
|
const result = this.parseStatus(command, fullOutput);
|
|
106
|
+
console.log(`[ScriptExecutor] ${scriptName} 解析结果: status=${result.status}, message=${result.message}`);
|
|
100
107
|
|
|
101
108
|
// 对于 STOP 命令,如果脚本退出码非零,强制返回错误
|
|
102
109
|
if (command === OpenClawCommandEnum.STOP && exitCode !== 0) {
|
|
@@ -115,6 +122,7 @@ class ScriptExecutor {
|
|
|
115
122
|
};
|
|
116
123
|
} catch (e) {
|
|
117
124
|
const msg = e instanceof Error ? e.message : String(e);
|
|
125
|
+
console.error(`[ScriptExecutor] 执行脚本异常: ${msg}`);
|
|
118
126
|
return { status: OpenClawServiceStatus.ERROR, message: `执行异常: ${msg}` };
|
|
119
127
|
}
|
|
120
128
|
}
|