snowballtools-base/scripts/kill-ports.js
2025-02-20 09:43:07 -08:00

109 lines
4.0 KiB
JavaScript
Executable File

#!/usr/bin/env node
const { exec } = require('child_process');
const { promisify } = require('util');
const chalk = require('chalk');
const execAsync = promisify(exec);
const ports = [3000, 3001, 8000];
async function killProcessOnPort(port) {
try {
console.log(chalk.blue(`🔍 Checking if port ${port} is in use...`));
if (process.platform === 'darwin' || process.platform === 'linux') {
// Try with lsof first
try {
const { stdout } = await execAsync(`lsof -i :${port} -t`);
if (stdout.trim()) {
console.log(chalk.yellow(`⚠️ Port ${port} is in use. Attempting to terminate processes...`));
const pids = stdout.trim().split('\n').filter(Boolean);
for (const pid of pids) {
try {
await execAsync(`kill -9 ${pid}`);
console.log(chalk.green(`✅ Terminated process ${pid} using port ${port}`));
} catch (error) {
console.error(chalk.red(`Failed to kill process ${pid}: ${error.message}`));
}
}
} else {
console.log(chalk.green(`✅ Port ${port} is available`));
}
} catch (lsofError) {
// Fallback to netstat if lsof fails
try {
const { stdout } = await execAsync(`netstat -anp 2>/dev/null | grep ${port} | grep LISTEN`);
if (stdout.trim()) {
console.log(chalk.yellow(`⚠️ Port ${port} is in use. Using netstat fallback...`));
// Extract PIDs with regex - this is more complex with netstat
const pidRegex = /\s(\d+)\/\w+\s*$/;
const matches = stdout.match(pidRegex);
if (matches && matches[1]) {
const pid = matches[1];
try {
await execAsync(`kill -9 ${pid}`);
console.log(chalk.green(`✅ Terminated process ${pid} using port ${port}`));
} catch (error) {
console.error(chalk.red(`Failed to kill process ${pid}: ${error.message}`));
}
} else {
console.log(chalk.yellow(`⚠️ Could not extract PID from netstat output`));
}
} else {
console.log(chalk.green(`✅ Port ${port} is available`));
}
} catch (netstatError) {
console.log(chalk.yellow(`⚠️ Could not check port ${port}: Both lsof and netstat failed`));
}
}
} else if (process.platform === 'win32') {
// Windows approach
const { stdout } = await execAsync(`netstat -ano | findstr :${port}`);
if (stdout.trim()) {
console.log(chalk.yellow(`⚠️ Port ${port} is in use. Attempting to terminate processes...`));
const pids = stdout.split('\n')
.filter(line => line.includes(`:${port}`))
.map(line => line.trim().split(/\s+/).pop() || '')
.filter(Boolean);
for (const pid of pids) {
try {
await execAsync(`taskkill /F /PID ${pid}`);
console.log(chalk.green(`✅ Terminated process ${pid} using port ${port}`));
} catch (error) {
console.error(chalk.red(`Failed to kill process ${pid}: ${error.message}`));
}
}
} else {
console.log(chalk.green(`✅ Port ${port} is available`));
}
}
} catch (error) {
// General error handling
console.log(chalk.yellow(`⚠️ Could not check port ${port}: ${error.message}`));
console.log(chalk.blue('Continuing anyway...'));
}
}
async function main() {
console.log(chalk.cyan.bold('🧹 Port Cleanup Utility'));
console.log(chalk.cyan('---------------------'));
for (const port of ports) {
await killProcessOnPort(port);
}
console.log(chalk.green('✅ Port cleanup complete'));
}
main().catch(error => {
console.error(chalk.red(`❌ Unhandled error: ${error.message}`));
console.log(chalk.yellow('Continuing with startup anyway...'));
process.exit(0); // Exit successfully even if port killing fails
});