【bat】netstat コマンド完全ガイド|ポート使用確認・接続状態・PIDからプロセス特定・バッチ自動化パターンまで

【bat】netstat コマンド完全ガイド|ポート使用確認・接続状態・PIDからプロセス特定・バッチ自動化パターンまで bat

「このポートは本当に使われているの?」「アプリが起動しないのはポートが競合しているから?」——こういった場面で活躍するのが netstat コマンドです。

Windows 標準搭載の netstat を使えば、現在開いているポートや確立している通信、ポートを使用しているプロセスを一覧で確認できます。この記事では基本構文からバッチファイルでの自動化まで、実務で使えるパターンを一通り解説します。

スポンサーリンク

netstat コマンドの基本構文とオプション

基本構文
netstat [オプション] [interval]

主要オプション:
-a   : すべての接続とリスニングポートを表示
-n   : アドレス・ポートを数値で表示(名前解決しない)
-o   : 各接続に対応するPIDを表示
-b   : 各接続を使用している実行ファイル名を表示(管理者権限必要)
-p proto : 指定したプロトコルの接続を表示(TCP/UDP/TCPv6/UDPv6)
-r   : ルーティングテーブルを表示
-s   : プロトコル別の統計情報を表示
-e   : イーサネット統計を表示

表示間隔(秒数)を指定すると指定秒ごとに繰り返し表示:
netstat -ano 5   (5秒ごとに更新)

実務で最もよく使う組み合わせは netstat -ano です。すべての接続・ポートを数値で表示し、対応 PID も確認できます。名前解決しないため表示が速く、スクリプトでのパース処理にも向いています。

ポートの使用状況を確認する

すべての接続・待機ポートを表示

全接続を表示
rem 全接続とPIDを数値で表示
netstat -ano

rem TCPのみ
netstat -ano -p TCP

rem UDPのみ
netstat -ano -p UDP

出力の各列は「プロトコル・ローカルアドレス・外部アドレス・状態・PID」の順です。

netstat -ano の出力例
  プロトコル  ローカル アドレス      外部アドレス           状態            PID
  TCP         0.0.0.0:80             0.0.0.0:0              LISTENING       1234
  TCP         0.0.0.0:443            0.0.0.0:0              LISTENING       1234
  TCP         127.0.0.1:3306         0.0.0.0:0              LISTENING       5678
  TCP         192.168.1.10:54321     203.0.113.1:443        ESTABLISHED     9012
  UDP         0.0.0.0:53             *:*                                    1234

ローカルアドレスの 0.0.0.0 と 127.0.0.1 の違い

LISTENING 状態のローカルアドレスが何を意味するかを理解しておくと、セキュリティの観点でも役立ちます。

ローカルアドレス 意味 アクセス元
0.0.0.0:8080 全インターフェースで待機 ローカルマシン・ネットワーク上の他PC 両方からアクセス可
127.0.0.1:3306 ループバックのみで待機 ローカルマシンからのみアクセス可(外部からはアクセス不可)
192.168.1.5:80 特定NICのみで待機 そのIPアドレスのNICが接続するネットワークからのみ
:::80 IPv6の全インターフェースで待機 IPv4/IPv6 両方から(デュアルスタック)

0.0.0.0 でリッスンしているサービスは外部からアクセスできる状態です。データベース(MySQL の 3306 など)が 0.0.0.0 でリッスンしていたら、ファイアウォールで遮断されているか確認してください。

特定のポートが使用中か確認する

特定ポートが使用中か確認するには FINDSTR でフィルタリングします。

特定ポートの使用確認.bat
@echo off
set PORT=8080

netstat -ano | findstr ":%PORT% " | findstr "LISTENING" >nul 2>&1
if %ERRORLEVEL%==0 (
    echo ポート %PORT% は使用中(LISTENING)です。
) else (
    echo ポート %PORT% は空き状態です。
)

FINDSTR のパターンは ":%PORT% " のように コロン+ポート番号+スペース で検索してください。こうすることで、ポート 80 の検索で 8080 や 18080 を誤検知しません。ポート番号の後ろのスペースが重要です。

接続状態の種類と意味

