claw-subagent-service 0.0.94 → 0.0.96

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.
@@ -22,10 +22,24 @@ MAX_WAIT=300 # 最长等待5分钟
22
22
  PORT="18789"
23
23
 
24
24
  # 检测是否在 Docker 环境(无 systemd)
25
+ # 注意:某些 Docker 镜像安装了 systemctl 命令但无法使用
26
+ # 所以同时检查 systemd 是否实际运行
25
27
  is_docker() {
28
+ # 方法1: 检查 systemctl 是否可用
26
29
  if ! command -v systemctl &>/dev/null; then
27
30
  return 0 # 无 systemctl,认为是 Docker
28
31
  fi
32
+
33
+ # 方法2: 即使安装了 systemctl,检查 systemd 是否实际运行
34
+ if [ ! -d "/run/systemd/system" ] && [ ! -d "/sys/fs/cgroup/systemd" ]; then
35
+ return 0 # systemd 未运行,认为是 Docker
36
+ fi
37
+
38
+ # 方法3: 尝试执行 systemctl status,如果失败则认为是 Docker
39
+ if ! systemctl status &>/dev/null; then
40
+ return 0 # systemctl 无法使用,认为是 Docker
41
+ fi
42
+
29
43
  return 1
30
44
  }
31
45
 
@@ -112,6 +126,7 @@ get_openclaw_pid() {
112
126
  }
113
127
 
114
128
  # 检查端口是否监听
