Mac でポート3000が使用中のとき:プロセスを特定して終了する方法
2026年10月13日更新
Mac でポート3000を空けるには、lsof -nP -iTCP:3000 -sTCP:LISTEN でどのプロセスが待ち受けているかを確認し、kill <PID> でそのプロセスを停止します。kill -9 は通常のシグナルを無視されたときだけ使います。犯人はたいてい、以前のセッションで起動したまま残っている開発サーバー(Node、Vite、Next.js、Rails、Python)です。
コマンドを打つより一覧で待ち受けポートを見たい場合は、無料のメニューバーアプリ WTMemory で、ポートとそれを所有するプロセスを確認できます。詳しくは最後に紹介しますが、以下のターミナルでの方法はどの Mac でも使えます。
「EADDRINUSE: address already in use :::3000」とはどういう意味?
ひとつの TCP ポートとアドレスを同時に待ち受けられるプロセスはひとつだけです。Node が Error: listen EADDRINUSE: address already in use :::3000 と表示したり、Rails が Address already in use - bind(2) for "127.0.0.1" port 3000 と言ったりするのは、すでに何かがそのポートを確保しているため OS が bind を拒否したということです。新しいサーバー自体に問題はありません。古いリスナーを見つけて止めるか、別のポートで起動する必要があります。
Mac でポート3000を使っているプロセスを調べるには?
macOS には lsof(list open files)が標準で入っており、ネットワークソケットも一覧表示できます。
lsof -nP -iTCP:3000 -sTCP:LISTEN
出力例:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 48213 you 23u IPv6 0x... 0t0 TCP *:3000 (LISTEN)
-iTCP:3000は、ポート3000の TCP ソケットだけに絞り込みます。-sTCP:LISTENは、待ち受け中のソケットだけを表示し、そこに接続しているクライアントは除外します。-nと-Pは DNS とポート名の解決を省略するので、lsof がかなり速くなります。
kill の対象になるのは PID 列です。COMMAND は9文字で切り詰められるので、プロジェクトのパスを含む完全なコマンドラインを見たいときは ps -p 48213 -o pid,ppid,etime,command を実行します。
Mac 上で待ち受け中の TCP ポートをまとめて一覧表示するには:
lsof -nP -iTCP -sTCP:LISTEN
lsof に表示されるのは、調べる権限のあるプロセスだけです。ポートが使用中なのに lsof に何も出ない場合、リスナーはほかのユーザーか root のものです。sudo を付けてもう一度実行してください。
ポート3000のプロセスを kill するには?
kill 48213
もう一度 lsof コマンドを実行し、何も表示されなければポートは空いています。ワンライナーにすると:
lsof -ti tcp:3000 -sTCP:LISTEN | xargs kill
-t は PID だけを出力し、それを xargs が kill に渡します。macOS の BSD 版 xargs は入力が空ならコマンドを実行しないので、ポートがすでに空いていても害はありません。
-sTCP:LISTEN の指定は外さないでください。よく紹介される lsof -ti :3000 | xargs kill は、ポート3000に接続しているすべてのクライアントにもマッチします。そこにはたいてい localhost:3000 を開いているブラウザのタブも含まれます。この指定がないと、サーバーと一緒に Chrome や Safari まで終了してしまうことがあります。
kill と kill -9、どちらを使うべき?
普通の kill は SIGTERM を送ります。終了してほしいという丁寧なお願いです。Node、Vite、Next.js、Rails をはじめほとんどのサーバーはこれを受け取ると、ソケットを閉じ、ログをフラッシュし、子プロセスを停止します。kill -9 は SIGKILL を送り、カーネルが即座に強制終了します。プロセスは後片付けをする機会がないため、次のようなことが起こります。
- 子プロセス(ワーカー、ファイル監視、バンドラー)が孤児プロセスとして残り、別のポートを確保し続けることがあります。
- ロックファイル、PID ファイル、一時ファイルが残り、それを削除するまで起動を拒否するツールもあります。
- PostgreSQL や MySQL などのデータベースは、次回起動時にクラッシュリカバリが必要になります。たとえば
brew services stop postgresql@16のように、専用のツールで停止してください。
まず kill を送り、2〜3秒待って lsof で確認し、それでもだめなときに初めて kill -9 に切り替えましょう。
ターミナルを閉じたのにサーバーが動き続けるのはなぜ?
ターミナルのウインドウを閉じると、通常はシェルとそのジョブにハングアップが送られます。ただし、それでも生き残る構成はたくさんあります。
- Ctrl+C ではなく Ctrl+Z を押した。 Ctrl+Z はサーバーを一時停止するだけで、停止中のプロセスもポートを確保したままです。
jobsを実行し、fgで戻してから Ctrl+C を押します。 - 孤児になった子プロセス。
npm run devはシェルを起動し、そのシェルがnodeを起動します。親が突然終了すると、子がlaunchd(PID 1)の子として引き取られ、サーバーを提供し続けることがあります。 - エディタのターミナルやタスク。 VS Code、Cursor、JetBrains の IDE は、ウインドウを閉じたりクラッシュしたりしたあとも、統合ターミナルやバックグラウンドタスクを生かしておくことがあります。
- tmux、screen、
nohup、disown付きの&。 これらはもともとターミナルより長く生き残るための仕組みです。 - プロセス管理ツール。
brew services(launchd)、pm2、nodemon、Docker の再起動ポリシーは、kill したプロセスを新しい PID ですぐに復活させます。
取り残された開発サーバーを名前で探すには?
古いサーバーがいくつも残っているときは、名前で絞り込み、親 PID と稼働時間と一緒に一覧表示します。
ps -axo pid,ppid,etime,command | grep -E 'node|vite|next|webpack|rails|python' | grep -v grep
PPID が 1 なら、そのプロセスは孤児になって launchd に引き取られています。ETIME が大きい(数日、あるいはターミナルを開いていないのに数時間)のも手がかりです。pgrep -fl vite ならもっと短い一覧が得られます。pkill -f "next dev" でパターン指定して停止することもできますが、-f は完全なコマンドラインのどこにでもマッチするので、先に pgrep -fl "next dev" で何がマッチするか確認してください。
Docker がポートを使っている場合は?
lsof に Docker のプロセス(たとえば com.docker.backend)が表示される場合は、コンテナがそのポートを公開しています。Docker のプロセスを kill するとすべてのコンテナが止まってしまうので、やめましょう。該当するコンテナを探して停止します。
docker ps --filter "publish=3000"
docker stop <container>
Mac の開発でよく使われるポート
| ポート | 主な使用元 |
|---|---|
| 3000 | Next.js、Create React App、Nuxt、Rails、多くの Express アプリ |
| 4200 | Angular CLI |
| 5000, 7000 | AirPlay レシーバー(ControlCenter)、Flask のデフォルト |
| 5173, 4173 | Vite 開発サーバー、Vite preview |
| 8000 | Django、python3 -m http.server |
| 8080 | Tomcat、Spring Boot、各種プロキシ |
| 8888 | Jupyter |
| 5432, 3306, 6379, 27017 | PostgreSQL、MySQL、Redis、MongoDB |
| 11434 | Ollama |
どのポートでも同じ lsof コマンドが使えます。3000 をそのポート番号に置き換えてください。
macOS でポート5000や7000が使用中なのはなぜ?
macOS Monterey 以降、AirPlay レシーバーがポート5000と7000を待ち受けていて、lsof では所有者が ControlCenter と表示されます。ほかに何も動いていない Mac で、新しく作った Flask アプリが「Address already in use」で失敗するのはこのためです。ControlCenter を kill しても macOS が再起動するだけなので、やめましょう。代わりに次のどちらかを行います。
- システム設定 > 一般 > AirDrop と Handoff で AirPlay レシーバーをオフにする(Monterey の場合:システム環境設定 > 共有)
- アプリを別のポートで動かす。たとえば
flask run --port 5001。
次からポートの競合を防ぐには?
- サーバーは Ctrl+Z ではなく Ctrl+C で止め、ターミナルを閉じる前に
jobsを確認しましょう。 - 2つのプロジェクトを同時に動かすときは別のポートを選びます:
PORT=3001 npm start、next dev -p 3001、vite --port 5174。 - Vite は空いている次のポートへ自動的に移ります。古いサーバーに気づけるよう失敗させたい場合は
--strictPortを付けます。
ポートを使っているプロセスをメニューバーから調べる
WTMemory は macOS 12 以降に対応したネイティブのメニューバーアプリで、Apple シリコンと Intel の両方で動きます。メニューから Find What's Using a Port(ポートを使用中のプロセスを探す)を選ぶと、TCP の待ち受けエンドポイントとそれぞれの背後にあるプロセスが表示されます。Running Apps(実行中のアプリ)を開けば、開発用の各プロセスの PID、実行ファイルの場所、メモリ、CPU を確認できます。確認するだけなら無料です。
プロセスの停止は Pro の機能で、実行前に内容を確認して承認します。リスナーを停止するとそのポートだけでなくプロセス全体が止まります。また WTMemory は、プロセスを「放置されている」「停止しても安全」などと判定しません。判断するのはあなたです。ロックで保護したアプリが終了されることはありません。Pro は買い切り $9 USD で最大3台の Mac に使え、7日間の試用付きです。
よくある質問
ポート3000を使っているものを1コマンドで終了するには?
lsof -ti tcp:3000 -sTCP:LISTEN | xargs kill を実行します。-sTCP:LISTEN の指定が重要です。これがないと、ブラウザなどポート3000に接続しているクライアントも lsof の結果に含まれ、それらまで終了してしまいます。
kill -9 は使わないほうがいい?
最後の手段です。SIGKILL はプロセスを即座に終了させるため、書き込みのフラッシュ、ロックファイルの削除、子プロセスの停止を行う余地がありません。まず普通の kill を試し、数秒待ちましょう。
終了してもプロセスが復活するのはなぜ?
何かが再起動しています。launchd 経由の Homebrew services、pm2、nodemon、ファイル監視ツール、再起動ポリシー付きの Docker コンテナなどです。brew services stop や docker stop など、そのツール側で停止してください。
ポートを使っているプロセスを見るのに sudo は必要?
ほかのユーザーや root が所有するプロセスの場合だけ必要です。lsof に何も表示されないのにポートが使用中なら、同じコマンドを sudo 付きで実行してください。
何も起動していないのに Mac でポート5000が使用中なのはなぜ?
macOS Monterey 以降、AirPlay レシーバーが ControlCenter プロセスを通じてポート5000と7000を待ち受けています。システム設定で AirPlay レシーバーをオフにするか、アプリを別のポートで動かしてください。