状態 意味 確認・対処ポイント
LISTENING 接続を待ち受け中(サーバーソケット) サービス・アプリが起動して待機している
ESTABLISHED 接続確立中(通信中) クライアントとサーバーがアクティブに通信している
TIME_WAIT 接続クローズ後の待機状態(既定240秒) 通常は短時間で消える。大量残存は高負荷・ポート不足の可能性
CLOSE_WAIT 相手からの切断を受信し、こちらの切断待ち 増え続ける場合はアプリがソケットを正しく閉じていないバグの疑い
SYN_SENT 接続開始リクエストを送信し、応答待ち 接続先が応答しない場合に残る。接続先の疎通を確認
SYN_RECEIVED 接続開始リクエストを受信し、確認待ち SYN フラッド攻撃時に大量発生することがある
FIN_WAIT_1/2 切断処理中 通常は瞬間的。残り続ける場合はアプリ側の問題

PID からプロセスを特定する

netstat -ano でわかった PID から tasklist でプロセス名を調べます。

PIDからプロセス名を特定.bat
@echo off
set PORT=8080

rem 指定ポートをLISTENしているPIDを取得
set PID=
for /f "tokens=5" %%p in (
    'netstat -ano ^| findstr ":%PORT% " ^| findstr "LISTENING"'
) do if not defined PID set PID=%%p

if not defined PID (
    echo ポート %PORT% を使用しているプロセスは見つかりませんでした。
    exit /b 0
)

echo ポート %PORT% を使用しているPID: %PID%
tasklist /fi "PID eq %PID%" /fo table

for /f "tokens=5" で5列目(PID)を取得しています。netstat -ano の出力は「プロトコル・ローカルアドレス・外部アドレス・状態・PID」の順に並んでいます。詳しくは外部コマンドの結果を変数に格納する方法を参照してください。

ポート占有プロセスを確認して終了する

ポート占有プロセスを終了.bat
@echo off
setlocal
set PORT=8080

rem PID取得
set PID=
for /f "tokens=5" %%p in (
    'netstat -ano ^| findstr ":%PORT% " ^| findstr "LISTENING"'
) do if not defined PID set PID=%%p

if not defined PID (
    echo ポート %PORT% は使用されていません。
    exit /b 0
)

echo PID %PID% がポート %PORT% を使用しています。
tasklist /fi "PID eq %PID%" /fo list | findstr "イメージ名"

echo このプロセスを終了しますか?
choice /c YN /m "[Y]終了する  [N]キャンセル"
if ERRORLEVEL 2 exit /b 0

taskkill /pid %PID% /f
if ERRORLEVEL 1 (
    echo [ERROR] プロセスの終了に失敗しました。管理者権限で実行してください。
) else (
    echo [OK] PID %PID% を終了しました。
)

バッチファイルでの自動化パターン

パターン1:ポートが開放されるまで待機する

アプリの起動を待ってから次の処理を実行したい場合に使えます。サーバーが起動して特定ポートが LISTEN 状態になるまで待機します。

ポート開放待機.bat
@echo off
setlocal
set PORT=8080
set TIMEOUT_SEC=60
set ELAPSED=0

echo ポート %PORT% が開放されるまで待機します...

:WAIT_LOOP
netstat -ano | findstr ":%PORT% " | findstr "LISTENING" >nul 2>&1
if %ERRORLEVEL%==0 (
    echo ポート %PORT% が開放されました。(%ELAPSED%秒後)
    exit /b 0
)

if %ELAPSED% GEQ %TIMEOUT_SEC% (
    echo タイムアウト: %TIMEOUT_SEC%秒待機しましたがポート %PORT% は開放されませんでした。
    exit /b 1
)

timeout /t 3 /nobreak >nul
set /a ELAPSED+=3
goto WAIT_LOOP

パターン2:接続数を監視してアラートを出す

接続数監視.bat
@echo off
setlocal enabledelayedexpansion
set PORT=80
set ALERT_COUNT=100
set LOG=C:\logs\netstat_alert.log
if not exist "C:\logs" mkdir "C:\logs"

:MONITOR_LOOP
rem 指定ポートの ESTABLISHED 接続数をカウント
for /f %%c in (
    'netstat -ano ^| findstr ":%PORT% " ^| findstr "ESTABLISHED" ^| find /c "ESTABLISHED"'
) do set COUNT=%%c

