「ポート3000が空かない」を二度と言わないためにVSCode拡張を作った
きっかけ
開発中、npm run dev しようとしたら「port 3000 is already in use」。
ターミナルで lsof -i :3000 して、PID調べて、kill -9 して……。これ、週に何回やってるんだろう。Windowsだと netstat -ano | findstr :3000 からの taskkill /F /PID xxxx で、もっとだるい。
別にコマンド打てばいいんだけど、毎回覚えてないし、毎回ググるのがしんどい。
「VSCodeから全部できたらよくない?」と思って作った。
作ったもの
Port Manager — VSCode拡張機能。
やれることはシンプルで、
- 使用中のポート一覧をサイドバーに表示
- ポート番号やプロセス名で検索
- ワンクリックでプロセスKILL(確認ダイアログあり)
- 複数選択して一括KILL
- 指定範囲の空きポート確認
Mac、Windows、Linux全部動く。依存パッケージなし。
サイドバーの様子
左のアクティビティバーにアイコンが追加されて、開くとこんな感じ。
VSCodeのテーマに自動で合わせてくれるので、ダーク・ライトどっちでも違和感ない。
コマンドパレットからも使える
Cmd+Shift+P(WindowsならCtrl+Shift+P)で3つのコマンドが出る。
| コマンド | 何ができる |
|---|---|
Port Manager: Show Listening Ports |
QuickPickで一覧 → 選んでKILL |
Port Manager: Check Port Availability |
番号入れるだけで空き判定 |
Port Manager: Kill Port |
カンマ区切りで複数KILLもOK |
サイドバー開くまでもないときはこっちが速い。3000 って打つだけで「使ってるのはnodeだよ、殺す?」って聞いてくれる。
中身の話
OS判定でコマンドを分岐
ポートの取得方法がOSごとに全然違うので、os.platform() で分岐してる。
const PLATFORM = os.platform();
function getListeningPorts() {
if (PLATFORM === "darwin" || PLATFORM === "linux") return getPortsUnix();
if (PLATFORM === "win32") return getPortsWindows();
return [];
}
Mac/Linuxは lsof -iTCP -sTCP:LISTEN -nP でパースして、Windowsは netstat -ano + tasklist の合わせ技。lsof が使えないLinux環境では ss -tlnp にフォールバックするようにした。
KILLもOS分岐
function killByPid(pid) {
if (PLATFORM === "win32") {
execSync(`taskkill /F /PID ${pid}`, { timeout: 5000 });
} else {
execSync(`kill -9 ${pid}`, { timeout: 5000 });
}
}
やってること自体は単純なんだけど、これをGUIのボタンでポチッとやれるのが楽。
Webview は1ファイルで完結
サイドバーの表示はWebview APIを使っていて、HTMLを1ファイルにまとめてる。CSSは var(--vscode-editor-background) みたいなVSCodeのCSS変数を使えば、テーマ追従が勝手に効く。外部ライブラリは何も使ってない。
:root {
--bg: var(--vscode-editor-background);
--fg: var(--vscode-editor-foreground);
--accent: #00E676;
--danger: #FF5252;
}
Reactとか入れるほどの画面じゃないし、素のHTML/JS/CSSで十分だった。
インストール方法
マーケットプレースで「Port Manager」で検索するか、コマンドラインなら:
code --install-extension port-manager-saiki.port-manager-saiki
自分でVSCode拡張を公開するまでの流れ
ついでに、初めてマーケットプレースに公開してみたのでメモ。
1. Azure DevOps でPATを取得
https://dev.azure.com にMicrosoftアカウントでログインして、右上のアイコンから「Personal access tokens」→「New Token」。
ここで絶対に気をつけるポイントがひとつあって、Organizationの欄で**「All accessible organizations」を選ぶこと**。特定のorganizationを選ぶと公開時にエラーで詰む。
Scopesは「Custom defined」→「Show all scopes」→「Marketplace」の「Manage」にチェック。
2. Publisherを作成
https://marketplace.visualstudio.com/manage でPublisherを作る。ここで設定したIDを package.json の "publisher" に書く。
3. パッケージング & 公開
npm install -g @vscode/vsce
cd my-extension
vsce login <publisher-id> # PATを入力
vsce package # .vsix生成(テスト用)
vsce publish # 公開
ファイル構成はこれだけ:
├── package.json
├── extension.js
├── README.md
├── CHANGELOG.md
├── LICENSE
├── .vscodeignore
└── images/icon.png
TypeScriptでビルドとか、webpackでバンドルとか、そういうの一切なし。extension.js 1ファイルでいけた。
ハマったところ
portal.azure.com と dev.azure.com は別物
Azureを普段使ってると portal.azure.com に行きがちだけど、マーケットプレースの認証は dev.azure.com。全く別のサービス。リダイレクトされて「あれ?ポートの設定画面に来たんだけど??」ってなった。
Webview内の状態管理
Webviewはタブを切り替えると破棄されるので、acquireVsCodeApi() で取得したAPIを使ってpostMessageでやり取りする。Reactの感覚で状態を持つとハマる。
Windowsのnetstat出力のパース
Macの lsof は行儀のいい出力をしてくれるけど、Windowsの netstat はスペース区切りが微妙にブレるので split(/\s+/) でゴリ押し。tasklist と突き合わせてPID→プロセス名の変換もしてる。
まとめ
VSCode拡張、思ったより簡単だった。特にWebview APIが強力で、HTMLが書ければそれなりのUIが作れる。公開もvsceコマンド3つで終わる。
「こういうちょっとした面倒」を自動化する拡張を作るの、自分用ツールとしてもいいし、公開して誰かの役に立てばもっといい。
ソースコードはGitHubに上げてるので、気になる人は見てみてください。
👉 GitHub - port-manager-saiki/vscode-port-manager

