@@ -248,28 +248,38 @@ adminApi.post('/gateway/restart', async (c) => {
248248 // Find and kill the existing gateway process
249249 const existingProcess = await findExistingGatewayProcess ( sandbox ) ;
250250
251+ // Kill via the Process API first
252+ if ( existingProcess ) {
253+ console . log ( '[Restart] Killing via Process API:' , existingProcess . id ) ;
254+ try {
255+ await existingProcess . kill ( ) ;
256+ } catch {
257+ // Ignore
258+ }
259+ }
260+
251261 // Force kill the gateway via exec — more reliable than Process.kill()
252262 // because start-openclaw.sh execs into "openclaw" which forks
253263 // "openclaw-gateway". Process.kill() only kills the tracked shell PID,
254264 // but the forked child keeps port 18789. (Credit: dalexeenko #261)
255265 //
256- // The actual process names are "openclaw" and "openclaw-gateway" (hyphenated) .
266+ // Use multiple strategies since we don't know what tools are available .
257267 try {
258- await sandbox . exec (
259- 'kill -9 $(pgrep -x "openclaw-gateway" 2>/dev/null) $(pgrep -x "openclaw" 2>/dev/null) 2>/dev/null; true' ,
268+ const killResult = await sandbox . exec (
269+ [
270+ // Strategy 1: pgrep by exact name (most precise)
271+ 'kill -9 $(pgrep -x "openclaw-gateway" 2>/dev/null) $(pgrep -x "openclaw" 2>/dev/null) 2>/dev/null' ,
272+ // Strategy 2: pkill by pattern (broader match)
273+ 'pkill -9 -f "openclaw" 2>/dev/null' ,
274+ // Strategy 3: find by port (most reliable but needs ss/fuser)
275+ 'kill -9 $(ss -tlnp sport = :18789 2>/dev/null | grep -oP "pid=\\K[0-9]+") 2>/dev/null' ,
276+ // Always succeed
277+ 'true' ,
278+ ] . join ( '; ' ) ,
260279 ) ;
261- } catch {
262- // Process may not exist or pgrep not available
263- }
264-
265- // Also kill via the Process API for completeness
266- if ( existingProcess ) {
267- console . log ( 'Also killing via Process API:' , existingProcess . id ) ;
268- try {
269- await existingProcess . kill ( ) ;
270- } catch {
271- // Ignore
272- }
280+ console . log ( '[Restart] Kill result:' , killResult . stdout ?. trim ( ) , killResult . stderr ?. trim ( ) ) ;
281+ } catch ( e ) {
282+ console . error ( '[Restart] Kill exec failed:' , e ) ;
273283 }
274284
275285 // Clean up lock files that prevent restart
@@ -281,13 +291,11 @@ adminApi.post('/gateway/restart', async (c) => {
281291 // Ignore
282292 }
283293
284- // Wait for process to fully die and verify port is free
285- await new Promise ( ( r ) => setTimeout ( r , 2000 ) ) ;
294+ // Wait for process to fully die and verify
295+ await new Promise ( ( r ) => setTimeout ( r , 3000 ) ) ;
286296 try {
287- const check = await sandbox . exec (
288- 'pgrep -x "openclaw-gateway" && echo "STILL ALIVE" || echo "dead"' ,
289- ) ;
290- console . log ( '[Restart] Process check after kill:' , check . stdout ?. trim ( ) ) ;
297+ const check = await sandbox . exec ( 'ps aux | grep -v grep | grep openclaw || echo "ALL DEAD"' ) ;
298+ console . log ( '[Restart] Surviving processes:' , check . stdout ?. trim ( ) ) ;
291299 } catch {
292300 // Ignore
293301 }
0 commit comments