echo %DATE% %TIME% - ポート %PORT% の接続数: %COUNT% >> "%LOG%"

if %COUNT% GEQ %ALERT_COUNT% (
    echo [ALERT] %DATE% %TIME% - ポート %PORT% の接続数が %COUNT% に達しました! >> "%LOG%"
)

timeout /t 30 /nobreak >nul
goto MONITOR_LOOP

パターン3:定期的なポート状態レポートを生成する

ポート状態レポート生成.bat
@echo off
setlocal
for /f "tokens=1-3 delims=/ " %%a in ("%DATE%") do set DSTR=%%a%%b%%c
set REPORT=C:\logs\port_report_%DSTR%.txt
if not exist "C:\logs" mkdir "C:\logs"

echo ===== ポート状態レポート %DATE% %TIME% ===== > "%REPORT%"
echo. >> "%REPORT%"

echo --- LISTENINGポート一覧 --- >> "%REPORT%"
netstat -ano | findstr "LISTENING" >> "%REPORT%"
echo. >> "%REPORT%"

echo --- ESTABLISHED接続一覧 --- >> "%REPORT%"
netstat -ano | findstr "ESTABLISHED" >> "%REPORT%"
echo. >> "%REPORT%"

for /f %%c in ('netstat -ano ^| findstr "LISTENING" ^| find /c "LISTENING"') do (
    echo LISTENING ポート数: %%c >> "%REPORT%"
)
for /f %%c in ('netstat -ano ^| findstr "ESTABLISHED" ^| find /c "ESTABLISHED"') do (
    echo ESTABLISHED 接続数: %%c >> "%REPORT%"
)

echo レポートを生成しました: %REPORT%
type "%REPORT%"

パターン4:複数ポートを一括チェックする

複数ポート一括チェック.bat
@echo off
setlocal enabledelayedexpansion

rem チェック対象ポートリスト
set PORTS=80 443 3306 5432 8080 8443

echo ===== ポート使用状況チェック =====
echo ポート      状態          PID
echo --------    ----------    -----

for %%P in (%PORTS%) do (
    set STATUS=空き
    set PID=-
    for /f "tokens=4,5" %%a in (
        'netstat -ano ^| findstr ":%%P " ^| findstr "LISTENING"'
    ) do (
        set STATUS=使用中
        set PID=%%b
    )
    echo %%P          !STATUS!    !PID!
)

パターン5:TIME_WAIT 状態の大量発生を検知する

高負荷な Web サーバーや API サーバーで TIME_WAIT が大量発生するとポート不足につながることがあります。

TIME_WAIT監視.bat
@echo off
setlocal
set THRESHOLD=500
set LOG=C:\logs\timewait_monitor.log
if not exist "C:\logs" mkdir "C:\logs"

for /f %%c in (
    'netstat -ano ^| findstr "TIME_WAIT" ^| find /c "TIME_WAIT"'
) do set TW_COUNT=%%c

echo %DATE% %TIME% - TIME_WAIT数: %TW_COUNT% >> "%LOG%"

if %TW_COUNT% GEQ %THRESHOLD% (
    echo [WARN] TIME_WAIT が %TW_COUNT% に達しています。ポート不足に注意してください。
)

パターン6:特定の外部 IP との接続を確認する

不審な接続先 IP との通信が発生していないか確認したいとき、または特定サーバーへの接続状況を把握したいときに使えます。

特定外部IPとの接続確認.bat
@echo off
set TARGET_IP=203.0.113.1

echo %TARGET_IP% との接続一覧:
netstat -ano | findstr "%TARGET_IP%"

rem 接続数をカウント
for /f %%c in ('netstat -ano ^| findstr "%TARGET_IP%" ^| find /c "%TARGET_IP%"') do (
    echo 接続数: %%c
)

パターン7:不審ポートの定期スキャンとログ記録

セキュリティ監査として、既知以外のポートが突然 LISTENING になっていないか監視できます。

不審ポート監視.bat
@echo off
setlocal
set LOG=C:\logs\port_audit.log
if not exist "C:\logs" mkdir "C:\logs"

