nox-openclaw-hunter 1.0.0 → 1.0.1
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/LICENSE +1 -1
- package/README.md +5 -12
- package/dist/banner.d.ts +6 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/banner.js +31 -0
- package/dist/banner.js.map +1 -0
- package/dist/branding.d.ts +4 -4
- package/dist/branding.d.ts.map +1 -1
- package/dist/branding.js +26 -10
- package/dist/branding.js.map +1 -1
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +800 -58
- package/dist/commands/export.js.map +1 -1
- package/dist/detector/cli-binary.d.ts +7 -3
- package/dist/detector/cli-binary.d.ts.map +1 -1
- package/dist/detector/cli-binary.js +31 -22
- package/dist/detector/cli-binary.js.map +1 -1
- package/dist/detector/detection-config.d.ts.map +1 -1
- package/dist/detector/detection-config.js +3 -0
- package/dist/detector/detection-config.js.map +1 -1
- package/dist/detector/docker.js +1 -1
- package/dist/detector/docker.js.map +1 -1
- package/dist/detector/process.js +1 -1
- package/dist/detector/process.js.map +1 -1
- package/dist/isolator/lockdown.d.ts.map +1 -1
- package/dist/isolator/lockdown.js +11 -0
- package/dist/isolator/lockdown.js.map +1 -1
- package/dist/mdm/templates/detect.sh.d.ts.map +1 -1
- package/dist/mdm/templates/detect.sh.js +5 -1
- package/dist/mdm/templates/detect.sh.js.map +1 -1
- package/dist/mdm/templates/enforce.sh.d.ts.map +1 -1
- package/dist/mdm/templates/enforce.sh.js +5 -1
- package/dist/mdm/templates/enforce.sh.js.map +1 -1
- package/dist/platform/darwin.d.ts.map +1 -1
- package/dist/platform/darwin.js +15 -2
- package/dist/platform/darwin.js.map +1 -1
- package/dist/platform/linux.d.ts.map +1 -1
- package/dist/platform/linux.js +9 -1
- package/dist/platform/linux.js.map +1 -1
- package/dist/platform/windows.d.ts.map +1 -1
- package/dist/platform/windows.js +8 -5
- package/dist/platform/windows.js.map +1 -1
- package/package.json +5 -5
package/dist/commands/export.js
CHANGED
|
@@ -47,61 +47,353 @@ send_webhook() {
|
|
|
47
47
|
# Generated by nox-openclaw-detector
|
|
48
48
|
# https://nox.security
|
|
49
49
|
|
|
50
|
-
set -
|
|
50
|
+
set -eo pipefail
|
|
51
|
+
|
|
52
|
+
# Set defaults for environment variables that may be unset when running as root
|
|
53
|
+
HOME="\${HOME:-/root}"
|
|
54
|
+
USER="\${USER:-root}"
|
|
51
55
|
|
|
52
56
|
OPENCLAW_FOUND=0
|
|
53
57
|
DETAILS=""
|
|
54
58
|
${webhookSection}
|
|
59
|
+
|
|
60
|
+
# Logging function
|
|
61
|
+
log() {
|
|
62
|
+
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Get all user home directories
|
|
66
|
+
get_all_user_homes() {
|
|
67
|
+
local homes=()
|
|
68
|
+
|
|
69
|
+
# macOS users
|
|
70
|
+
if [[ -d "/Users" ]]; then
|
|
71
|
+
for user_dir in /Users/*; do
|
|
72
|
+
if [[ -d "$user_dir" && "$user_dir" != "/Users/Shared" && "$user_dir" != "/Users/Guest" ]]; then
|
|
73
|
+
homes+=("$user_dir")
|
|
74
|
+
fi
|
|
75
|
+
done
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# Linux users
|
|
79
|
+
if [[ -d "/home" ]]; then
|
|
80
|
+
for user_dir in /home/*; do
|
|
81
|
+
if [[ -d "$user_dir" ]]; then
|
|
82
|
+
homes+=("$user_dir")
|
|
83
|
+
fi
|
|
84
|
+
done
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Root home
|
|
88
|
+
if [[ -d "/root" ]]; then
|
|
89
|
+
homes+=("/root")
|
|
90
|
+
fi
|
|
91
|
+
if [[ -d "/var/root" ]]; then
|
|
92
|
+
homes+=("/var/root")
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
echo "\${homes[@]}"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
log "=========================================="
|
|
99
|
+
log "Nox OpenClaw Hunter - Detection Scan"
|
|
100
|
+
log "=========================================="
|
|
101
|
+
log "Hostname: $(hostname)"
|
|
102
|
+
log "Platform: $(uname -s) $(uname -m)"
|
|
103
|
+
log "User: $USER"
|
|
104
|
+
log "Date: $(date)"
|
|
105
|
+
log "=========================================="
|
|
106
|
+
log ""
|
|
107
|
+
|
|
55
108
|
# Check if nox CLI is installed
|
|
109
|
+
log "Checking for nox CLI..."
|
|
56
110
|
if command -v nox &>/dev/null; then
|
|
111
|
+
log " [INFO] nox CLI found, using for detection"
|
|
57
112
|
if nox scan --quiet --json > /tmp/nox_scan_result.json 2>/dev/null; then
|
|
58
113
|
SUMMARY=$(cat /tmp/nox_scan_result.json | grep -o '"summary":"[^"]*"' | cut -d'"' -f4 || echo "")
|
|
59
114
|
if [[ "$SUMMARY" != "not-installed" ]]; then
|
|
60
115
|
OPENCLAW_FOUND=1
|
|
61
116
|
DETAILS="Detected via nox CLI: $SUMMARY"
|
|
117
|
+
log " [DETECTED] $DETAILS"
|
|
118
|
+
else
|
|
119
|
+
log " [CLEAN] No OpenClaw detected via nox CLI"
|
|
62
120
|
fi
|
|
63
121
|
rm -f /tmp/nox_scan_result.json
|
|
64
122
|
fi
|
|
65
123
|
${webhookUrl ? 'send_webhook "$([[ $OPENCLAW_FOUND -eq 1 ]] && echo "detected" || echo "clean")" "$DETAILS"' : ''}
|
|
124
|
+
|
|
125
|
+
log ""
|
|
126
|
+
log "=========================================="
|
|
127
|
+
if [[ $OPENCLAW_FOUND -eq 1 ]]; then
|
|
128
|
+
log "RESULT: OpenClaw DETECTED"
|
|
129
|
+
else
|
|
130
|
+
log "RESULT: System CLEAN"
|
|
131
|
+
fi
|
|
132
|
+
log "=========================================="
|
|
66
133
|
exit $OPENCLAW_FOUND
|
|
67
134
|
fi
|
|
68
135
|
|
|
136
|
+
log " [INFO] nox CLI not found, using fallback detection"
|
|
137
|
+
log ""
|
|
138
|
+
|
|
69
139
|
# Fallback: direct detection
|
|
140
|
+
# Scanning for: openclaw, clawbot, clawdbot, moltbot
|
|
70
141
|
|
|
71
|
-
# Check CLI
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
142
|
+
# Check CLI binaries (system-wide and per-user)
|
|
143
|
+
log "Checking for CLI binaries (all locations)..."
|
|
144
|
+
CLI_FOUND=0
|
|
145
|
+
|
|
146
|
+
# System-wide locations
|
|
147
|
+
for cli_name in openclaw clawbot clawdbot moltbot; do
|
|
148
|
+
for bin_dir in /usr/local/bin /opt/homebrew/bin /usr/bin; do
|
|
149
|
+
cli_path="$bin_dir/$cli_name"
|
|
150
|
+
if [[ -f "$cli_path" ]]; then
|
|
151
|
+
OPENCLAW_FOUND=1
|
|
152
|
+
CLI_FOUND=1
|
|
153
|
+
DETAILS="$DETAILS; CLI found at $cli_path"
|
|
154
|
+
log " [DETECTED] CLI binary found at $cli_path"
|
|
155
|
+
fi
|
|
156
|
+
done
|
|
78
157
|
done
|
|
79
158
|
|
|
80
|
-
#
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
159
|
+
# Per-user locations
|
|
160
|
+
for user_home in $(get_all_user_homes); do
|
|
161
|
+
for cli_name in openclaw clawbot clawdbot moltbot; do
|
|
162
|
+
for bin_dir in "$user_home/bin" "$user_home/.local/bin"; do
|
|
163
|
+
cli_path="$bin_dir/$cli_name"
|
|
164
|
+
if [[ -f "$cli_path" ]]; then
|
|
165
|
+
OPENCLAW_FOUND=1
|
|
166
|
+
CLI_FOUND=1
|
|
167
|
+
DETAILS="$DETAILS; CLI found at $cli_path"
|
|
168
|
+
log " [DETECTED] CLI binary found at $cli_path"
|
|
169
|
+
fi
|
|
170
|
+
done
|
|
171
|
+
done
|
|
172
|
+
done
|
|
173
|
+
|
|
174
|
+
if [[ $CLI_FOUND -eq 0 ]]; then
|
|
175
|
+
log " [CLEAN] No CLI binaries found"
|
|
84
176
|
fi
|
|
85
177
|
|
|
86
|
-
# Check
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
178
|
+
# Check config directories for ALL users
|
|
179
|
+
log ""
|
|
180
|
+
log "Checking for config directories (all users)..."
|
|
181
|
+
CONFIG_FOUND=0
|
|
182
|
+
for user_home in $(get_all_user_homes); do
|
|
183
|
+
for config_name in .openclaw .clawbot .clawdbot .moltbot; do
|
|
184
|
+
config_path="$user_home/$config_name"
|
|
185
|
+
if [[ -d "$config_path" ]]; then
|
|
186
|
+
OPENCLAW_FOUND=1
|
|
187
|
+
CONFIG_FOUND=1
|
|
188
|
+
DETAILS="$DETAILS; Config directory found at $config_path"
|
|
189
|
+
log " [DETECTED] Config directory found at $config_path"
|
|
190
|
+
fi
|
|
191
|
+
done
|
|
192
|
+
done
|
|
193
|
+
if [[ $CONFIG_FOUND -eq 0 ]]; then
|
|
194
|
+
log " [CLEAN] No config directories found"
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# Check macOS app bundles (system-wide and per-user)
|
|
198
|
+
log ""
|
|
199
|
+
log "Checking for macOS app bundles (all locations)..."
|
|
200
|
+
APP_FOUND=0
|
|
201
|
+
for app_name in OpenClaw.app ClawBot.app ClawdBot.app MoltBot.app; do
|
|
202
|
+
# System-wide Applications
|
|
203
|
+
app_path="/Applications/$app_name"
|
|
204
|
+
if [[ -d "$app_path" ]]; then
|
|
205
|
+
OPENCLAW_FOUND=1
|
|
206
|
+
APP_FOUND=1
|
|
207
|
+
DETAILS="$DETAILS; App bundle found at $app_path"
|
|
208
|
+
log " [DETECTED] App bundle found at $app_path"
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
# Per-user Applications folders
|
|
212
|
+
for user_home in $(get_all_user_homes); do
|
|
213
|
+
app_path="$user_home/Applications/$app_name"
|
|
214
|
+
if [[ -d "$app_path" ]]; then
|
|
215
|
+
OPENCLAW_FOUND=1
|
|
216
|
+
APP_FOUND=1
|
|
217
|
+
DETAILS="$DETAILS; App bundle found at $app_path"
|
|
218
|
+
log " [DETECTED] App bundle found at $app_path"
|
|
219
|
+
fi
|
|
220
|
+
done
|
|
221
|
+
done
|
|
222
|
+
if [[ $APP_FOUND -eq 0 ]]; then
|
|
223
|
+
log " [CLEAN] No app bundles found"
|
|
90
224
|
fi
|
|
91
225
|
|
|
92
226
|
# Check gateway port
|
|
227
|
+
log ""
|
|
228
|
+
log "Checking for gateway port 18789..."
|
|
93
229
|
if command -v nc &>/dev/null && nc -z localhost 18789 2>/dev/null; then
|
|
94
230
|
OPENCLAW_FOUND=1
|
|
95
231
|
DETAILS="$DETAILS; Gateway port 18789 listening"
|
|
232
|
+
log " [DETECTED] Gateway port 18789 is listening"
|
|
233
|
+
elif command -v lsof &>/dev/null && lsof -i :18789 -sTCP:LISTEN &>/dev/null; then
|
|
234
|
+
OPENCLAW_FOUND=1
|
|
235
|
+
DETAILS="$DETAILS; Gateway port 18789 listening"
|
|
236
|
+
log " [DETECTED] Gateway port 18789 is listening"
|
|
237
|
+
else
|
|
238
|
+
log " [CLEAN] Gateway port 18789 not listening"
|
|
96
239
|
fi
|
|
97
240
|
|
|
98
241
|
# Check running processes
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
242
|
+
log ""
|
|
243
|
+
log "Checking for running processes (openclaw, clawbot, clawdbot, moltbot)..."
|
|
244
|
+
PROC_FOUND=0
|
|
245
|
+
for proc_name in openclaw clawbot clawdbot moltbot; do
|
|
246
|
+
if pgrep -x "$proc_name" > /dev/null 2>&1; then
|
|
247
|
+
OPENCLAW_FOUND=1
|
|
248
|
+
PROC_FOUND=1
|
|
249
|
+
PIDS=$(pgrep -x "$proc_name" | tr '\\n' ' ')
|
|
250
|
+
DETAILS="$DETAILS; Process $proc_name running (PIDs: $PIDS)"
|
|
251
|
+
log " [DETECTED] $proc_name process running (PIDs: $PIDS)"
|
|
252
|
+
elif pgrep -f "$proc_name" > /dev/null 2>&1; then
|
|
253
|
+
OPENCLAW_FOUND=1
|
|
254
|
+
PROC_FOUND=1
|
|
255
|
+
PIDS=$(pgrep -f "$proc_name" | tr '\\n' ' ')
|
|
256
|
+
DETAILS="$DETAILS; Process $proc_name running (PIDs: $PIDS)"
|
|
257
|
+
log " [DETECTED] $proc_name-related process running (PIDs: $PIDS)"
|
|
258
|
+
fi
|
|
259
|
+
done
|
|
260
|
+
if [[ $PROC_FOUND -eq 0 ]]; then
|
|
261
|
+
log " [CLEAN] No matching processes running"
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
# Check launchd services (macOS) - all users
|
|
265
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
266
|
+
log ""
|
|
267
|
+
log "Checking for launchd services (all users)..."
|
|
268
|
+
LAUNCHD_FOUND=0
|
|
269
|
+
|
|
270
|
+
# System-wide LaunchAgents and LaunchDaemons
|
|
271
|
+
for plist_dir in /Library/LaunchAgents /Library/LaunchDaemons; do
|
|
272
|
+
if [[ -d "$plist_dir" ]]; then
|
|
273
|
+
for pattern in "bot.molt.*" "*openclaw*" "*clawbot*" "*clawdbot*" "*moltbot*"; do
|
|
274
|
+
for plist in "$plist_dir"/$pattern; do
|
|
275
|
+
if [[ -f "$plist" ]]; then
|
|
276
|
+
OPENCLAW_FOUND=1
|
|
277
|
+
LAUNCHD_FOUND=1
|
|
278
|
+
DETAILS="$DETAILS; LaunchAgent found: $plist"
|
|
279
|
+
log " [DETECTED] LaunchAgent/Daemon found: $plist"
|
|
280
|
+
fi
|
|
281
|
+
done
|
|
282
|
+
done
|
|
283
|
+
fi
|
|
284
|
+
done
|
|
285
|
+
|
|
286
|
+
# Per-user LaunchAgents
|
|
287
|
+
for user_home in $(get_all_user_homes); do
|
|
288
|
+
plist_dir="$user_home/Library/LaunchAgents"
|
|
289
|
+
if [[ -d "$plist_dir" ]]; then
|
|
290
|
+
for pattern in "bot.molt.*" "*openclaw*" "*clawbot*" "*clawdbot*" "*moltbot*"; do
|
|
291
|
+
for plist in "$plist_dir"/$pattern; do
|
|
292
|
+
if [[ -f "$plist" ]]; then
|
|
293
|
+
OPENCLAW_FOUND=1
|
|
294
|
+
LAUNCHD_FOUND=1
|
|
295
|
+
DETAILS="$DETAILS; LaunchAgent found: $plist"
|
|
296
|
+
log " [DETECTED] LaunchAgent/Daemon found: $plist"
|
|
297
|
+
fi
|
|
298
|
+
done
|
|
299
|
+
done
|
|
300
|
+
fi
|
|
301
|
+
done
|
|
302
|
+
|
|
303
|
+
if [[ $LAUNCHD_FOUND -eq 0 ]]; then
|
|
304
|
+
log " [CLEAN] No launchd services found"
|
|
305
|
+
fi
|
|
306
|
+
fi
|
|
307
|
+
|
|
308
|
+
# Check systemd services (Linux) - system and user level
|
|
309
|
+
if command -v systemctl &>/dev/null; then
|
|
310
|
+
log ""
|
|
311
|
+
log "Checking for systemd services (system and user level)..."
|
|
312
|
+
SYSTEMD_FOUND=0
|
|
313
|
+
|
|
314
|
+
# System-level services
|
|
315
|
+
for svc_name in openclaw clawbot clawdbot moltbot; do
|
|
316
|
+
if systemctl list-unit-files "$svc_name.service" &>/dev/null 2>&1; then
|
|
317
|
+
OPENCLAW_FOUND=1
|
|
318
|
+
SYSTEMD_FOUND=1
|
|
319
|
+
STATUS=$(systemctl is-active "$svc_name.service" 2>/dev/null || echo "inactive")
|
|
320
|
+
DETAILS="$DETAILS; Systemd service $svc_name found (status: $STATUS)"
|
|
321
|
+
log " [DETECTED] Systemd service $svc_name found (status: $STATUS)"
|
|
322
|
+
fi
|
|
323
|
+
|
|
324
|
+
# Check service file directly
|
|
325
|
+
for svc_path in /etc/systemd/system /usr/lib/systemd/system; do
|
|
326
|
+
if [[ -f "$svc_path/$svc_name.service" ]]; then
|
|
327
|
+
OPENCLAW_FOUND=1
|
|
328
|
+
SYSTEMD_FOUND=1
|
|
329
|
+
DETAILS="$DETAILS; Systemd service file found: $svc_path/$svc_name.service"
|
|
330
|
+
log " [DETECTED] Systemd service file found: $svc_path/$svc_name.service"
|
|
331
|
+
fi
|
|
332
|
+
done
|
|
333
|
+
done
|
|
334
|
+
|
|
335
|
+
# User-level systemd services
|
|
336
|
+
for user_home in $(get_all_user_homes); do
|
|
337
|
+
user_systemd="$user_home/.config/systemd/user"
|
|
338
|
+
if [[ -d "$user_systemd" ]]; then
|
|
339
|
+
for svc_name in openclaw clawbot clawdbot moltbot; do
|
|
340
|
+
if [[ -f "$user_systemd/$svc_name.service" ]]; then
|
|
341
|
+
OPENCLAW_FOUND=1
|
|
342
|
+
SYSTEMD_FOUND=1
|
|
343
|
+
DETAILS="$DETAILS; User systemd service found: $user_systemd/$svc_name.service"
|
|
344
|
+
log " [DETECTED] User systemd service found: $user_systemd/$svc_name.service"
|
|
345
|
+
fi
|
|
346
|
+
done
|
|
347
|
+
fi
|
|
348
|
+
done
|
|
349
|
+
|
|
350
|
+
if [[ $SYSTEMD_FOUND -eq 0 ]]; then
|
|
351
|
+
log " [CLEAN] No systemd services found"
|
|
352
|
+
fi
|
|
353
|
+
fi
|
|
354
|
+
|
|
355
|
+
# Check Docker
|
|
356
|
+
if command -v docker &>/dev/null; then
|
|
357
|
+
log ""
|
|
358
|
+
log "Checking for Docker artifacts..."
|
|
359
|
+
DOCKER_FOUND=0
|
|
360
|
+
for docker_name in openclaw clawbot clawdbot moltbot; do
|
|
361
|
+
CONTAINERS=$(docker ps -a --filter "name=$docker_name" --format "{{.Names}}" 2>/dev/null || true)
|
|
362
|
+
if [[ -n "$CONTAINERS" ]]; then
|
|
363
|
+
OPENCLAW_FOUND=1
|
|
364
|
+
DOCKER_FOUND=1
|
|
365
|
+
DETAILS="$DETAILS; Docker containers ($docker_name): $CONTAINERS"
|
|
366
|
+
log " [DETECTED] Docker containers found ($docker_name): $CONTAINERS"
|
|
367
|
+
fi
|
|
368
|
+
IMAGES=$(docker images --filter "reference=*$docker_name*" --format "{{.Repository}}:{{.Tag}}" 2>/dev/null || true)
|
|
369
|
+
if [[ -n "$IMAGES" ]]; then
|
|
370
|
+
OPENCLAW_FOUND=1
|
|
371
|
+
DOCKER_FOUND=1
|
|
372
|
+
DETAILS="$DETAILS; Docker images ($docker_name): $IMAGES"
|
|
373
|
+
log " [DETECTED] Docker images found ($docker_name): $IMAGES"
|
|
374
|
+
fi
|
|
375
|
+
done
|
|
376
|
+
if [[ $DOCKER_FOUND -eq 0 ]]; then
|
|
377
|
+
log " [CLEAN] No Docker artifacts found"
|
|
378
|
+
fi
|
|
102
379
|
fi
|
|
103
380
|
${webhookUrl ? '\nsend_webhook "$([[ $OPENCLAW_FOUND -eq 1 ]] && echo "detected" || echo "clean")" "$DETAILS"' : ''}
|
|
104
381
|
|
|
382
|
+
# Final summary
|
|
383
|
+
log ""
|
|
384
|
+
log "=========================================="
|
|
385
|
+
log "SCAN SUMMARY"
|
|
386
|
+
log "=========================================="
|
|
387
|
+
if [[ $OPENCLAW_FOUND -eq 1 ]]; then
|
|
388
|
+
log "STATUS: OpenClaw DETECTED"
|
|
389
|
+
log "DETAILS: $DETAILS"
|
|
390
|
+
log "EXIT CODE: 1"
|
|
391
|
+
else
|
|
392
|
+
log "STATUS: System CLEAN - No OpenClaw installation detected"
|
|
393
|
+
log "EXIT CODE: 0"
|
|
394
|
+
fi
|
|
395
|
+
log "=========================================="
|
|
396
|
+
|
|
105
397
|
exit $OPENCLAW_FOUND
|
|
106
398
|
`;
|
|
107
399
|
}
|
|
@@ -230,8 +522,13 @@ send_webhook() {
|
|
|
230
522
|
#
|
|
231
523
|
# WARNING: This script will remove OpenClaw installations!
|
|
232
524
|
# Run with sudo for full purge capabilities.
|
|
525
|
+
# Exit code is always 0 if the script runs to completion - check logs for details.
|
|
526
|
+
|
|
527
|
+
set -o pipefail
|
|
233
528
|
|
|
234
|
-
|
|
529
|
+
# Set defaults for environment variables that may be unset when running as root
|
|
530
|
+
HOME="\${HOME:-/root}"
|
|
531
|
+
USER="\${USER:-root}"
|
|
235
532
|
|
|
236
533
|
PURGE_RESULTS=""
|
|
237
534
|
${webhookSection}
|
|
@@ -240,68 +537,516 @@ log_action() {
|
|
|
240
537
|
PURGE_RESULTS="$PURGE_RESULTS; $1"
|
|
241
538
|
}
|
|
242
539
|
|
|
540
|
+
# Get all user home directories
|
|
541
|
+
get_all_user_homes() {
|
|
542
|
+
local homes=()
|
|
543
|
+
|
|
544
|
+
# macOS users
|
|
545
|
+
if [[ -d "/Users" ]]; then
|
|
546
|
+
for user_dir in /Users/*; do
|
|
547
|
+
if [[ -d "$user_dir" && "$user_dir" != "/Users/Shared" && "$user_dir" != "/Users/Guest" ]]; then
|
|
548
|
+
homes+=("$user_dir")
|
|
549
|
+
fi
|
|
550
|
+
done
|
|
551
|
+
fi
|
|
552
|
+
|
|
553
|
+
# Linux users
|
|
554
|
+
if [[ -d "/home" ]]; then
|
|
555
|
+
for user_dir in /home/*; do
|
|
556
|
+
if [[ -d "$user_dir" ]]; then
|
|
557
|
+
homes+=("$user_dir")
|
|
558
|
+
fi
|
|
559
|
+
done
|
|
560
|
+
fi
|
|
561
|
+
|
|
562
|
+
# Root home
|
|
563
|
+
if [[ -d "/root" ]]; then
|
|
564
|
+
homes+=("/root")
|
|
565
|
+
fi
|
|
566
|
+
if [[ -d "/var/root" ]]; then
|
|
567
|
+
homes+=("/var/root")
|
|
568
|
+
fi
|
|
569
|
+
|
|
570
|
+
echo "\${homes[@]}"
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
log_action "=========================================="
|
|
574
|
+
log_action "Nox OpenClaw Hunter - Purge (All Users)"
|
|
575
|
+
log_action "=========================================="
|
|
576
|
+
|
|
243
577
|
# Check if running as root
|
|
244
|
-
if [[
|
|
578
|
+
if [[ \${EUID:-$(id -u)} -ne 0 ]]; then
|
|
245
579
|
echo "Warning: Not running as root. Some actions may fail."
|
|
580
|
+
echo "For complete purge across all users, run with sudo."
|
|
246
581
|
fi
|
|
247
582
|
|
|
248
|
-
#
|
|
249
|
-
|
|
250
|
-
|
|
583
|
+
# STEP 1: Unload launchd services FIRST to prevent process respawning (macOS)
|
|
584
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
585
|
+
log_action "Unloading launchd services to prevent respawning..."
|
|
586
|
+
|
|
587
|
+
# System-wide LaunchAgents and LaunchDaemons
|
|
588
|
+
for plist_dir in /Library/LaunchAgents /Library/LaunchDaemons; do
|
|
589
|
+
for pattern in "bot.molt.*" "*openclaw*" "*clawbot*" "*clawdbot*" "*moltbot*"; do
|
|
590
|
+
for plist in "$plist_dir"/$pattern; do
|
|
591
|
+
if [[ -f "$plist" ]]; then
|
|
592
|
+
launchctl bootout system "$plist" 2>/dev/null || launchctl unload "$plist" 2>/dev/null || true
|
|
593
|
+
fi
|
|
594
|
+
done
|
|
595
|
+
done
|
|
596
|
+
done
|
|
597
|
+
|
|
598
|
+
# Per-user LaunchAgents - unload for all users
|
|
599
|
+
for user_home in $(get_all_user_homes); do
|
|
600
|
+
plist_dir="$user_home/Library/LaunchAgents"
|
|
601
|
+
username=$(basename "$user_home")
|
|
602
|
+
user_uid=$(id -u "$username" 2>/dev/null || echo "")
|
|
603
|
+
if [[ -d "$plist_dir" ]]; then
|
|
604
|
+
for pattern in "bot.molt.*" "*openclaw*" "*clawbot*" "*clawdbot*" "*moltbot*"; do
|
|
605
|
+
for plist in "$plist_dir"/$pattern; do
|
|
606
|
+
if [[ -f "$plist" ]]; then
|
|
607
|
+
if [[ -n "$user_uid" ]]; then
|
|
608
|
+
launchctl bootout "gui/$user_uid" "$plist" 2>/dev/null || true
|
|
609
|
+
launchctl bootout "user/$user_uid" "$plist" 2>/dev/null || true
|
|
610
|
+
fi
|
|
611
|
+
launchctl unload "$plist" 2>/dev/null || true
|
|
612
|
+
fi
|
|
613
|
+
done
|
|
614
|
+
done
|
|
615
|
+
fi
|
|
616
|
+
done
|
|
617
|
+
log_action "Launchd services unloaded"
|
|
618
|
+
fi
|
|
619
|
+
|
|
620
|
+
# STEP 1b: Stop systemd services FIRST to prevent respawning (Linux)
|
|
621
|
+
if command -v systemctl &>/dev/null; then
|
|
622
|
+
log_action "Stopping systemd services to prevent respawning..."
|
|
623
|
+
for svc_name in openclaw clawbot clawdbot moltbot; do
|
|
624
|
+
systemctl stop "$svc_name.service" 2>/dev/null || true
|
|
625
|
+
systemctl disable "$svc_name.service" 2>/dev/null || true
|
|
626
|
+
done
|
|
627
|
+
|
|
628
|
+
# User-level services
|
|
629
|
+
for user_home in $(get_all_user_homes); do
|
|
630
|
+
username=$(basename "$user_home")
|
|
631
|
+
for svc_name in openclaw clawbot clawdbot moltbot; do
|
|
632
|
+
sudo -u "$username" systemctl --user stop "$svc_name.service" 2>/dev/null || true
|
|
633
|
+
sudo -u "$username" systemctl --user disable "$svc_name.service" 2>/dev/null || true
|
|
634
|
+
done
|
|
635
|
+
done
|
|
636
|
+
log_action "Systemd services stopped"
|
|
637
|
+
fi
|
|
638
|
+
|
|
639
|
+
# STEP 2: Kill running processes
|
|
640
|
+
log_action "Killing processes (openclaw, clawbot, clawdbot, moltbot)..."
|
|
641
|
+
PROCS_KILLED=0
|
|
642
|
+
for proc_name in openclaw clawbot clawdbot moltbot; do
|
|
643
|
+
# Find PIDs first (exclude our own script)
|
|
644
|
+
PIDS=$(pgrep -x "$proc_name" 2>/dev/null || true)
|
|
645
|
+
if [[ -z "$PIDS" ]]; then
|
|
646
|
+
# Try matching command line if exact name match fails
|
|
647
|
+
PIDS=$(pgrep -f "/$proc_name\$" 2>/dev/null || true)
|
|
648
|
+
fi
|
|
649
|
+
|
|
650
|
+
if [[ -n "$PIDS" ]]; then
|
|
651
|
+
for pid in $PIDS; do
|
|
652
|
+
# Skip if it's our own process
|
|
653
|
+
if [[ "$pid" == "$$" ]]; then
|
|
654
|
+
continue
|
|
655
|
+
fi
|
|
656
|
+
kill -9 "$pid" 2>/dev/null && {
|
|
657
|
+
log_action " Killed $proc_name (PID: $pid)"
|
|
658
|
+
PROCS_KILLED=$((PROCS_KILLED + 1))
|
|
659
|
+
} || true
|
|
660
|
+
done
|
|
661
|
+
fi
|
|
662
|
+
|
|
663
|
+
# Also try pkill as backup
|
|
664
|
+
pkill -9 -x "$proc_name" 2>/dev/null || true
|
|
665
|
+
|
|
666
|
+
# On macOS, also try killall
|
|
667
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
668
|
+
killall -9 "$proc_name" 2>/dev/null || true
|
|
669
|
+
fi
|
|
670
|
+
done
|
|
671
|
+
|
|
672
|
+
# Wait briefly for processes to terminate
|
|
673
|
+
sleep 1
|
|
251
674
|
|
|
252
|
-
#
|
|
675
|
+
# Verify processes are gone
|
|
676
|
+
REMAINING=""
|
|
677
|
+
for proc_name in openclaw clawbot clawdbot moltbot; do
|
|
678
|
+
if pgrep -x "$proc_name" >/dev/null 2>&1; then
|
|
679
|
+
REMAINING="$REMAINING $proc_name"
|
|
680
|
+
fi
|
|
681
|
+
done
|
|
682
|
+
|
|
683
|
+
if [[ -n "$REMAINING" ]]; then
|
|
684
|
+
log_action "WARNING: Some processes may still be running:$REMAINING"
|
|
685
|
+
# Try one more aggressive kill
|
|
686
|
+
for proc_name in $REMAINING; do
|
|
687
|
+
pkill -9 -f "$proc_name" 2>/dev/null || true
|
|
688
|
+
done
|
|
689
|
+
sleep 1
|
|
690
|
+
|
|
691
|
+
# Final check
|
|
692
|
+
STILL_RUNNING=""
|
|
693
|
+
for proc_name in openclaw clawbot clawdbot moltbot; do
|
|
694
|
+
if pgrep -x "$proc_name" >/dev/null 2>&1; then
|
|
695
|
+
STILL_RUNNING="$STILL_RUNNING $proc_name($(pgrep -x "$proc_name" | tr '\\n' ' '))"
|
|
696
|
+
fi
|
|
697
|
+
done
|
|
698
|
+
|
|
699
|
+
if [[ -n "$STILL_RUNNING" ]]; then
|
|
700
|
+
log_action "ERROR: Failed to kill processes:$STILL_RUNNING - may require manual intervention"
|
|
701
|
+
else
|
|
702
|
+
log_action "Process kill completed (after retry)"
|
|
703
|
+
fi
|
|
704
|
+
else
|
|
705
|
+
if [[ $PROCS_KILLED -gt 0 ]]; then
|
|
706
|
+
log_action "Process kill completed ($PROCS_KILLED processes terminated)"
|
|
707
|
+
else
|
|
708
|
+
log_action "Process kill completed (no matching processes found)"
|
|
709
|
+
fi
|
|
710
|
+
fi
|
|
711
|
+
|
|
712
|
+
# Stop and disable launchd services (macOS) - ALL USERS
|
|
253
713
|
if [[ "$(uname)" == "Darwin" ]]; then
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
714
|
+
log_action "Removing launchd services (all users)..."
|
|
715
|
+
LAUNCHD_REMOVED=0
|
|
716
|
+
LAUNCHD_FAILED=0
|
|
717
|
+
|
|
718
|
+
# System-wide LaunchAgents and LaunchDaemons
|
|
719
|
+
for plist_dir in /Library/LaunchAgents /Library/LaunchDaemons; do
|
|
720
|
+
for pattern in "bot.molt.*" "*openclaw*" "*clawbot*" "*clawdbot*" "*moltbot*"; do
|
|
721
|
+
for plist in "$plist_dir"/$pattern; do
|
|
722
|
+
if [[ -f "$plist" ]]; then
|
|
723
|
+
launchctl unload "$plist" 2>/dev/null || true
|
|
724
|
+
rm -f "$plist" 2>/dev/null
|
|
725
|
+
if [[ -f "$plist" ]]; then
|
|
726
|
+
log_action " FAILED to remove launchd plist: $plist"
|
|
727
|
+
LAUNCHD_FAILED=$((LAUNCHD_FAILED + 1))
|
|
728
|
+
else
|
|
729
|
+
log_action " Removed launchd plist: $plist"
|
|
730
|
+
LAUNCHD_REMOVED=$((LAUNCHD_REMOVED + 1))
|
|
731
|
+
fi
|
|
732
|
+
fi
|
|
733
|
+
done
|
|
734
|
+
done
|
|
735
|
+
done
|
|
736
|
+
|
|
737
|
+
# Per-user LaunchAgents
|
|
738
|
+
for user_home in $(get_all_user_homes); do
|
|
739
|
+
plist_dir="$user_home/Library/LaunchAgents"
|
|
740
|
+
if [[ -d "$plist_dir" ]]; then
|
|
741
|
+
for pattern in "bot.molt.*" "*openclaw*" "*clawbot*" "*clawdbot*" "*moltbot*"; do
|
|
742
|
+
for plist in "$plist_dir"/$pattern; do
|
|
743
|
+
if [[ -f "$plist" ]]; then
|
|
744
|
+
launchctl unload "$plist" 2>/dev/null || true
|
|
745
|
+
rm -f "$plist" 2>/dev/null
|
|
746
|
+
if [[ -f "$plist" ]]; then
|
|
747
|
+
log_action " FAILED to remove launchd plist: $plist"
|
|
748
|
+
LAUNCHD_FAILED=$((LAUNCHD_FAILED + 1))
|
|
749
|
+
else
|
|
750
|
+
log_action " Removed launchd plist: $plist"
|
|
751
|
+
LAUNCHD_REMOVED=$((LAUNCHD_REMOVED + 1))
|
|
752
|
+
fi
|
|
753
|
+
fi
|
|
754
|
+
done
|
|
755
|
+
done
|
|
259
756
|
fi
|
|
260
757
|
done
|
|
758
|
+
|
|
759
|
+
if [[ $LAUNCHD_FAILED -gt 0 ]]; then
|
|
760
|
+
log_action "Launchd removal: $LAUNCHD_REMOVED removed, $LAUNCHD_FAILED failed"
|
|
761
|
+
elif [[ $LAUNCHD_REMOVED -gt 0 ]]; then
|
|
762
|
+
log_action "Launchd removal completed ($LAUNCHD_REMOVED services removed)"
|
|
763
|
+
else
|
|
764
|
+
log_action "Launchd removal completed (no launchd services found)"
|
|
765
|
+
fi
|
|
261
766
|
fi
|
|
262
767
|
|
|
263
|
-
# Stop and disable systemd
|
|
768
|
+
# Stop and disable systemd services (Linux) - system and user level
|
|
264
769
|
if command -v systemctl &>/dev/null; then
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
770
|
+
log_action "Removing systemd services (system and user level)..."
|
|
771
|
+
SYSTEMD_REMOVED=0
|
|
772
|
+
SYSTEMD_FAILED=0
|
|
773
|
+
|
|
774
|
+
# System-level services
|
|
775
|
+
for svc_name in openclaw clawbot clawdbot moltbot; do
|
|
776
|
+
systemctl stop "$svc_name.service" 2>/dev/null || true
|
|
777
|
+
systemctl disable "$svc_name.service" 2>/dev/null || true
|
|
778
|
+
|
|
779
|
+
for svc_path in "/etc/systemd/system/$svc_name.service" "/usr/lib/systemd/system/$svc_name.service"; do
|
|
780
|
+
if [[ -f "$svc_path" ]]; then
|
|
781
|
+
rm -f "$svc_path" 2>/dev/null
|
|
782
|
+
if [[ -f "$svc_path" ]]; then
|
|
783
|
+
log_action " FAILED to remove systemd service: $svc_path"
|
|
784
|
+
SYSTEMD_FAILED=$((SYSTEMD_FAILED + 1))
|
|
785
|
+
else
|
|
786
|
+
log_action " Removed systemd service: $svc_path"
|
|
787
|
+
SYSTEMD_REMOVED=$((SYSTEMD_REMOVED + 1))
|
|
788
|
+
fi
|
|
789
|
+
fi
|
|
790
|
+
done
|
|
791
|
+
done
|
|
792
|
+
|
|
793
|
+
# User-level systemd services
|
|
794
|
+
for user_home in $(get_all_user_homes); do
|
|
795
|
+
user_systemd="$user_home/.config/systemd/user"
|
|
796
|
+
if [[ -d "$user_systemd" ]]; then
|
|
797
|
+
for svc_name in openclaw clawbot clawdbot moltbot; do
|
|
798
|
+
svc_path="$user_systemd/$svc_name.service"
|
|
799
|
+
if [[ -f "$svc_path" ]]; then
|
|
800
|
+
rm -f "$svc_path" 2>/dev/null
|
|
801
|
+
if [[ -f "$svc_path" ]]; then
|
|
802
|
+
log_action " FAILED to remove user systemd service: $svc_path"
|
|
803
|
+
SYSTEMD_FAILED=$((SYSTEMD_FAILED + 1))
|
|
804
|
+
else
|
|
805
|
+
log_action " Removed user systemd service: $svc_path"
|
|
806
|
+
SYSTEMD_REMOVED=$((SYSTEMD_REMOVED + 1))
|
|
807
|
+
fi
|
|
808
|
+
fi
|
|
809
|
+
done
|
|
810
|
+
fi
|
|
811
|
+
done
|
|
812
|
+
|
|
268
813
|
systemctl daemon-reload 2>/dev/null || true
|
|
269
|
-
|
|
814
|
+
|
|
815
|
+
if [[ $SYSTEMD_FAILED -gt 0 ]]; then
|
|
816
|
+
log_action "Systemd removal: $SYSTEMD_REMOVED removed, $SYSTEMD_FAILED failed"
|
|
817
|
+
elif [[ $SYSTEMD_REMOVED -gt 0 ]]; then
|
|
818
|
+
log_action "Systemd removal completed ($SYSTEMD_REMOVED services removed)"
|
|
819
|
+
else
|
|
820
|
+
log_action "Systemd removal completed (no systemd services found)"
|
|
821
|
+
fi
|
|
270
822
|
fi
|
|
271
823
|
|
|
272
|
-
# Remove CLI
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
824
|
+
# Remove CLI binaries (system-wide and per-user)
|
|
825
|
+
log_action "Removing CLI binaries (all locations)..."
|
|
826
|
+
CLI_REMOVED=0
|
|
827
|
+
CLI_FAILED=0
|
|
828
|
+
|
|
829
|
+
# System-wide locations
|
|
830
|
+
for cli_name in openclaw clawbot clawdbot moltbot; do
|
|
831
|
+
for bin_dir in /usr/local/bin /opt/homebrew/bin /usr/bin; do
|
|
832
|
+
cli_path="$bin_dir/$cli_name"
|
|
833
|
+
if [[ -f "$cli_path" ]]; then
|
|
834
|
+
rm -f "$cli_path" 2>/dev/null
|
|
835
|
+
if [[ -f "$cli_path" ]]; then
|
|
836
|
+
log_action " FAILED to remove CLI: $cli_path (permission denied)"
|
|
837
|
+
CLI_FAILED=$((CLI_FAILED + 1))
|
|
838
|
+
else
|
|
839
|
+
log_action " Removed CLI: $cli_path"
|
|
840
|
+
CLI_REMOVED=$((CLI_REMOVED + 1))
|
|
841
|
+
fi
|
|
842
|
+
fi
|
|
843
|
+
done
|
|
278
844
|
done
|
|
279
845
|
|
|
280
|
-
#
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
846
|
+
# Per-user locations
|
|
847
|
+
for user_home in $(get_all_user_homes); do
|
|
848
|
+
for cli_name in openclaw clawbot clawdbot moltbot; do
|
|
849
|
+
for bin_dir in "$user_home/bin" "$user_home/.local/bin"; do
|
|
850
|
+
cli_path="$bin_dir/$cli_name"
|
|
851
|
+
if [[ -f "$cli_path" ]]; then
|
|
852
|
+
rm -f "$cli_path" 2>/dev/null
|
|
853
|
+
if [[ -f "$cli_path" ]]; then
|
|
854
|
+
log_action " FAILED to remove CLI: $cli_path (permission denied)"
|
|
855
|
+
CLI_FAILED=$((CLI_FAILED + 1))
|
|
856
|
+
else
|
|
857
|
+
log_action " Removed CLI: $cli_path"
|
|
858
|
+
CLI_REMOVED=$((CLI_REMOVED + 1))
|
|
859
|
+
fi
|
|
860
|
+
fi
|
|
861
|
+
done
|
|
862
|
+
done
|
|
863
|
+
done
|
|
864
|
+
|
|
865
|
+
if [[ $CLI_FAILED -gt 0 ]]; then
|
|
866
|
+
log_action "CLI removal: $CLI_REMOVED removed, $CLI_FAILED failed"
|
|
867
|
+
elif [[ $CLI_REMOVED -gt 0 ]]; then
|
|
868
|
+
log_action "CLI removal completed ($CLI_REMOVED binaries removed)"
|
|
869
|
+
else
|
|
870
|
+
log_action "CLI removal completed (no CLI binaries found)"
|
|
284
871
|
fi
|
|
285
872
|
|
|
286
|
-
# Remove
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
873
|
+
# Remove macOS app bundles (system-wide and per-user)
|
|
874
|
+
log_action "Removing app bundles (all locations)..."
|
|
875
|
+
APP_REMOVED=0
|
|
876
|
+
APP_FAILED=0
|
|
877
|
+
|
|
878
|
+
for app_name in OpenClaw.app ClawBot.app ClawdBot.app MoltBot.app; do
|
|
879
|
+
# System-wide Applications
|
|
880
|
+
if [[ -d "/Applications/$app_name" ]]; then
|
|
881
|
+
rm -rf "/Applications/$app_name" 2>/dev/null
|
|
882
|
+
if [[ -d "/Applications/$app_name" ]]; then
|
|
883
|
+
log_action " FAILED to remove app: /Applications/$app_name (permission denied or protected)"
|
|
884
|
+
APP_FAILED=$((APP_FAILED + 1))
|
|
885
|
+
else
|
|
886
|
+
log_action " Removed app bundle: /Applications/$app_name"
|
|
887
|
+
APP_REMOVED=$((APP_REMOVED + 1))
|
|
888
|
+
fi
|
|
291
889
|
fi
|
|
890
|
+
|
|
891
|
+
# Per-user Applications
|
|
892
|
+
for user_home in $(get_all_user_homes); do
|
|
893
|
+
if [[ -d "$user_home/Applications/$app_name" ]]; then
|
|
894
|
+
rm -rf "$user_home/Applications/$app_name" 2>/dev/null
|
|
895
|
+
if [[ -d "$user_home/Applications/$app_name" ]]; then
|
|
896
|
+
log_action " FAILED to remove app: $user_home/Applications/$app_name (permission denied)"
|
|
897
|
+
APP_FAILED=$((APP_FAILED + 1))
|
|
898
|
+
else
|
|
899
|
+
log_action " Removed app bundle: $user_home/Applications/$app_name"
|
|
900
|
+
APP_REMOVED=$((APP_REMOVED + 1))
|
|
901
|
+
fi
|
|
902
|
+
fi
|
|
903
|
+
done
|
|
904
|
+
done
|
|
905
|
+
|
|
906
|
+
if [[ $APP_FAILED -gt 0 ]]; then
|
|
907
|
+
log_action "App bundle removal: $APP_REMOVED removed, $APP_FAILED failed"
|
|
908
|
+
elif [[ $APP_REMOVED -gt 0 ]]; then
|
|
909
|
+
log_action "App bundle removal completed ($APP_REMOVED bundles removed)"
|
|
910
|
+
else
|
|
911
|
+
log_action "App bundle removal completed (no app bundles found)"
|
|
912
|
+
fi
|
|
913
|
+
|
|
914
|
+
# Remove config directories for ALL USERS
|
|
915
|
+
log_action "Removing config directories (all users)..."
|
|
916
|
+
CONFIG_REMOVED=0
|
|
917
|
+
CONFIG_FAILED=0
|
|
918
|
+
for user_home in $(get_all_user_homes); do
|
|
919
|
+
for config_name in .openclaw .clawbot .clawdbot .moltbot; do
|
|
920
|
+
config_path="$user_home/$config_name"
|
|
921
|
+
if [[ -d "$config_path" ]]; then
|
|
922
|
+
# On macOS: remove extended attributes and clear immutable flags
|
|
923
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
924
|
+
xattr -cr "$config_path" 2>/dev/null || true
|
|
925
|
+
chflags -R nouchg "$config_path" 2>/dev/null || true
|
|
926
|
+
fi
|
|
927
|
+
# On Linux: remove immutable attribute
|
|
928
|
+
if command -v chattr &>/dev/null; then
|
|
929
|
+
chattr -R -i "$config_path" 2>/dev/null || true
|
|
930
|
+
fi
|
|
931
|
+
|
|
932
|
+
# Remove all contents first, then the directory
|
|
933
|
+
find "$config_path" -type f -delete 2>/dev/null || true
|
|
934
|
+
find "$config_path" -type d -empty -delete 2>/dev/null || true
|
|
935
|
+
rm -rf "$config_path" 2>/dev/null || true
|
|
936
|
+
|
|
937
|
+
# If still exists, try moving to temp and deleting
|
|
938
|
+
if [[ -d "$config_path" ]]; then
|
|
939
|
+
temp_path="/tmp/.nox_purge_$$_$(basename "$config_path")"
|
|
940
|
+
mv "$config_path" "$temp_path" 2>/dev/null && rm -rf "$temp_path" 2>/dev/null || true
|
|
941
|
+
fi
|
|
942
|
+
|
|
943
|
+
# Verify removal
|
|
944
|
+
if [[ -d "$config_path" ]]; then
|
|
945
|
+
log_action " FAILED to remove config: $config_path (permission denied or protected)"
|
|
946
|
+
CONFIG_FAILED=$((CONFIG_FAILED + 1))
|
|
947
|
+
else
|
|
948
|
+
log_action " Removed config: $config_path"
|
|
949
|
+
CONFIG_REMOVED=$((CONFIG_REMOVED + 1))
|
|
950
|
+
fi
|
|
951
|
+
fi
|
|
952
|
+
done
|
|
292
953
|
done
|
|
954
|
+
if [[ $CONFIG_FAILED -gt 0 ]]; then
|
|
955
|
+
log_action "Config removal: $CONFIG_REMOVED removed, $CONFIG_FAILED failed"
|
|
956
|
+
elif [[ $CONFIG_REMOVED -gt 0 ]]; then
|
|
957
|
+
log_action "Config removal completed ($CONFIG_REMOVED directories removed)"
|
|
958
|
+
else
|
|
959
|
+
log_action "Config removal completed (no config directories found)"
|
|
960
|
+
fi
|
|
293
961
|
|
|
294
962
|
# Remove Docker containers and images
|
|
295
963
|
if command -v docker &>/dev/null; then
|
|
296
|
-
|
|
297
|
-
|
|
964
|
+
log_action "Cleaning Docker artifacts..."
|
|
965
|
+
for docker_name in openclaw clawbot clawdbot moltbot; do
|
|
966
|
+
docker ps -a --filter "name=$docker_name" --format "{{.ID}}" | xargs -r docker rm -f 2>/dev/null || true
|
|
967
|
+
docker images --filter "reference=*$docker_name*" --format "{{.ID}}" | xargs -r docker rmi -f 2>/dev/null || true
|
|
968
|
+
done
|
|
298
969
|
log_action "Cleaned Docker artifacts"
|
|
299
970
|
fi
|
|
300
971
|
|
|
972
|
+
# FINAL CLEANUP PASS - catch any respawned processes and recreated files
|
|
973
|
+
log_action "Running final cleanup pass..."
|
|
974
|
+
sleep 2
|
|
975
|
+
|
|
976
|
+
# Kill any respawned processes
|
|
977
|
+
RESPAWNED=0
|
|
978
|
+
for proc_name in openclaw clawbot clawdbot moltbot; do
|
|
979
|
+
if pgrep -x "$proc_name" >/dev/null 2>&1; then
|
|
980
|
+
pkill -9 -x "$proc_name" 2>/dev/null || true
|
|
981
|
+
killall -9 "$proc_name" 2>/dev/null || true
|
|
982
|
+
RESPAWNED=1
|
|
983
|
+
log_action " Killed respawned process: $proc_name"
|
|
984
|
+
fi
|
|
985
|
+
done
|
|
986
|
+
|
|
987
|
+
# Remove any recreated config directories (thorough removal)
|
|
988
|
+
for user_home in $(get_all_user_homes); do
|
|
989
|
+
for config_name in .openclaw .clawbot .clawdbot .moltbot; do
|
|
990
|
+
config_path="$user_home/$config_name"
|
|
991
|
+
if [[ -d "$config_path" ]]; then
|
|
992
|
+
# On macOS: remove extended attributes and clear immutable flags
|
|
993
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
994
|
+
xattr -cr "$config_path" 2>/dev/null || true
|
|
995
|
+
chflags -R nouchg "$config_path" 2>/dev/null || true
|
|
996
|
+
fi
|
|
997
|
+
# On Linux: remove immutable attribute
|
|
998
|
+
if command -v chattr &>/dev/null; then
|
|
999
|
+
chattr -R -i "$config_path" 2>/dev/null || true
|
|
1000
|
+
fi
|
|
1001
|
+
|
|
1002
|
+
# Remove all contents first, then the directory
|
|
1003
|
+
find "$config_path" -type f -delete 2>/dev/null || true
|
|
1004
|
+
find "$config_path" -type d -empty -delete 2>/dev/null || true
|
|
1005
|
+
rm -rf "$config_path" 2>/dev/null || true
|
|
1006
|
+
|
|
1007
|
+
# If still exists, try moving to temp and deleting
|
|
1008
|
+
if [[ -d "$config_path" ]]; then
|
|
1009
|
+
temp_path="/tmp/.nox_purge_$$_$(basename "$config_path")"
|
|
1010
|
+
mv "$config_path" "$temp_path" 2>/dev/null && rm -rf "$temp_path" 2>/dev/null || true
|
|
1011
|
+
fi
|
|
1012
|
+
|
|
1013
|
+
if [[ -d "$config_path" ]]; then
|
|
1014
|
+
log_action " FAILED: Config directory recreated and cannot be removed: $config_path"
|
|
1015
|
+
else
|
|
1016
|
+
log_action " Removed recreated config directory: $config_path"
|
|
1017
|
+
fi
|
|
1018
|
+
fi
|
|
1019
|
+
done
|
|
1020
|
+
done
|
|
1021
|
+
|
|
1022
|
+
# Final verification
|
|
1023
|
+
FINAL_PROCS=""
|
|
1024
|
+
FINAL_CONFIGS=""
|
|
1025
|
+
for proc_name in openclaw clawbot clawdbot moltbot; do
|
|
1026
|
+
if pgrep -x "$proc_name" >/dev/null 2>&1; then
|
|
1027
|
+
FINAL_PROCS="$FINAL_PROCS $proc_name"
|
|
1028
|
+
fi
|
|
1029
|
+
done
|
|
1030
|
+
for user_home in $(get_all_user_homes); do
|
|
1031
|
+
for config_name in .openclaw .clawbot .clawdbot .moltbot; do
|
|
1032
|
+
if [[ -d "$user_home/$config_name" ]]; then
|
|
1033
|
+
FINAL_CONFIGS="$FINAL_CONFIGS $user_home/$config_name"
|
|
1034
|
+
fi
|
|
1035
|
+
done
|
|
1036
|
+
done
|
|
1037
|
+
|
|
1038
|
+
if [[ -n "$FINAL_PROCS" || -n "$FINAL_CONFIGS" ]]; then
|
|
1039
|
+
log_action "WARNING: Some items could not be fully purged:"
|
|
1040
|
+
[[ -n "$FINAL_PROCS" ]] && log_action " Processes still running:$FINAL_PROCS"
|
|
1041
|
+
[[ -n "$FINAL_CONFIGS" ]] && log_action " Config directories still exist:$FINAL_CONFIGS"
|
|
1042
|
+
log_action "Manual intervention may be required"
|
|
1043
|
+
else
|
|
1044
|
+
log_action "Final cleanup pass completed - all items purged successfully"
|
|
1045
|
+
fi
|
|
1046
|
+
|
|
301
1047
|
log_action "Purge complete"
|
|
302
1048
|
${webhookUrl ? '\nsend_webhook "purged" "$PURGE_RESULTS"' : ''}
|
|
303
1049
|
|
|
304
|
-
echo "Purge complete. Results: $PURGE_RESULTS"
|
|
305
1050
|
exit 0
|
|
306
1051
|
`;
|
|
307
1052
|
}
|
|
@@ -401,11 +1146,8 @@ if (Get-Command docker -ErrorAction SilentlyContinue) {
|
|
|
401
1146
|
Log-Action "Cleaned Docker artifacts"
|
|
402
1147
|
}
|
|
403
1148
|
|
|
404
|
-
$ResultsString = $PurgeResults -join "; "
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
Write-Host ""
|
|
408
|
-
Write-Host "Purge complete. Results: $ResultsString"
|
|
1149
|
+
${webhookUrl ? '$ResultsString = $PurgeResults -join "; "\nSend-Webhook -Status "purged" -Details $ResultsString\n' : ''}
|
|
1150
|
+
Log-Action "Purge complete"
|
|
409
1151
|
exit 0
|
|
410
1152
|
`;
|
|
411
1153
|
}
|