42 lines
1.1 KiB
JavaScript
42 lines
1.1 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Free PORT (default 3010) so npm run dev can bind after orphaned node --watch processes.
|
|
*/
|
|
const { execSync } = require('child_process');
|
|
|
|
const port = String(process.env.PORT || 3010).trim();
|
|
|
|
function pidsListening() {
|
|
try {
|
|
const out = execSync(`lsof -tiTCP:${port} -sTCP:LISTEN`, { encoding: 'utf8' }).trim();
|
|
if (!out) return [];
|
|
return [...new Set(out.split(/\s+/).filter(Boolean))];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
const pids = pidsListening();
|
|
if (!pids.length) {
|
|
console.log(`[free-port] :${port} already free`);
|
|
process.exit(0);
|
|
}
|
|
|
|
for (const pid of pids) {
|
|
try {
|
|
process.kill(Number(pid), 'SIGKILL');
|
|
console.log(`[free-port] killed pid ${pid} on :${port}`);
|
|
} catch (err) {
|
|
console.warn(`[free-port] could not kill ${pid}:`, err.message);
|
|
}
|
|
}
|
|
|
|
// brief wait for OS to release the socket
|
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 300);
|
|
const left = pidsListening();
|
|
if (left.length) {
|
|
console.error(`[free-port] still in use by: ${left.join(', ')}`);
|
|
process.exit(1);
|
|
}
|
|
console.log(`[free-port] :${port} is free`);
|