rem 許可ポートリスト(カンマ区切り)
set ALLOWED=80 443 3389 22 3306 1433

echo ===== ポート監査 %DATE% %TIME% ===== >> "%LOG%"

for /f "tokens=2" %%a in ('netstat -ano ^| findstr "LISTENING"') do (
    rem ローカルアドレスからポート番号を取得
    for /f "tokens=2 delims=:" %%p in ("%%a") do (
        rem 許可リストに含まれているか確認
        echo %ALLOWED% | findstr "%%p" >nul 2>&1
        if ERRORLEVEL 1 (
            echo [UNKNOWN PORT] %%p - %%a >> "%LOG%"
        )
    )
)

echo 監査完了。ログ: %LOG%

実行ファイル名も表示する(-b オプション)

-b オプションを使うと、各接続に対応する実行ファイル名(.exe)を表示できます。管理者権限が必要です。

実行ファイル名を表示(管理者権限必要)
rem 管理者権限が必要
netstat -anob

rem 特定ポートに絞り込む
netstat -anob | findstr ":8080"

-b は実行が遅くなります。通常は -ano で PID を取得してから tasklist /fi "PID eq XXX" で確認する方が高速です。

ルーティングテーブルを確認する(-r)

ルーティングテーブル確認
rem ルーティングテーブルを表示(route print と同等)
netstat -r

rem デフォルトゲートウェイを確認
netstat -r | findstr "0.0.0.0"

プロトコル統計を確認する(-s)

TCP/UDP/ICMP などのプロトコルごとの統計情報を表示します。パケットロスや再送数の確認に使えます。

プロトコル統計確認
rem 全プロトコルの統計
netstat -s

rem TCP統計のみ
netstat -s -p TCP

TCP 統計の「Segments Retransmitted」(再送セグメント数)が多い場合はネットワーク品質の問題が考えられます。

netstat と PowerShell の比較

Windows PowerShell には Get-NetTCPConnection コマンドがあり、netstat より柔軟なフィルタリングができます。

操作 netstat(bat) PowerShell
全接続表示 netstat -ano Get-NetTCPConnection
特定ポートで絞り込み findstr ":8080 " | Where-Object LocalPort -eq 8080
PIDからプロセス名 tasklist /fi "PID eq XXX" Get-Process -Id (PID)
速度 速い やや遅い(起動コスト)
日本語環境での安定性 列幅が変わる場合がある オブジェクト処理なので安定
PowerShellでポート確認(batから呼び出し)
@echo off
set PORT=8080
powershell -command "Get-NetTCPConnection -LocalPort %PORT% -State Listen -ErrorAction SilentlyContinue | Select-Object LocalPort,State,OwningProcess | Format-Table -AutoSize"

TIME_WAIT が大量発生する場合の対処

高負荷サーバーで TIME_WAIT が大量発生してポート不足になる場合、レジストリで待機時間を短縮できます。ただし本番環境での変更は慎重に行ってください。

TIME_WAIT待機時間を短縮(管理者権限・要注意)
rem TcpTimedWaitDelay を 30秒に短縮(デフォルト240秒)
rem ★本番環境での変更は事前にバックアップを取り、影響を十分確認すること★
reg add "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v TcpTimedWaitDelay /t REG_DWORD /d 30 /f

rem MaxUserPort を増やしてポール枯渇を防ぐ(デフォルト5000→65534)
reg add "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" /v MaxUserPort /t REG_DWORD /d 65534 /f

rem 変更後は再起動が必要
echo 変更を適用するには再起動が必要です。

レジストリを誤って変更するとシステムに深刻な影響が出ることがあります。変更前に必ずバックアップを取り、テスト環境で検証してから本番に適用してください。

よくあるトラブルと対処法

