/** * kill-dev v2 - Ultimate Safe Process Cleanup Script * * Strategy: * 1. Clean up processes occupying ports (most critical) * 2. Wait 2 seconds for parent processes to exit naturally * 3. Check ports again to ensure complete cleanup * * About "missed processes": * - Parent processes (pnpm) usually exit automatically after child processes terminate * - vite build --watch doesn't occupy ports, exits with parent process * - Even if missed, they don't occupy ports and won't block new starts */ const { execSync } = require('child_process'); const os = require('os'); console.log('๐Ÿงน Safely cleaning up project development processes...\n'); // Limit to project-specific ports so we do not kill other apps using defaults like 5173 const PORTS = [18181]; /** * Cross-platform non-blocking sleep */ function wait(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function killByPorts(round = 1) { const platform = os.platform(); let killedCount = 0; const killedPids = new Set(); console.log(`๐Ÿ” Round ${round}: Checking port occupation...`); if (platform === 'win32') { for (const port of PORTS) { try { const output = execSync(`netstat -ano | findstr ":${port}"`, { encoding: 'utf-8', stdio: 'pipe' }); // Windows uses \r\n, so split by \n and trim each line const lines = output.split('\n').map(line => line.trim()).filter(Boolean); lines.forEach(line => { const match = line.match(/LISTENING\s+(\d+)/); if (match && !killedPids.has(match[1])) { const pid = match[1]; try { execSync(`taskkill /F /PID ${pid}`, { stdio: 'pipe' }); console.log(` โœ“ Killed process on port ${port} (PID: ${pid})`); killedPids.add(pid); killedCount++; } catch (e) { // Process may have already exited } } }); } catch (error) { // Port not occupied or command failed } } } else { for (const port of PORTS) { try { const output = execSync(`lsof -ti :${port}`, { encoding: 'utf-8', stdio: 'pipe' }); const pids = output.split('\n').map(pid => pid.trim()).filter(Boolean); pids.forEach(pid => { if (!killedPids.has(pid)) { try { execSync(`kill -9 ${pid}`, { stdio: 'pipe' }); console.log(` โœ“ Killed process on port ${port} (PID: ${pid})`); killedPids.add(pid); killedCount++; } catch (e) { // Process may have already exited } } }); } catch (error) { // Port not occupied or command failed } } } if (killedCount === 0) { console.log(' โ„น๏ธ No processes found occupying ports'); } return killedCount; } async function main() { try { // First round cleanup let totalKilled = killByPorts(1); if (totalKilled > 0) { // Wait for parent processes to exit naturally (cross-platform) console.log('\nโณ Waiting 2 seconds for parent processes to exit naturally...\n'); await wait(2000); // Second round cleanup (ensure no missed processes) const round2Killed = killByPorts(2); totalKilled += round2Killed; if (round2Killed > 0) { console.log('\n๐Ÿ’ก Found and cleaned up missed processes'); } else { console.log('\nโœ… Confirmed: All processes completely cleaned up'); } } console.log(`\n๐Ÿ“Š Total cleaned: ${totalKilled} process(es)`); if (totalKilled > 0) { console.log('โœ… Cleanup complete! You can now run pnpm dev:fresh'); } else { console.log('โ„น๏ธ No processes found that need cleanup'); } process.exit(0); } catch (error) { console.error('\nโŒ Cleanup failed:', error.message); console.error('\n๐Ÿ’ก Please try:'); console.error(' 1. Run this script again'); console.error(' 2. Or manually terminate related processes in Task Manager'); process.exit(1); } } main();