@jait/gateway 0.1.500 → 0.1.501
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/bin/jait.mjs +148 -14
- package/package.json +1 -1
package/bin/jait.mjs
CHANGED
|
@@ -368,29 +368,163 @@ async function cmdStart(cliFlags) {
|
|
|
368
368
|
console.log("");
|
|
369
369
|
}
|
|
370
370
|
|
|
371
|
-
function cmdStop() {
|
|
371
|
+
async function cmdStop() {
|
|
372
372
|
printBanner();
|
|
373
|
+
|
|
374
|
+
const port = process.env.PORT || flags.port || "8000";
|
|
375
|
+
|
|
376
|
+
// Case 1: Process tracked via PID file
|
|
373
377
|
const tracked = getTrackedProcess();
|
|
374
|
-
if (
|
|
375
|
-
|
|
378
|
+
if (tracked) {
|
|
379
|
+
const { pid, pidPath } = tracked;
|
|
380
|
+
try {
|
|
381
|
+
if (platform() === "win32") {
|
|
382
|
+
execSync(`taskkill /PID ${pid} /T /F`, { stdio: "ignore" });
|
|
383
|
+
} else {
|
|
384
|
+
process.kill(Number(pid), "SIGTERM");
|
|
385
|
+
}
|
|
386
|
+
console.log(` Sent stop signal to PID ${pid}.`);
|
|
387
|
+
} catch (err) {
|
|
388
|
+
console.error(` Failed to stop process ${pid}: ${err.message}`);
|
|
389
|
+
}
|
|
390
|
+
cleanupPidFile(pidPath);
|
|
376
391
|
console.log("");
|
|
377
|
-
|
|
392
|
+
return;
|
|
378
393
|
}
|
|
379
394
|
|
|
380
|
-
|
|
395
|
+
// Case 2: systemd unit is active
|
|
396
|
+
if (platform() === "linux") {
|
|
397
|
+
let unitActive = false;
|
|
398
|
+
try {
|
|
399
|
+
const status = runSilent(`systemctl --user is-active ${SERVICE_NAME} 2>/dev/null`);
|
|
400
|
+
if (status.trim() === "active") {
|
|
401
|
+
console.log(` No PID file found. Stopping via systemd...`);
|
|
402
|
+
try {
|
|
403
|
+
run(`systemctl --user stop ${SERVICE_NAME}`, { silent: true });
|
|
404
|
+
console.log(` ${SERVICE_NAME} stopped.`);
|
|
405
|
+
console.log("");
|
|
406
|
+
return;
|
|
407
|
+
} catch (err) {
|
|
408
|
+
console.error(` Failed to stop via systemd: ${err.message}`);
|
|
409
|
+
}
|
|
410
|
+
unitActive = true;
|
|
411
|
+
}
|
|
412
|
+
} catch {}
|
|
413
|
+
|
|
414
|
+
if (!unitActive) {
|
|
415
|
+
// Case 3: check if port is actually answering /health — kill that process
|
|
416
|
+
const health = await healthCheck(port);
|
|
417
|
+
if (health) {
|
|
418
|
+
console.log(` No PID file found, but gateway is healthy on port ${port}.`);
|
|
419
|
+
|
|
420
|
+
// Find the PID listening on the port
|
|
421
|
+
let targetPids = [];
|
|
422
|
+
try {
|
|
423
|
+
const lsofOut = runSilent(
|
|
424
|
+
`lsof -ti:${port} 2>/dev/null`
|
|
425
|
+
);
|
|
426
|
+
targetPids = lsofOut
|
|
427
|
+
? lsofOut.split("\n").filter(Boolean).map(Number)
|
|
428
|
+
: [];
|
|
429
|
+
} catch {}
|
|
430
|
+
|
|
431
|
+
// Also try ss/fuser as fallback
|
|
432
|
+
if (targetPids.length === 0) {
|
|
433
|
+
try {
|
|
434
|
+
const fuserOut = runSilent(
|
|
435
|
+
`fuser ${port}/tcp 2>/dev/null`
|
|
436
|
+
);
|
|
437
|
+
targetPids = fuserOut
|
|
438
|
+
? fuserOut.split(/\s+/).map(Number)
|
|
439
|
+
: [];
|
|
440
|
+
} catch {}
|
|
441
|
+
}
|
|
381
442
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
443
|
+
let stopped = false;
|
|
444
|
+
for (const pid of targetPids) {
|
|
445
|
+
const exePath = "/proc/" + pid + "/exe";
|
|
446
|
+
try {
|
|
447
|
+
if (!existsSync(exePath)) continue;
|
|
448
|
+
const exeTarget = readFileSync(exePath, "utf8");
|
|
449
|
+
if (exeTarget.includes("node") || exeTarget.includes("jait")) {
|
|
450
|
+
try {
|
|
451
|
+
process.kill(pid, "SIGTERM");
|
|
452
|
+
console.log(` Sent stop signal to PID ${pid}.`);
|
|
453
|
+
stopped = true;
|
|
454
|
+
} catch (err) {
|
|
455
|
+
// already dead
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
} catch {}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (!stopped) {
|
|
462
|
+
// Last resort: kill all processes on the port that are owned by this user
|
|
463
|
+
for (const pid of targetPids) {
|
|
464
|
+
try {
|
|
465
|
+
process.kill(pid, "SIGTERM");
|
|
466
|
+
console.log(` Sent stop signal to PID ${pid}.`);
|
|
467
|
+
stopped = true;
|
|
468
|
+
} catch {}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (!stopped) {
|
|
473
|
+
console.log(` Could not find process to stop. Try 'sudo lsof -i :${port}' and kill manually.`);
|
|
474
|
+
} else {
|
|
475
|
+
// Clean up stale PID file if one exists (from a prior crash)
|
|
476
|
+
for (const p of [PID_PATH, LEGACY_PID_PATH]) {
|
|
477
|
+
if (existsSync(p)) cleanupPidFile(p);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
console.log("");
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Nothing found: no PID file, no systemd unit, port not in use
|
|
486
|
+
const reachable = await isPortReachable(port);
|
|
487
|
+
if (reachable) {
|
|
488
|
+
console.log(` Port ${port} is in use, but health check timed out.`);
|
|
489
|
+
console.log(` Another process may be listening. Run 'lsof -i :${port}' to inspect.`);
|
|
490
|
+
} else {
|
|
491
|
+
console.log(" Jait is not running (no PID file found).");
|
|
492
|
+
}
|
|
493
|
+
console.log("");
|
|
494
|
+
return;
|
|
387
495
|
}
|
|
388
|
-
|
|
389
|
-
} catch (err) {
|
|
390
|
-
console.error(` Failed to stop process ${pid}: ${err.message}`);
|
|
496
|
+
return;
|
|
391
497
|
}
|
|
392
498
|
|
|
393
|
-
|
|
499
|
+
// Non-Linux: port check fallback
|
|
500
|
+
const reachable = await isPortReachable(port);
|
|
501
|
+
if (reachable) {
|
|
502
|
+
const health = await healthCheck(port);
|
|
503
|
+
if (health) {
|
|
504
|
+
console.log(` No PID file found, but gateway is healthy on port ${port}.`);
|
|
505
|
+
let targetPids = [];
|
|
506
|
+
try {
|
|
507
|
+
targetPids = runSilent(
|
|
508
|
+
platform() === "darwin"
|
|
509
|
+
? `lsof -ti:${port} 2>/dev/null`
|
|
510
|
+
: `netstat -tlnp | grep :${port} | awk '{print $NF}' | cut -d/ -f1 | uniq'`
|
|
511
|
+
).split("\n").filter(Boolean).map(Number);
|
|
512
|
+
} catch {}
|
|
513
|
+
|
|
514
|
+
for (const pid of targetPids) {
|
|
515
|
+
try {
|
|
516
|
+
process.kill(pid, "SIGTERM");
|
|
517
|
+
console.log(` Sent stop signal to PID ${pid}.`);
|
|
518
|
+
} catch {}
|
|
519
|
+
}
|
|
520
|
+
} else {
|
|
521
|
+
console.log(` Port ${port} is in use but not a Jait health endpoint.`);
|
|
522
|
+
}
|
|
523
|
+
} else {
|
|
524
|
+
console.log(" Jait is not running (no PID file found).");
|
|
525
|
+
console.log("");
|
|
526
|
+
process.exit(1);
|
|
527
|
+
}
|
|
394
528
|
console.log("");
|
|
395
529
|
}
|
|
396
530
|
|