- 技術 💻
ポートを使っているプロセスの調べ方|ss・lsof・netstat比較
Linux では sudo ss -ltnp 'sport = :8000' で、8000番ポートで待ち受けているプロセスの名前と PID が分かります。 lsof・netstat・fuser でも同じことが分かり、出す情報と得意なことが少しずつ違います。
sudo ss -ltnp 'sport = :8000' # Linux(標準で入っていることが多い)
sudo lsof -nP -iTCP:8000 -sTCP:LISTEN # Linux・Mac
netstat -ano | findstr :8000 # Windows(コマンドプロンプト)
8000番で動かした Python のサーバーに対して、4つのコマンドを実際に動かした結果です。
| コマンド | 分かること | 出力(抜粋) | 入っているか |
|---|---|---|---|
ss -ltnp |
状態・待ち受けアドレス・プロセス名・PID・fd | 0.0.0.0:8000 ... users:(("python3",pid=1869,fd=3)) |
iproute2 に含まれる |
lsof -i :8000 |
プロセス名・PID・ユーザー・IPv4/IPv6 | python3 1869 root 3u IPv4 ... TCP *:8000 (LISTEN) |
別に入れることがある |
netstat -ltnp |
状態・アドレス・PID/プロセス名 | 0.0.0.0:8000 ... LISTEN 1869/python3 |
net-tools(入っていないことが多い) |
fuser -v 8000/tcp |
PID・ユーザー・プロセス名。-k で止める |
8000/tcp: root 1869 F.... python3 |
psmisc |
確認環境:Ubuntu 24.04(Linux カーネル 6.18)で、ss(iproute2-6.1.0)・lsof 4.95.0・netstat(net-tools 2.10)・fuser(PSmisc 23.7)を動かし、Python 3.11・Node.js 22.22.2・Java(OpenJDK 21.0.10)でエラー文と TIME_WAIT の動きを再現しました。Mac・Windows・Docker のコマンドは公式ドキュメントで確かめています。図は mermaid-cli 11.14.0 で描画できることを確かめました(確認日 2026年10月13日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ポートを使っているプロセスの調べ方|ss・lsof・netstat比較」
切り分けの流れ
「Address already in use」が出たときは、まず「待ち受けているプロセスがいるか」を見て、いなければ TIME_WAIT やアドレスの指定を疑います。
flowchart TD
A["Address already in use / EADDRINUSE"] --> B{"sudo ss -ltnp で<br/>そのポートが LISTEN か"}
B -- "いる" --> C{"プロセス名・PID は出たか"}
C -- "出た" --> D["ps で中身を確かめて止める<br/>(kill・systemctl stop)"]
C -- "出ない" --> E["sudo を付ける / コンテナ・別ユーザーを疑う"]
B -- "いない" --> F{"ss -tan state time-wait に<br/>そのポートがあるか"}
F -- "ある" --> G["TIME_WAIT:待つか SO_REUSEADDR"]
F -- "ない" --> H["待ち受けアドレスの指定・<br/>同じプロセスの二重 listen を疑う"]
ss:Linux で最初に使うコマンド
ss は iproute2 に含まれ、多くの Linux ディストリビューションに最初から入っています。 netstat の後継として使われています。
$ sudo ss -ltnp 'sport = :8000'
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 5 0.0.0.0:8000 0.0.0.0:* users:(("python3",pid=1869,fd=3))
| オプション | 意味(man ss より) |
|---|---|
-l |
待ち受け中(LISTEN)のソケットだけ |
-t / -u |
TCP / UDP |
-n |
サービス名に変換しない(:http ではなく :80) |
-p |
ソケットを使っているプロセスを出す |
-a |
待ち受け中と接続中の両方 |
-s |
集計だけ(件数が多いとき向き) |
出力の読み方
| 列 | 例 | 読み方 |
|---|---|---|
| State | LISTEN |
待ち受け中。接続中なら ESTAB |
| Local Address:Port | 0.0.0.0:8000 |
どのアドレスで待っているか。0.0.0.0 は全部、127.0.0.1 は自分のマシンからだけ |
| Peer Address:Port | 0.0.0.0:* |
相手。待ち受け中は * |
| Process | ("python3",pid=1869,fd=3) |
プロセス名・PID・ファイル記述子の番号 |
| Recv-Q / Send-Q | 0 / 5 |
LISTEN では、Send-Q は受け付け待ちの列の上限(この例は 5) |
'sport = :8000' はフィルタの書き方です。 grep :8000 だと :80001 や相手側のポートも引っかかりますが、フィルタなら自分側のポートだけに絞れます。相手側のポートは dport、両方なら '( sport = :8000 or dport = :8000 )' と書きます。
sudo を付けないとプロセス名が出ない
自分以外のユーザーのプロセスは、root でないとプロセス名が出ません。 root で動くサーバーを、一般ユーザー(nobody)から調べた結果です。
| コマンド(一般ユーザー) | 結果 |
|---|---|
ss -ltnp 'sport = :8000' |
行は出るが、Process 列が空 |
lsof -i :8000 |
何も出ない(終了ステータス 1) |
netstat -ltnp |
PID 列が -、先頭に (Not all processes could be identified, ...) |
lsof は、見えないと何も出しません。 「何も出ないから空いている」と判断すると間違えるので、ss -ltn(-p なし)で、ポートが使われているかどうかを先に見ます。
lsof:ユーザー名と接続の向きが分かる
$ sudo lsof -nP -iTCP:8000 -sTCP:LISTEN
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 1869 root 3u IPv4 22948 0t0 TCP *:8000 (LISTEN)
| オプション | 意味 |
|---|---|
-i :8000 |
8000番を使うネットワークのファイル(待ち受け・接続中の両方) |
-iTCP:8000 -sTCP:LISTEN |
TCP の 8000番で、待ち受け中のものだけ |
-n / -P |
ホスト名・ポート名に変換しない(速くなる) |
-t |
PID だけを出す(kill $(lsof -t -i :8000) のように使う) |
-i :8000 だけだと、接続中のクライアントも出ます。 8000番に1本つないだ状態で動かした結果です。サーバー(PID 3064)の待ち受けと接続、クライアント(PID 3066)の接続が並びます。
$ sudo lsof -nP -i :8000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3 3064 root 3u IPv4 29377 0t0 TCP *:8000 (LISTEN)
python3 3064 root 4u IPv4 28632 0t0 TCP 127.0.0.1:8000->127.0.0.1:37732 (ESTABLISHED)
python3 3066 root 3u IPv4 28631 0t0 TCP 127.0.0.1:37732->127.0.0.1:8000 (ESTABLISHED)
NAME の -> の左が自分、右が相手です。止めたいのは LISTEN の行のプロセスで、クライアント側の PID を止めても、ポートは空きません。
netstat と fuser
$ sudo netstat -ltnp | grep :8000
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 1869/python3
$ sudo fuser -v 8000/tcp
USER PID ACCESS COMMAND
8000/tcp: root 1869 F.... python3
netstat は net-tools に含まれ、最近のディストリビューションでは最初から入っていないことがあります。fuser は -k を付けると、そのポートを使うプロセスにシグナル(既定は SIGKILL)を送ります。 手元では sudo fuser -k 8001/tcp で、8001番のプロセスが止まりました。中身を確かめずに止めることになるので、先に -v で何が止まるかを見ます。
見つけたプロセスを確かめて止める
PID が分かったら、止める前に「何のプロセスか」を確かめます。 同じ python3 や java でも、別の人が動かしているサービスのことがあります。
$ ps -o pid,ppid,user,lstart,cmd -p 1869
PID PPID USER STARTED CMD
1869 1 root Tue Oct 13 00:35:45 2026 python3 -m http.server 8000 --bind 0.0.0.0
$ ls -l /proc/1869/cwd
lrwxrwxrwx 1 root root 0 Oct 13 00:35 /proc/1869/cwd -> /home/you/app
| 確かめること | コマンド | 分かること |
|---|---|---|
| 起動したコマンド | ps -o cmd -p PID |
引数まで(どの設定ファイル・ポートか) |
| 親のプロセス | ps -o ppid -p PID |
PPID が 1 なら、サービスや nohup で切り離されたもの |
| 作業ディレクトリ | ls -l /proc/PID/cwd |
どのプロジェクトから起動したか |
| サービスか | systemctl status PID |
systemd のサービス名 |
| 止め方 | コマンド | 向いている場面 |
|---|---|---|
| 普通に止める | kill PID(SIGTERM) |
まずこれ。後片付けをしてから終わる |
| 強制的に止める | kill -9 PID |
SIGTERM で止まらないとき |
| サービスを止める | sudo systemctl stop 名前 |
systemd が動かしているもの(kill しても再起動される) |
| ポート指定で止める | sudo fuser -k 8000/tcp |
中身を確かめたあと |
プロセスの調べ方と止め方は、関連記事「Linuxプロセス確認と停止|ps・top・kill逆引きコマンド一覧」で扱っています。
Mac で調べる
Mac でも lsof が使えます。 lsof のマニュアルは Mac(Darwin)を含む複数の UNIX を対象にしていて、-iTCP:8000 -sTCP:LISTEN・-t・-n・-P の書き方は Linux と同じです。
sudo lsof -nP -iTCP:8000 -sTCP:LISTEN
kill $(lsof -t -iTCP:8000 -sTCP:LISTEN)
マニュアルには「Apple Darwin は UDP の状態を lsof に渡さない」とあり、Mac では UDP を状態で絞り込めません。UDP は sudo lsof -nP -iUDP:53 のように状態を付けずに調べます。
Windows で調べる
コマンドプロンプトでは netstat -ano、PowerShell では Get-NetTCPConnection を使います。
netstat -ano | findstr :8000
tasklist /FI "PID eq 1234"
taskkill /PID 1234 /F
Get-NetTCPConnection -LocalPort 8000 -State Listen |
Select-Object LocalAddress, LocalPort, State, OwningProcess
Get-Process -Id (Get-NetTCPConnection -LocalPort 8000 -State Listen).OwningProcess
Stop-Process -Id 1234
| コマンド | オプションの意味(Microsoft のドキュメントより) |
|---|---|
netstat -a |
すべての TCP 接続と、待ち受け中の TCP・UDP ポート |
netstat -n |
アドレスとポートを数字で出す(名前に変換しない) |
netstat -o |
接続ごとに PID を出す |
netstat -b |
実行ファイル名を出す(権限が足りないと失敗する) |
Get-NetTCPConnection -LocalPort |
ローカルのポートで絞り込む。-State には Listen・Established・TimeWait など |
Get-NetTCPConnection の結果の OwningProcess が PID です。
Docker のコンテナが使っている場合
ホストのポートをコンテナに割り当てている(-p 8080:80)と、ホスト側では Docker が待ち受けます。 ss で見ると、プロセス名がアプリではなく Docker 側のプロセス(docker-proxy など)になることがあります。Docker のドキュメントでは、ユーザーランドプロキシは既定で有効(--userland-proxy=true)です。
docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Ports}}'
docker port コンテナ名 # そのコンテナのポートの割り当て
docker stop コンテナ名
| 見るところ | 例 | 読み方 |
|---|---|---|
docker ps の PORTS 列 |
0.0.0.0:32768->80/tcp |
左がホスト側、右がコンテナ側。この例はホストの 32768番を使う |
docker ps --filter publish=80 |
― | ドキュメントの例では、コンテナ側が 80番のコンテナが出る |
docker ps -a |
Exited |
止まったコンテナはポートを使わない |
docker ps --filter publish= はコンテナ側のポートで絞り込みます。 ホスト側の 8080番を使うコンテナを探すときは、PORTS 列を見ます。Docker の「port is already allocated」のエラーは、関連記事「Docker port is already allocatedの直し方」で扱っています。
言語ごとのエラー文
同じ 8000番が使われているときに、それぞれ出たエラーです。
| 言語 | エラー文 |
|---|---|
| Python 3.11 | OSError: [Errno 98] Address already in use |
| Node.js 22 | Error: listen EADDRINUSE: address already in use 0.0.0.0:8000(code: 'EADDRINUSE', errno: -98) |
| Java 21 | java.net.BindException: Address already in use |
Error: listen EADDRINUSE: address already in use 0.0.0.0:8000
at Server.setupListenHandle [as _listen2] (node:net:1940:16)
...
code: 'EADDRINUSE',
errno: -98,
syscall: 'listen',
address: '0.0.0.0',
port: 8000
98 は Linux の EADDRINUSE の番号です。 どの言語でも、OS の bind(ポートの割り当て)が失敗したことを表しています。言語ごとの直し方は、関連記事「EADDRINUSE: address already in useの直し方」「Port 8080 was already in useの直し方|OS別の手順」で、OS 別の手順のまとめは「Address already in useの解決方法【Windows・Mac・Linux】」で扱っています。
待ち受けアドレスが違っても、ぶつかる
127.0.0.1:8000 と 0.0.0.0:8000 は、別のアドレスでも同時には待ち受けられません。 Python で試した結果です。
| 先に待ち受けたもの | 後から bind したもの | 結果 |
|---|---|---|
127.0.0.1:9000 |
0.0.0.0:9000 |
[Errno 98] Address already in use |
127.0.0.1:9000 |
0.0.0.0:9000(SO_REUSEADDR あり) |
[Errno 98] Address already in use |
0.0.0.0:8000 |
127.0.0.1:8000 |
[Errno 98] Address already in use |
0.0.0.0 は「全部のアドレス」なので、127.0.0.1 の同じポートと重なります。ss の Local Address が 127.0.0.1:9000 になっていて「8000 しか見ていなかった」と見落とすことがあるので、ポート番号で絞り込んで見ます。
TIME_WAIT と SO_REUSEADDR
サーバーを止めた直後に起動し直すと、待ち受けているプロセスがいないのに「Address already in use」になることがあります。 原因は、閉じた接続が TIME_WAIT(閉じたあと、遅れて届くパケットに備えてしばらく残る状態)でポートを持っているためです。
$ ss -tan state time-wait '( sport = :9100 )'
Recv-Q Send-Q Local Address:Port Peer Address:Port Process
0 0 127.0.0.1:9100 127.0.0.1:57052
TIME_WAIT は、先に接続を閉じた側に残ります。 サーバーが接続を先に閉じると、サーバーのポートに残ります。
再現:両方に SO_REUSEADDR が要る
サーバーが接続を先に閉じて TIME_WAIT を作り、そのあと同じポートで新しいサーバーを bind しました。
| 前のサーバー | 新しいサーバー | 結果 |
|---|---|---|
| SO_REUSEADDR なし | なし | Address already in use |
| なし | あり | Address already in use |
| あり | なし | Address already in use |
| あり | あり | OK |
Linux では、前のソケットと新しいソケットの両方に SO_REUSEADDR が付いていないと、TIME_WAIT のポートを使えませんでした。 man socket(7) にも、Linux では両方のソケットに設定が要ると書かれています。SO_REUSEADDR を付けても、待ち受け中(LISTEN)のソケットがいるときは使えません(上の表の2行目のとおり)。
付けないままでも、時間がたつと空きます。手元では、61秒待つと SO_REUSEADDR なしで bind できました。
主なサーバーの設定
| 言語・ライブラリ | SO_REUSEADDR | 確かめ方 |
|---|---|---|
Python http.server.HTTPServer |
付く(allow_reuse_address = 1) |
手元で属性を表示 |
Python socketserver.TCPServer |
付かない(False) |
同上。allow_reuse_address = True にすると付く |
Java ServerSocket(Linux) |
付く(getReuseAddress() が true) |
手元で表示 |
| Node.js | ドキュメントでは net.Socket に設定 |
Node.js のドキュメント |
自分で socket を作るときは、bind の前に設定します。
import socket
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # bind の前に
s.bind(("0.0.0.0", 8000))
s.listen()
SO_REUSEPORT は別物です。 同じポートを複数のソケットで同時に待ち受け、OS が接続を振り分けるためのもので、Linux 3.9 から使えます。設定はすべてのソケットに要り、同じ実効ユーザーのプロセスどうしに限られます(man socket(7) より)。「ポートが空かない」ときに付けるものではありません。
よくある質問
Q. ss でも lsof でも何も出ないのに Address already in use になります。
A. 次の順に見ます。① sudo を付けたか(付けないと他のユーザーのプロセスは見えない)、② ss -tan state time-wait に残っていないか、③ 同じプログラムの中で2回 listen していないか(設定の読み込みが2回など)、④ コンテナや別のネットワーク名前空間の中ではないか。
Q. kill したのに、すぐ同じポートでプロセスが立ち上がります。
A. systemd・supervisor・Docker の再起動設定などが、止まったプロセスを起動し直しています。PPID と systemctl status PID で親を確かめ、サービスとして止めます。
Q. UDP のポートを調べるには?
A. sudo ss -lunp 'sport = :53'、sudo lsof -nP -iUDP:53 のように、-u・-iUDP に変えます。
Q. どのポートが何に使われるのかを知りたいです。 A. 関連記事「ポート番号一覧【2026年版】well-knownポートと確認コマンドの早見表」で扱っています。
Q. ss や lsof が無いと言われます。
A. Ubuntu なら ss は iproute2、lsof は lsof、netstat は net-tools、fuser は psmisc のパッケージで入ります。コマンドが見つからないときの調べ方は、関連記事「command not foundの直し方|PATHの確認方法と原因別の対処表」で扱っています。
まとめ
- Linux は
sudo ss -ltnp 'sport = :ポート'、Mac はsudo lsof -nP -iTCP:ポート -sTCP:LISTEN、Windows はnetstat -anoかGet-NetTCPConnection sudoを付けないと、他のユーザーのプロセスは見えない(lsof は何も出さない)- 止める前に
ps・/proc/PID/cwd・systemctl statusで何のプロセスかを確かめる - Docker は PORTS 列の左がホスト側
127.0.0.1と0.0.0.0の同じポートもぶつかる- 待ち受けがいないのに使えないときは TIME_WAIT。Linux では前と新しいソケットの両方に SO_REUSEADDR が要った
参考・出典
確認日はいずれも 2026年10月13日です。
- ss(8) — Linux manual page:https://man7.org/linux/man-pages/man8/ss.8.html
- socket(7) — Linux manual page(SO_REUSEADDR・SO_REUSEPORT):https://man7.org/linux/man-pages/man7/socket.7.html
- lsof(8) — Linux manual page:https://man7.org/linux/man-pages/man8/lsof.8.html
- Microsoft Learn「netstat」:https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/netstat
- Microsoft Learn「Get-NetTCPConnection」:https://learn.microsoft.com/en-us/powershell/module/nettcpip/get-nettcpconnection
- Docker Docs「docker container ls」:https://docs.docker.com/reference/cli/docker/container/ls/
- Docker Docs「docker container port」:https://docs.docker.com/reference/cli/docker/container/port/
- Docker Docs「Port publishing and mapping」:https://docs.docker.com/engine/network/port-publishing/
- Node.js ドキュメント「Net」(EADDRINUSE・reusePort):https://nodejs.org/api/net.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ポートを使っているプロセスの調べ方|ss・lsof・netstat比較」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。