症状 原因 対処法
アプリが起動しない(ポート競合) 既に別プロセスが同じポートを使用している netstat -ano | findstr ":ポート番号 " で PID を確認し、不要なら taskkill で終了
netstat の出力が遅い 名前解決に時間がかかっている 必ず -n を付けて数値表示にする
-b オプションが使えない 管理者権限がない 管理者として実行する
TIME_WAIT が大量に残る 短時間に大量の接続を処理している TIME_WAIT は一定時間で自動解消。永続する場合はレジストリの TcpTimedWaitDelay を調整(要注意)
CLOSE_WAIT が増え続ける アプリがソケットを閉じていない(バグ) 対象プロセスの再起動。根本的にはアプリ側でソケットを適切に close() する修正が必要
0.0.0.0:3306 が外部公開されている MySQL等DBが全NICでリッスンしている bind-address=127.0.0.1 に変更してローカルのみにするか、ファイアウォールで外部からのアクセスを遮断
findstr でポート番号を絞り込むと誤検知する ポート 80 の検索で 8080 がヒットする等 ":80 " のようにコロンと後ろのスペースも含めて検索する
バッチで for /f のパースが失敗する 日本語環境で列数が変わる場合がある 出力を一時ファイルに書き出して確認するか、PowerShell の Get-NetTCPConnection を使う

まとめ

やりたいこと コマンド
全接続とPIDを表示 netstat -ano
特定ポートが使用中か確認 netstat -ano | findstr ":8080 " | findstr "LISTENING"
TCPのみ表示 netstat -ano -p TCP
LISTENING ポートのみ表示 netstat -ano | findstr "LISTENING"
PIDからプロセス名を調べる tasklist /fi "PID eq 1234"
実行ファイル名も表示(管理者) netstat -anob
ルーティングテーブル確認 netstat -r
プロトコル統計 netstat -s -p TCP
接続数をカウント netstat -ano | findstr "ESTABLISHED" | find /c "ESTABLISHED"

バッチファイルで netstat を活用する場合は for /ffindstr の組み合わせが基本です。PID の取得には tokens=5 が定番パターンです。ネットワーク接続確認IPアドレス取得などの関連記事もあわせて参照してください。

よくある質問

netstat -ano と netstat -an の違いは何ですか?
-o を追加することで、各接続に対応するプロセス ID(PID)が表示されます。-an だけではどのプロセスがポートを使っているか分かりませんが、-ano にすれば PID から tasklist でプロセス名を調べることができます。ポートのトラブルシューティングでは -ano が基本です。
ポート 8080 を検索したら 8 や 80 が使っているポートもヒットしてしまいます。
findstr で単純に “8080” を検索すると、外部アドレスの 8080 も拾ってしまいます。":8080 "(コロン + ポート番号 + スペース)のように絞り込むと誤検知を防げます。それでも不安なら findstr /r ":8080[^0-9]" という正規表現パターンも使えます。
CLOSE_WAIT が大量に発生しています。どうすればいいですか?
CLOSE_WAIT は、相手(クライアント)から接続終了(FIN)を受け取ったが、こちら(サーバー側アプリ)がまだソケットを閉じていない状態です。アプリがソケットを適切に close() していないことが原因で、増え続ける場合はアプリのバグです。netstat -ano で対象プロセスの PID を特定してアプリを再起動するか、根本的にはアプリ側でソケットを適切に閉じる修正が必要です。
バッチファイルで netstat の出力をパースするのが難しいです。
netstat の出力は環境(日本語版 Windows など)によって列幅やヘッダー表記が変わることがあります。-n オプションで数値表示にして findstr で絞り込み、for /f で列を分割するのが基本です。より高度な処理が必要なら PowerShell の Get-NetTCPConnection を使うと、オブジェクト形式で処理できるため日本語環境に左右されません。
netstat を定期実行してポートを監視したいのですが、タスクスケジューラで実行するとうまく動きません。
タスクスケジューラからバッチを実行する場合、ログファイルのパスを絶対パスで指定し、ログフォルダが存在するか事前にチェックする処理(if not exist mkdir)を入れてください。また、タスクの設定で「最上位の特権で実行する」にチェックを入れると netstat -b のような管理者権限が必要な操作も実行できます。
0.0.0.0 でリッスンしているポートはどこからでもアクセスできますか?
0.0.0.0 はすべてのネットワークインターフェースで待ち受けることを意味します。ただし実際にアクセスできるかどうかは Windows ファイアウォールや上位のネットワーク機器の設定によります。DB サービス(MySQL の 3306 など)が 0.0.0.0 でリッスンしている場合、ファイアウォールで外部からのアクセスを遮断しているか確認することをおすすめします。