129
+ # 注意:只检查端口,不检查进程。进程存在不等于端口在监听。
115
130
  check_port() {
116
131
  local port=$1
117
132
  if command -v ss &>/dev/null; then
@@ -126,11 +141,9 @@ check_port() {
126
141
  elif command -v fuser &>/dev/null; then
127
142
  fuser $port/tcp 2>/dev/null | grep -q '[0-9]'
128
143
  return $?
129
- else
130
- # 降级:直接检查进程
131
- [ -n "$(get_openclaw_pid)" ]
132
- return $?
133
144
  fi
145
+ # 如果所有工具都不可用,无法准确检查端口,保守返回 1(端口未监听)
146
+ return 1
134
147
  }
135
148
 
136
149
  # 等待端口启动
@@ -22,10 +22,24 @@ MAX_WAIT=300 # 最长等待5分钟
22
22
  PORT="18789"
23
23
 
24
24
  # 检测是否在 Docker 环境(无 systemd)
25
+ # 注意:某些 Docker 镜像安装了 systemctl 命令但无法使用
26
+ # 所以同时检查 systemd 是否实际运行
25
27
  is_docker() {
28
+ # 方法1: 检查 systemctl 是否可用
26
29
  if ! command -v systemctl &>/dev/null; then
27
30
  return 0 # 无 systemctl,认为是 Docker
28
31
  fi
32
+
33
+ # 方法2: 即使安装了 systemctl,检查 systemd 是否实际运行
34
+ if [ ! -d "/run/systemd/system" ] && [ ! -d "/sys/fs/cgroup/systemd" ]; then
35
+ return 0 # systemd 未运行,认为是 Docker
36
+ fi
37
+
38
+ # 方法3: 尝试执行 systemctl status,如果失败则认为是 Docker
39
+ if ! systemctl status &>/dev/null; then
40
+ return 0 # systemctl 无法使用,认为是 Docker
41
+ fi
42
+
29
43
  return 1
30
44
  }
31
45
 
@@ -112,6 +126,7 @@ get_openclaw_pid() {
112
126
  }
113
127
 
114
128
  # 检查端口是否监听
129
+ # 注意:只检查端口,不检查进程。进程存在不等于端口在监听。
115
130
  check_port() {
116
131
  local port=$1
117
132
  if command -v ss &>/dev/null; then
@@ -126,11 +141,9 @@ check_port() {
126
141
  elif command -v fuser &>/dev/null; then
127
142
  fuser $port/tcp 2>/dev/null | grep -q '[0-9]'
128
143
  return $?
129
- else
130
- # 降级:直接检查进程
131
- [ -n "$(get_openclaw_pid)" ]
132
- return $?
133
144
  fi
145
+ # 如果所有工具都不可用,无法准确检查端口,保守返回 1(端口未监听)
146
+ return 1
134
147
  }
135
148
 
136
149
  # 等待端口启动
@@ -36,10 +36,24 @@ SERVICE_NAME="openclaw-gateway.service"
36
36
  PORT="18789"
37
37
 
38
38
  # 检测是否在 Docker 环境(无 systemd)
39
+ # 注意:某些 Docker 镜像安装了 systemctl 命令但无法使用
40
+ # 所以同时检查 systemd 是否实际运行
39
41
  is_docker() {
42
+ # 方法1: 检查 systemctl 是否可用
40
43
  if ! command -v systemctl &>/dev/null; then
41
44
  return 0 # 无 systemctl,认为是 Docker
42
45
  fi
46
+
47
+ # 方法2: 即使安装了 systemctl,检查 systemd 是否实际运行
48
+ if [ ! -d "/run/systemd/system" ] && [ ! -d "/sys/fs/cgroup/systemd" ]; then
49
+ return 0 # systemd 未运行,认为是 Docker
50
+ fi
51
+
52
+ # 方法3: 尝试执行 systemctl status,如果失败则认为是 Docker
53
+ if ! systemctl status &>/dev/null; then
54
+ return 0 # systemctl 无法使用,认为是 Docker
55
+ fi
56
+
43
57
  return 1
44
58
  }
45
59
 
@@ -126,6 +140,7 @@ get_openclaw_pid() {
126
140
  }
127
141
 
128
142
  # 检查端口是否监听
143
+ # 注意:只检查端口,不检查进程。进程存在不等于端口在监听。
129
144
  check_port() {
130
145
  local port=$1
131
146
  if command -v ss &>/dev/null; then
@@ -140,11 +155,9 @@ check_port() {
140
155
  elif command -v fuser &>/dev/null; then
141
156
  fuser $port/tcp 2>/dev/null | grep -q '[0-9]'
142
157
  return $?
143
- else
144
- # 降级:直接检查进程
145
- [ -n "$(get_openclaw_pid)" ]
146
- return $?
147
158
  fi
159
+ # 如果所有工具都不可用,无法准确检查端口,保守返回 1(端口未监听)
160
+ return 1
148
161
  }
149
162
 
150
163
  # Docker 模式:查看状态
@@ -30,10 +30,25 @@ log_error() {
30
30
  SERVICE_NAME="openclaw-gateway.service"
31
31
 
32
32
  # 检测是否在 Docker 环境(无 systemd)
33
+ # 注意:某些 Docker 镜像安装了 systemctl 命令但无法使用
34
+ # 所以同时检查 systemd 是否实际运行
33
35
  is_docker() {
36
+ # 方法1: 检查 systemctl 是否可用
34
37
  if ! command -v systemctl &>/dev/null; then
35
38
  return 0 # 无 systemctl,认为是 Docker
36
39
  fi
40
+
41
+ # 方法2: 即使安装了 systemctl,检查 systemd 是否实际运行
42
+ # 在 Docker 中,/run/systemd/system 通常不存在
43
+ if [ ! -d "/run/systemd/system" ] && [ ! -d "/sys/fs/cgroup/systemd" ]; then
44
+ return 0 # systemd 未运行,认为是 Docker
45
+ fi
46
+
47
+ # 方法3: 尝试执行 systemctl status,如果失败则认为是 Docker
48
+ if ! systemctl status &>/dev/null; then
49
+ return 0 # systemctl 无法使用,认为是 Docker
50
+ fi
51
+
37
52
  return 1
38
53
  }
39
54
 
@@ -41,6 +56,7 @@ is_docker() {
41
56
  PORT="18789"
42
57
 
43
58
  # 检查端口是否监听
59
+ # 注意:只检查端口,不检查进程。进程存在不等于端口在监听。
44
60
  check_port() {
45
61
  local port=$1
46
62
  if command -v ss &>/dev/null; then
@@ -55,11 +71,9 @@ check_port() {
55
71
  elif command -v fuser &>/dev/null; then
56
72
  fuser $port/tcp 2>/dev/null | grep -q '[0-9]'
57
73
  return $?
58
- else
59
- # 最后降级:直接检查进程
60
- [ -n "$(get_openclaw_pid)" ]
61
- return $?
62
74
  fi
75
+ # 如果所有工具都不可用,无法准确检查端口,保守返回 1(端口未监听)
76
+ return 1
63
77
  }
64
78
 
65
79
  # 获取 openclaw 进程 PID
@@ -192,15 +206,17 @@ stop_docker() {
192
206
 
193
207
  log_info "发现 OpenClaw 进程: $all_pids"
194
208
 
195
- # 停止所有 openclaw 进程:先发送 SIGTERM(优雅停止)
196
- log_info "正在停止 OpenClaw 服务(发送 SIGTERM)..."
209
+ # 直接发送 SIGKILL(强制停止),避免 SIGTERM 被忽略
210
+ log_info "正在强制停止 OpenClaw 服务(SIGKILL)..."
197
211
  for p in $all_pids; do
198
- kill "$p" &>/dev/null || true
212
+ kill -9 "$p" 2>/dev/null || true
199
213
  done
214
+ # 额外使用 pkill 确保所有相关进程都被停止
215
+ pkill -9 -f "openclaw" 2>/dev/null || true
200
216
 
201
- # 等待服务完全停止(最多 10 秒)
217
+ # 等待进程退出(最多 3 秒)
202
218
  local elapsed=0
203
- while [ $elapsed -lt 10 ]; do
219
+ while [ $elapsed -lt 3 ]; do
204
220
  # 检查是否还有 openclaw 进程
205
221
  local remaining_pids=""
206
222
  if command -v pgrep &>/dev/null; then
@@ -211,8 +227,8 @@ stop_docker() {
211
227
  remaining_pids=$(ps aux | grep -v grep | grep "openclaw" | awk '{print $2}' | tr '\n' ' ')
212
228
  fi
213
229
 
214
- if [ -z "$remaining_pids" ] && ! check_port "$PORT"; then
215
- log_info "OpenClaw 服务停止成功!(所有进程已退出,端口已关闭)"
230
+ if [ -z "$remaining_pids" ]; then
231
+ log_info "OpenClaw 服务已停止。(所有进程已退出)"
216
232
  log_info "服务已成功停止。"
217
233
  log_info "Success"
218
234
  exit 0
@@ -221,36 +237,13 @@ stop_docker() {
221
237
  elapsed=$((elapsed + 1))
222
238
  done
223
239
 
224
- # 如果还在运行,强制停止(SIGKILL)
225
- log_warn "服务未在 10 秒内停止,正在强制停止..."
226
- for p in $all_pids; do
227
- kill -9 "$p" &>/dev/null || true
228
- done
229
- pkill -9 -f "openclaw" &>/dev/null || true
230
-
231
- # 等待进程消失(最多 5 秒)
232
- elapsed=0
233
- while [ $elapsed -lt 5 ]; do
234
- local remaining_pids=""
235
- if command -v pgrep &>/dev/null; then
236
- remaining_pids=$(pgrep -f "openclaw" | tr '\n' ' ')
237
- elif command -v pidof &>/dev/null; then
238
- remaining_pids=$(pidof openclaw)
239
- else
240
- remaining_pids=$(ps aux | grep -v grep | grep "openclaw" | awk '{print $2}' | tr '\n' ' ')
241
- fi
242
-
243
- if [ -z "$remaining_pids" ] && ! check_port "$PORT"; then
244
- log_info "OpenClaw 服务已强制停止。"
245
- log_info "服务已成功停止。"
246
- log_info "Success"
247
- exit 0
248
- fi
249
- sleep 1
250
- elapsed=$((elapsed + 1))
251
- done
240
+ # 如果进程仍在,再次强制停止
241
+ log_warn "进程仍在运行,再次强制停止..."
242
+ pkill -9 -f "openclaw" 2>/dev/null || true
243
+ killall -9 openclaw 2>/dev/null || true
252
244
 
253
- # 最终验证
245
+ # 最终检查
246
+ sleep 2
254
247
  local remaining_pids=""
255
248
  if command -v pgrep &>/dev/null; then
256
249
  remaining_pids=$(pgrep -f "openclaw" | tr '\n' ' ')
@@ -260,16 +253,13 @@ stop_docker() {
260
253
  remaining_pids=$(ps aux | grep -v grep | grep "openclaw" | awk '{print $2}' | tr '\n' ' ')
261
254
  fi
262
255
 
263
- if [ -z "$remaining_pids" ] && ! check_port "$PORT"; then
256
+ if [ -z "$remaining_pids" ]; then
264
257
  log_info "OpenClaw 服务已停止。"
265
258
  log_info "服务已成功停止。"
266
259
  log_info "Success"
267
260
  exit 0
268
- elif [ -n "$remaining_pids" ]; then
269
- log_error "OpenClaw 服务停止失败!进程仍然存在: $remaining_pids"
270
- exit 1
271
261
  else
272
- log_error "OpenClaw 服务停止失败!端口 $PORT 仍在监听。"
262
+ log_error "OpenClaw 服务停止失败!进程仍然存在: $remaining_pids"
273
263
  exit 1
274
264
  fi
275
265
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claw-subagent-service",
3
- "version": "0.0.94",
3
+ "version": "0.0.96",
4
4
  "description": "虾说智能助手",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -136,33 +136,29 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
136
136
  }
137
137
 
138
138
  if (command === OpenClawCommandEnum.STOP) {
139
- // 等待 3 秒后验证端口
140
- await new Promise(resolve => setTimeout(resolve, 3000));
141
- const portStatus = await getOpenClawStatus(18789);
142
- console.log(`[OpenClawControl] 停止后端口状态: ${portStatus}`);
139
+ // 停止命令验证:多次检查端口,处理看门狗自动重启的情况
140
+ console.log(`[OpenClawControl] 开始验证停止结果...`);
141
+
142
+ let portStatus = 1;
143
+ let checkCount = 0;
144
+ const maxChecks = 5; // 最多检查 5 次
145
+
146
+ while (checkCount < maxChecks && portStatus === 1) {
147
+ await new Promise(resolve => setTimeout(resolve, 3000)); // 每次等待 3 秒
148
+ portStatus = await getOpenClawStatus(18789);
149
+ console.log(`[OpenClawControl] 停止验证第 ${checkCount + 1} 次检查,端口状态: ${portStatus}`);
150
+ checkCount++;
151
+ }
143
152
 
144
153
  if (portStatus === 1) {
145
- // 端口仍在监听,但检查脚本是否报告已停止
146
- if (outputUpper.includes('SUCCESS') || outputUpper.includes('STOPPED')) {
147
- console.warn(`[OpenClawControl] 警告: 端口仍在监听,但脚本报告成功。可能是僵尸进程或服务未正确停止。`);
148
- // 仍然返回成功,但附带警告信息
149
- return {
150
- status: result.status,
151
- message: result.message + ' (警告: 端口仍在监听)'
152
- };
153
- }
154
+ console.error(`[OpenClawControl] 停止失败: 经过 ${maxChecks} 次检查,端口 18789 仍在监听。服务可能被看门狗自动重启。`);
154
155
  return {
155
156
  status: OpenClawServiceStatus.ERROR,
156
- message: '停止失败: 服务仍在运行'
157
- };
158
- } else if (portStatus === 2) {
159
- // 进程存在但端口未监听,可能服务正在停止中
160
- console.warn(`[OpenClawControl] 警告: openclaw 进程仍存在但端口已关闭。`);
161
- return {
162
- status: result.status,
163
- message: result.message + ' (警告: 进程仍存在)'
157
+ message: '停止失败: 服务仍在运行(可能被自动重启)'
164
158
  };
165
159
  }
160
+
161
+ console.log(`[OpenClawControl] 停止验证通过: 端口已关闭`);
166
162
  } else if (command === OpenClawCommandEnum.START || command === OpenClawCommandEnum.RESTART) {
167
163
  // 等待服务启动
168
164
  const maxWait = command === OpenClawCommandEnum.START ? 30 : 60;
@@ -314,9 +314,12 @@ class ScriptExecutor {
314
314
  if (upper.includes(kw.toUpperCase())) return true;
315
315
  }
316
316
 
317
- // 对于 START 命令,不提前返回,让脚本完整执行
318
- // 因为 start.bat 有等待循环,需要完整输出才能判断状态
319
- if (command === OpenClawCommandEnum.START) {
317
+ // 对于 START/STOP/RESTART 命令,不提前返回
318
+ // 让脚本完整执行到 exit,由 exit code 判断成功失败
319
+ // 提前返回可能导致 kill 命令未执行完成
320
+ if (command === OpenClawCommandEnum.START ||
321
+ command === OpenClawCommandEnum.STOP ||
322
+ command === OpenClawCommandEnum.RESTART) {
320
323
  return false;
321
324
  }
322
325