はじめに
二重起動しているわけではないのに port 50000 is already in use
というメッセージが表示して RoboServerが終了してしまう。
実は1年半前に同じ内容でブログを書いていたのも忘れて再度書いてます。前回は Management Console
で今回は RoboServer
という違いはあるものの、Qiitaって、記事を増やすほどに検索性というか、後になって見落とす率高いですよね。。 Zenn に引っ越そうかな。と思ってます。
以下、LLMとの会話で得た情報も織り交ぜて記載します。
ポートの利用状況調査
管理者権限でコマンドプロンプトを起動して、以下のコマンドを実行しましょう。
- 管理者モードで実行した場合: システム上のすべてのプロセスに関するPID情報を取得できます。これにより、どのプロセスがどのポートを使用しているかを正確に特定できます。
- 通常のユーザーモードで実行した場合: 通常、自分が所有するプロセスや、一部の共通のシステムプロセスに関するPID情報しか表示されません。他のユーザーが実行しているプロセスや、管理者権限で実行されている重要なシステムプロセスについては、PIDが表示されなかったり、「PIDが見つかりません」のような表示になったりすることがあります。これは、セキュリティ上の理由から、通常のユーザーが他のプロセスの詳細情報にアクセスできないようにするためです。
netstat -aon | findstr :50080
このコマンドは、すべてのアクティブな接続とリスニングポート (-a
) を数値形式 (-n
) で表示し、それらに関連付けられているプロセスのID (PID) (-o
) も表示します。
findstr :50080
でポート番号が50080の行に絞り込みます。
C:\Users\robo>netstat -aon | findstr :50080
TCP 127.0.0.1:53480 127.0.0.1:50080 SYN_SENT 31708
TCP 172.19.48.1:50080 0.0.0.0:0 LISTENING 4684
TCP [::1]:53473 [::1]:50080 SYN_SENT 31708
表示される項目は順番に以下を示します。
- プロトコル (Proto):
- TCP または UDP。
- ローカルアドレス (Local Address):
- 自分のPCのIPアドレスとポート番号。0.0.0.0:50080は、任意のIPアドレスでポート50080をリッスンしている状態を示します。[::]:50080 はIPv6の場合です。
- 外部アドレス (Foreign Address):
- 接続相手のIPアドレスとポート番号。0.0.0.0:0や[::]:0は、リスニング状態(まだ接続がない状態)を示します。
- 状態 (State):
- 現在の接続の状態。LISTENINGは接続待ちの状態です。
- PID (Process ID):
- その接続またはリスニングポートを使用しているプロセスのID。上記の例では 1234 がそのプロセスIDです。
タスクマネージャーでプロセスを特定
特定したプロセスのPIDが分かったら、タスクマネージャーを開き、「詳細」タブに切り替えます。PID列を確認し、該当するPIDのプロセスを選択して右クリックから「サービスの表示」を選択します。
例題:svchost.exe
編
svchost.exe
がポート50080を使用していることが特定できた場合
svchost.exe
は、Windowsサービスを実行するための汎用的なホストプロセスであり、一つのsvchost.exe
プロセスの中で複数のサービスが動作しているのが一般的です。そのため、タスクマネージャーにはたくさんのsvchost.exe
が起動しているように見えます。
特定のsvchost.exe
プロセスを強制終了させると、そのプロセスがホストしている複数のWindowsサービスがすべて強制的に停止してしまいます。これは、思わぬシステム機能の停止や不安定化を招く可能性があるため、安易な強制終了は推奨されません。
重要なのは、その50080ポートを使用しているsvchost.exe
が、どのWindowsサービスのグループをホストしているのかを特定することです。
対象の svchost.exe
がホストするサービスを特定する方法
-
タスクマネージャーで確認する:
- タスクマネージャーを開き、「詳細」タブに切り替えます。
- PID(プロセスID)列を表示させ、ポート50080を使用している
svchost.exe
のPIDを探します。 - その
svchost.exe
を右クリックし、「サービスの表示」を選択します。 - すると、その
svchost.exe
プロセスがホストしているサービスの一覧が表示されます。
-
コマンドプロンプトまたはPowerShellで確認する:
管理者権限でコマンドプロンプトまたはPowerShellを開き、以下のコマンドを実行します。[特定したPID]
の部分は、ポート50080を使用しているsvchost.exe
の実際のPIDに置き換えてください。# コマンドプロンプトの場合 tasklist /svc /fi "PID eq [特定したPID]" # PowerShellの場合 Get-CimInstance win32_service -Filter "ProcessId = [特定したPID]"
これらのコマンドでも、そのPIDの
svchost.exe
がホストしているサービス名の一覧が表示されます。
ポートを使用しているサービスを特定し、安全にポートを解放する
特定したサービスの一覧の中に、ポート50080を使用していそうなサービス(例:Web関連のサービス、リモート管理サービス、特定のアプリケーションサービスなど)や、BizRobo!に関連しそうなサービスがないか確認します。
もし、そのサービスがポート50080をリッスンしていることが明確、またはBizRobo!に関連するサービスであることが分かった場合、以下の手順でサービスを再起動または停止することを試みます。
-
対象サービスの特定: 上記の方法で、ポート50080を使用している
svchost.exe
がホストしているサービスの中から、原因と思われるサービスを特定します。 -
サービスの再起動: 特定したサービス名を控えておき、「サービス」アプリケーション(
services.msc
をファイル名を指定して実行、または管理ツールからアクセス)を開きます。- 該当するサービスを見つけ、右クリックして「再起動」を選択します。これにより、サービスが一時的に停止し、再度起動します。正常に再起動できれば、ポートが解放される可能性があります。
- サービスの停止: 再起動してもポートが解放されない、あるいは再起動ができない場合は、右クリックして「停止」を選択します。サービスが停止すれば、ポートは解放されます。サービスを停止した場合は、BizRobo!の起動後に必要に応じてサービスを再度開始してください。
強制終了について
サービスを特定して再起動や停止を試みてもポートが解放されない、またはどのサービスが原因か特定できないがどうしてもBizRobo!を起動したい、という場合の最終手段として、対象のsvchost.exe
プロセスを強制終了させることは可能です。
ただし、前述の通り、そのプロセスがホストしている複数のサービスがすべて強制停止します。これにより、以下のような影響が出る可能性があります。
- システム機能の一部が停止する(例:Windows Update関連、ネットワーク関連、特定のデバイス機能など)。
- システムが不安定になる、エラーが発生する。
- 最悪の場合、OSの再起動が必要になる。
推奨される手順
-
最も推奨: ポートを使用している
svchost.exe
がホストするサービスを特定し、そのサービスを正常に再起動または停止する。 -
次善策: 原因サービスが不明、または正常終了できない場合に限り、影響を理解した上で、対象の
svchost.exe
プロセスを強制終了する。強制終了後は、システムの動作に問題がないか注意深く監視し、必要であればOSを再起動する。 - 最終手段: PC/サーバー自体を再起動する。これが最も確実にポートを解放する方法ですが、業務への影響を確認する必要があります。
まずは、svchost.exe
がホストしているサービスの一覧を確認し、どのサービスがポートを使用している可能性が高いかを見極めることから始めてください。
RoboServer や Management Console で使用するポートを予約設定しておく方法
ここまで記事を読んだ中で、「そもそも事前に予約しておけば、他のプロセスにポートを使用されてしまう事態は防げるのでは?」と思う方も多いでしょう。
実際、ポートを予約しておいても svchost
などのプログラムにより勝手にポートが使われてしまうことはあるのですが、一定の効果は望めるので、以下事前予約の方法もを記述します。
管理者権限でコマンドプロンプトを開いて実行してください。
REM RoboServer用の待ち受けポートの予約
netsh int ipv4 add excludedportrange protocol=tcp startport=50000 ^
numberofports=1 store=persistent
REM Management Console用の待ち受けポートの予約
netsh int ipv4 add excludedportrange protocol=tcp startport=50080 ^
numberofports=1 store=persistent
REM 設定したポートの確認
netsh int ipv4 show excludedportrange protocol=tcp
なぜ予約したはずのポートが使われてしまうのか?
netsh ... add excludedportrange ... store=persistent
コマンドは、TCP/IPのドライバーに対して「このポート番号を、動的ポート(エフェメラルポート)の割り当て対象から除外してください」と指示するものです。動的ポートとは、アプリケーションが特定のポート番号を指定せず「空いているポートを貸してください」とOSに要求した際に割り当てられるポートのことです。
しかし、svchost.exe
の中で動作している特定のWindowsサービスは、これとは異なる動きをします。
サービスの起動タイミング: 重要なWindowsサービスは、システムの起動プロセスのかなり早い段階で起動します。
明示的なポート要求: これらのサービスは「空いているポート」を要求するのではなく、自身の構成に基づいて「ポート番号 50080 を使います」と明示的にOSに要求します。
予約の適用タイミングとの競合: store=persistent
で設定したポート除外設定は、レジストリに書き込まれ、システムの起動時にTCP/IPスタックに読み込まれます。しかし、問題のサービスが起動してポートを確保する方が、この除外設定が全てのプロセスに対して完全に効力を発揮するよりも早い場合があるのです。
つまり、一種の「早い者勝ち」が発生している状態です。svchost
内のサービスが、あなたが作った予約ルールが適用される前に、目的のポートを確保してしまっている可能性が非常に高いです。
by Gemini
まとめ
今回は、Gemini と一緒に問題解決した際のメモ書きをベースに記事を書きました。
AIの出力する回答を無批判に信じることはできないものの、何かに取り組む際のセカンドオピニオンや仮説、検証対象としては非常に有用だなぁと思いますね。