fix: harden dev stack process detection

This commit is contained in:
afei A
2026-03-27 23:57:47 +08:00
parent 98c6b741d6
commit 40bf9de8d7
2 changed files with 126 additions and 2 deletions

View File

@@ -181,6 +181,61 @@ function isPidRunning(pid) {
}
}
function readProcessCommand(pid) {
if (!pid) {
return null;
}
const result = spawnSync("ps", ["-p", String(pid), "-o", "command="], {
encoding: "utf8",
});
if (result.status !== 0) {
return null;
}
const command = result.stdout.trim();
return command.length > 0 ? command : null;
}
export function getServiceCommandMatchers(service) {
switch (service.key) {
case "temporal":
return ["temporal", "server", "start-dev"];
case "backend-api":
return ["uvicorn", "app.main:app"];
case "backend-worker":
return ["app.workers.runner"];
case "frontend":
return ["next", "dev", "127.0.0.1", "3000"];
default:
return service.command.map((part) => path.basename(part));
}
}
export function isServiceProcessMatch(service, processCommand) {
if (!processCommand) {
return false;
}
const normalizedCommand = processCommand.toLowerCase();
return getServiceCommandMatchers(service).every((matcher) =>
normalizedCommand.includes(matcher.toLowerCase()),
);
}
export function isServiceHealthy(service, { pid, processCommand, portOpen }) {
if (!pid || !isServiceProcessMatch(service, processCommand)) {
return false;
}
if (service.port) {
return portOpen;
}
return true;
}
function removePidFile(pidFilePath) {
if (fs.existsSync(pidFilePath)) {
fs.unlinkSync(pidFilePath);
@@ -309,6 +364,12 @@ async function stopService(config, service) {
return false;
}
const processCommand = readProcessCommand(pid);
if (!isServiceProcessMatch(service, processCommand)) {
removePidFile(pidFilePath);
return false;
}
process.kill(-pid, "SIGTERM");
for (let index = 0; index < 20; index += 1) {
if (!isPidRunning(pid)) {
@@ -430,10 +491,21 @@ async function printStatus() {
const pidFilePath = getServicePidFile(config, service.key);
const logFilePath = getServiceLogFile(config, service.key);
const pid = readPid(pidFilePath);
const running = pid ? isPidRunning(pid) : false;
const processCommand =
pid && isPidRunning(pid) ? readProcessCommand(pid) : null;
const portOpen = service.port ? await isLocalPortBusy(service.port) : false;
const running = isServiceHealthy(service, {
pid,
processCommand,
portOpen,
});
if (!running && pid) {
removePidFile(pidFilePath);
}
const displayPid = running ? pid : null;
const portText = service.port ? ` port=${service.port}` : "";
const logText = fs.existsSync(logFilePath) ? ` log=${logFilePath}` : "";
console.log(`${service.key}: ${running ? "running" : "stopped"} pid=${pid ?? "-"}${portText}${logText}`);
console.log(`${service.key}: ${running ? "running" : "stopped"} pid=${displayPid ?? "-"}${portText}${logText}`);
}
}