claw-subagent-service 0.0.90 → 0.0.91
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/package.json
CHANGED
|
@@ -128,7 +128,7 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
|
|
|
128
128
|
// 等待 3 秒后验证端口
|
|
129
129
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
130
130
|
const portStatus = await getOpenClawStatus(18789);
|
|
131
|
-
console.log(`[OpenClawControl] 停止后端口状态: ${portStatus
|
|
131
|
+
console.log(`[OpenClawControl] 停止后端口状态: ${portStatus}`);
|
|
132
132
|
|
|
133
133
|
if (portStatus === 1) {
|
|
134
134
|
// 端口仍在监听,但检查脚本是否报告已停止
|
|
@@ -144,6 +144,13 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
|
|
|
144
144
|
status: OpenClawServiceStatus.ERROR,
|
|
145
145
|
message: '停止失败: 服务仍在运行'
|
|
146
146
|
};
|
|
147
|
+
} else if (portStatus === 2) {
|
|
148
|
+
// 进程存在但端口未监听,可能服务正在停止中
|
|
149
|
+
console.warn(`[OpenClawControl] 警告: openclaw 进程仍存在但端口已关闭。`);
|
|
150
|
+
return {
|
|
151
|
+
status: result.status,
|
|
152
|
+
message: result.message + ' (警告: 进程仍存在)'
|
|
153
|
+
};
|
|
147
154
|
}
|
|
148
155
|
} else if (command === OpenClawCommandEnum.START || command === OpenClawCommandEnum.RESTART) {
|
|
149
156
|
// 等待服务启动
|
|
@@ -154,14 +161,14 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
|
|
|
154
161
|
while (attempts < maxWait) {
|
|
155
162
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
156
163
|
portStatus = await getOpenClawStatus(18789);
|
|
157
|
-
if (portStatus === 1) break;
|
|
164
|
+
if (portStatus === 1 || portStatus === 2) break; // 端口监听或进程存在都算成功
|
|
158
165
|
attempts++;
|
|
159
166
|
}
|
|
160
167
|
|
|
161
|
-
console.log(`[OpenClawControl] ${getCommandName(command)}后端口状态: ${portStatus
|
|
168
|
+
console.log(`[OpenClawControl] ${getCommandName(command)}后端口状态: ${portStatus}`);
|
|
162
169
|
|
|
163
170
|
if (portStatus === 0) {
|
|
164
|
-
//
|
|
171
|
+
// 端口未监听且进程不存在,但检查脚本是否报告成功
|
|
165
172
|
if (outputUpper.includes('SUCCESS') || outputUpper.includes('ALREADY RUNNING')) {
|
|
166
173
|
console.warn(`[OpenClawControl] 警告: 端口检查失败,但脚本报告成功。服务可能绑定到其他网络接口。`);
|
|
167
174
|
// 信任脚本结果,但添加警告
|
|
@@ -174,6 +181,13 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
|
|
|
174
181
|
status: OpenClawServiceStatus.ERROR,
|
|
175
182
|
message: `${getCommandName(command)}失败: 服务未运行`
|
|
176
183
|
};
|
|
184
|
+
} else if (portStatus === 2) {
|
|
185
|
+
// 进程存在但端口未监听,服务可能在启动中或绑定到其他地址
|
|
186
|
+
console.warn(`[OpenClawControl] 警告: openclaw 进程存在但端口 ${portStatus} 未监听。`);
|
|
187
|
+
return {
|
|
188
|
+
status: result.status === OpenClawServiceStatus.START_SUCCESS ? result.status : OpenClawServiceStatus.START_SUCCESS,
|
|
189
|
+
message: result.message + ' (进程已启动,端口检查可能不准确)'
|
|
190
|
+
};
|
|
177
191
|
}
|
|
178
192
|
}
|
|
179
193
|
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
const net = require('net');
|
|
2
2
|
const os = require('os');
|
|
3
|
+
const { execSync } = require('child_process');
|
|
3
4
|
|
|
4
5
|
function checkPortListening(port, host = '127.0.0.1') {
|
|
5
6
|
return new Promise((resolve) => {
|
|
6
7
|
const sock = new net.Socket();
|
|
7
|
-
sock.setTimeout(
|
|
8
|
+
sock.setTimeout(5000);
|
|
9
|
+
|
|
10
|
+
console.log(`[PortChecker] 尝试连接 ${host}:${port}`);
|
|
11
|
+
|
|
8
12
|
sock.once('connect', () => {
|
|
13
|
+
console.log(`[PortChecker] 成功连接到 ${host}:${port}`);
|
|
9
14
|
sock.destroy();
|
|
10
15
|
resolve(true);
|
|
11
16
|
});
|
|
12
|
-
|
|
17
|
+
|
|
18
|
+
sock.once('error', (err) => {
|
|
19
|
+
console.log(`[PortChecker] 连接 ${host}:${port} 失败: ${err.code} - ${err.message}`);
|
|
13
20
|
sock.destroy();
|
|
14
21
|
resolve(false);
|
|
15
22
|
});
|
|
23
|
+
|
|
16
24
|
sock.once('timeout', () => {
|
|
25
|
+
console.log(`[PortChecker] 连接 ${host}:${port} 超时`);
|
|
17
26
|
sock.destroy();
|
|
18
27
|
resolve(false);
|
|
19
28
|
});
|
|
29
|
+
|
|
20
30
|
sock.connect(port, host);
|
|
21
31
|
});
|
|
22
32
|
}
|
|
@@ -51,9 +61,98 @@ async function checkPortOnAllInterfaces(port) {
|
|
|
51
61
|
return false;
|
|
52
62
|
}
|
|
53
63
|
|
|
64
|
+
/**
|
|
65
|
+
* 通过系统命令检查端口是否监听(备选方法)
|
|
66
|
+
* 当 net.Socket 连接失败时使用
|
|
67
|
+
*/
|
|
68
|
+
function checkPortViaSystemCommand(port) {
|
|
69
|
+
try {
|
|
70
|
+
// 按优先级尝试多种工具
|
|
71
|
+
const commands = [
|
|
72
|
+
`ss -tlnp 2>/dev/null | grep -q ":${port} " && echo "found"`,
|
|
73
|
+
`netstat -tlnp 2>/dev/null | grep -q ":${port} " && echo "found"`,
|
|
74
|
+
`lsof -i :${port} 2>/dev/null | grep -q LISTEN && echo "found"`,
|
|
75
|
+
`fuser ${port}/tcp 2>/dev/null | grep -q '[0-9]' && echo "found"`
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
for (const cmd of commands) {
|
|
79
|
+
try {
|
|
80
|
+
const result = execSync(cmd, { encoding: 'utf8', timeout: 5000 }).trim();
|
|
81
|
+
if (result === 'found') {
|
|
82
|
+
console.log(`[PortChecker] 系统命令检测到端口 ${port} 正在监听`);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
} catch (e) {
|
|
86
|
+
// 命令失败,尝试下一个
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.error(`[PortChecker] 系统命令检查端口失败: ${e.message}`);
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 检查 openclaw 进程是否存在
|
|
97
|
+
*/
|
|
98
|
+
function checkProcessExists() {
|
|
99
|
+
try {
|
|
100
|
+
// 尝试多种方法检查进程
|
|
101
|
+
const commands = [
|
|
102
|
+
'ps aux | grep -v grep | grep openclaw',
|
|
103
|
+
'pgrep -f openclaw',
|
|
104
|
+
'pidof openclaw'
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
for (const cmd of commands) {
|
|
108
|
+
try {
|
|
109
|
+
const output = execSync(cmd, {
|
|
110
|
+
encoding: 'utf8',
|
|
111
|
+
timeout: 5000
|
|
112
|
+
}).trim();
|
|
113
|
+
|
|
114
|
+
if (output) {
|
|
115
|
+
console.log(`[PortChecker] 检测到 openclaw 进程存在 (通过: ${cmd.split(' ')[0]})`);
|
|
116
|
+
console.log(`[PortChecker] 进程信息: ${output.split('\n')[0]}`);
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
} catch (e) {
|
|
120
|
+
// 命令失败,尝试下一个
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log(`[PortChecker] 未检测到 openclaw 进程`);
|
|
125
|
+
} catch (e) {
|
|
126
|
+
console.error(`[PortChecker] 进程检查失败: ${e.message}`);
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
54
131
|
async function getOpenClawStatus(port = 18789) {
|
|
132
|
+
// 方法1: 通过 net.Socket 检查端口
|
|
55
133
|
const isListening = await checkPortOnAllInterfaces(port);
|
|
56
|
-
|
|
134
|
+
if (isListening) {
|
|
135
|
+
console.log(`[PortChecker] 端口 ${port} 检测为运行中(net.Socket)`);
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 方法2: 通过系统命令检查端口
|
|
140
|
+
const isListeningViaCmd = checkPortViaSystemCommand(port);
|
|
141
|
+
if (isListeningViaCmd) {
|
|
142
|
+
console.log(`[PortChecker] 端口 ${port} 检测为运行中(系统命令)`);
|
|
143
|
+
return 1;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 方法3: 检查进程是否存在(备选)
|
|
147
|
+
const processExists = checkProcessExists();
|
|
148
|
+
if (processExists) {
|
|
149
|
+
console.warn(`[PortChecker] 警告: openclaw 进程存在,但端口 ${port} 未监听。可能绑定到其他端口或地址。`);
|
|
150
|
+
// 进程存在但端口未监听,返回特殊状态 2
|
|
151
|
+
return 2;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
console.log(`[PortChecker] 端口 ${port} 检测为未运行`);
|
|
155
|
+
return 0;
|
|
57
156
|
}
|
|
58
157
|
|
|
59
158
|
module.exports = {
|
|
@@ -326,9 +326,20 @@ class RongyunMessageHandler {
|
|
|
326
326
|
// 获取 OpenClaw 运行状态(检查端口 18789)
|
|
327
327
|
const openClawStatus = await getOpenClawStatus();
|
|
328
328
|
|
|
329
|
-
//
|
|
329
|
+
// 构建状态数据
|
|
330
|
+
// openClawStatus: 1=端口监听正常, 2=进程存在但端口未监听, 0=未运行
|
|
331
|
+
let statusMessage;
|
|
332
|
+
if (openClawStatus === 1) {
|
|
333
|
+
statusMessage = '运行中';
|
|
334
|
+
} else if (openClawStatus === 2) {
|
|
335
|
+
statusMessage = '运行中(端口异常)';
|
|
336
|
+
} else {
|
|
337
|
+
statusMessage = '未运行';
|
|
338
|
+
}
|
|
339
|
+
|
|
330
340
|
const statusData = {
|
|
331
|
-
open_claw_status: openClawStatus, // 1=运行中, 0=未运行
|
|
341
|
+
open_claw_status: openClawStatus, // 1=运行中, 2=进程存在但端口未监听, 0=未运行
|
|
342
|
+
status_message: statusMessage,
|
|
332
343
|
mac_address: getMacAddress(),
|
|
333
344
|
version: '0.0.20',
|
|
334
345
|
timestamp: Date.now(),
|