109 lines
4.0 KiB
JavaScript
Executable File
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
|
|
}); |