You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
54 lines
1.7 KiB
54 lines
1.7 KiB
import { readFileSync, existsSync, unlinkSync } from "node:fs";
|
|
import { execSync } from "node:child_process";
|
|
import path from "node:path";
|
|
|
|
const ROOT = path.resolve(import.meta.dirname, "..");
|
|
const PID_FILE = path.join(ROOT, ".e2e-server-pid");
|
|
const MOCK_LLM_PORT = Number(process.env.MOCK_LLM_PORT) || 3600;
|
|
const PREVIEW_PORT = Number(process.env.NITRO_PORT) || 3400;
|
|
|
|
/**
|
|
* 杀掉占用指定端口的进程,确保即使 setup 崩溃也能清理遗留进程。
|
|
*/
|
|
function killPortOccupants(port: number) {
|
|
try {
|
|
execSync(`fuser -k ${port}/tcp 2>/dev/null || true`, { stdio: "pipe" });
|
|
} catch {
|
|
try {
|
|
const out = execSync(`lsof -t -i :${port} 2>/dev/null || true`, {
|
|
stdio: "pipe",
|
|
}).toString().trim();
|
|
if (out) {
|
|
for (const pid of out.split("\n")) {
|
|
try { process.kill(Number(pid), "SIGKILL"); } catch { /* 已退出 */ }
|
|
}
|
|
}
|
|
} catch { /* 忽略 */ }
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
// 1. 通过 PID 文件优雅停止 preview server
|
|
if (existsSync(PID_FILE)) {
|
|
const pid = parseInt(readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
if (pid) {
|
|
try {
|
|
process.kill(pid, "SIGTERM");
|
|
console.log(`[global-teardown] Stopped preview server (PID: ${pid})`);
|
|
} catch {
|
|
// 进程可能已退出
|
|
}
|
|
}
|
|
unlinkSync(PID_FILE);
|
|
}
|
|
|
|
// 2. 兜底清理:杀掉占用端口的残留进程(mock LLM + preview server)
|
|
// 防止 setup 崩溃后 mock LLM 进程遗留导致下次 EADDRINUSE
|
|
console.log(`[global-teardown] Cleaning up ports: ${MOCK_LLM_PORT}, ${PREVIEW_PORT}`);
|
|
killPortOccupants(MOCK_LLM_PORT);
|
|
killPortOccupants(PREVIEW_PORT);
|
|
|
|
console.log("[global-teardown] Done");
|
|
}
|
|
|
|
export default main;
|
|
|