Skip to content

Commit 1d0c0da

Browse files
authored
Merge pull request #33005 from storybookjs/yann/kill-verdaccio-process
Build: Enhance run-registry script to kill existing Verdaccio processes
2 parents d12cf1b + 3907cd9 commit 1d0c0da

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

scripts/run-registry.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { parseConfigFile, runServer } from 'verdaccio';
1313

1414
import { maxConcurrentTasks } from './utils/concurrency';
1515
import { PACKS_DIRECTORY } from './utils/constants';
16+
import { killProcessOnPort } from './utils/kill-process-on-port';
1617
import { getWorkspaces } from './utils/workspace';
1718

1819
program
@@ -37,6 +38,10 @@ const pathExists = async (p: string) => {
3738
};
3839

3940
const startVerdaccio = async () => {
41+
// Kill Verdaccio related processes if they are already running
42+
await killProcessOnPort(6001);
43+
await killProcessOnPort(6002);
44+
4045
const ready = {
4146
proxy: false,
4247
verdaccio: false,
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// eslint-disable-next-line depend/ban-dependencies
2+
import { execa } from 'execa';
3+
4+
const isWindows = process.platform === 'win32';
5+
6+
/** Kills any process that is listening on the specified port. */
7+
export const killProcessOnPort = async (port: number): Promise<void> => {
8+
try {
9+
let pids: string[] = [];
10+
11+
if (isWindows) {
12+
// Windows: use netstat to find the process
13+
try {
14+
const { stdout } = await execa('netstat', ['-ano']);
15+
const lines = stdout.split('\n');
16+
const regex = new RegExp(`TCP.*:${port}.*LISTENING\\s+(\\d+)`, 'i');
17+
18+
for (const line of lines) {
19+
const match = line.match(regex);
20+
if (match && match[1]) {
21+
pids.push(match[1]);
22+
}
23+
}
24+
} catch {
25+
// netstat failed, ignore
26+
}
27+
} else {
28+
// Unix-like (macOS, Linux): use lsof
29+
try {
30+
const { stdout } = await execa('lsof', ['-ti', `:${port}`]);
31+
pids = stdout.trim().split('\n').filter(Boolean);
32+
} catch {
33+
// lsof failed or no process found
34+
}
35+
}
36+
37+
if (pids.length > 0) {
38+
console.log(`☠️ killing process(es) on port ${port}: ${pids.join(', ')}`);
39+
40+
if (isWindows) {
41+
await Promise.all(
42+
pids.map((pid) => execa('taskkill', ['/PID', pid, '/F']).catch(() => {}))
43+
);
44+
} else {
45+
await Promise.all(pids.map((pid) => execa('kill', ['-9', pid]).catch(() => {})));
46+
}
47+
48+
// Give the OS a moment to release the port
49+
await new Promise((resolve) => setTimeout(resolve, 500));
50+
}
51+
} catch {
52+
// No process found on port or command failed, which is fine
53+
}
54+
};

0 commit comments

Comments
 (0)