我如何杀死一个死了但正在倾听的进程?


48

我正在开发一个监听端口3000的应用程序。显然,有一个实例仍在监听该端口,因为无论何时启动它,它都无法创建监听器(C#,TcpListener,但这无关紧要),因为该端口已经存在采取。

现在,该应用程序在任务管理器中不存在,因此我试图找到它的PID并杀死它,这导致了有趣的结果:

C:\Users\username>netstat -o -n -a | findstr 0.0:3000
   TCP    0.0.0.0:3000           0.0.0.0:0              LISTENING       3116

C:\Users\username>taskkill /F /PID 3116
ERROR: The process "3116" not found.

我以前从未见过这种行为,并且认为这很有趣,可以看看是否有人可以解决。

更新:我启动了Process Explorer,并搜索了3000,发现了这一点:

<Non-existent Process>(3000): 5552

我右键单击它,然后选择“关闭手柄”。它不再位于Process Explorer中,但仍显示在netstat中,并且仍使应用程序无法启动侦听器。

更新2:找到Windows的TCPView,该过程显示为"<non-existent>"。像使用CurrPorts一样,当我尝试关闭此工具中的连接时也没有任何反应。


通过杀死病人可以治愈疾病,但是如果重新启动计算机,它会停止吗?
Xantec

2
实际上,注销并再次登录就足够了,但是我现在设法重现了它,所以我仍然想找到一个更好的解决方案...
Srekel 2010年

检查此处列出的任何程序是否有 帮助
Sathyajith Bhat

1
在当前版本的TCPView 3.05中,<non-exsitent>进程的上下文菜单中的“关闭连接”成功关闭了连接并释放了端口。
Ventzy Kunev

Answers:


13

为了避免在套接字上无休止的等待,您的程序应使用带有SO_REUSEADDR和SO_RCVTIMEO参数的setsockopt函数

SO_REUSEADDR : Allows the socket to be bound to an address that is already in use.
SO_RCVTIMEO : Sets the timeout, in milliseconds, for blocking receive calls. 

1
这对这个特定问题(通过死进程侦听套接字)是否有帮助?
rustyx

12

我们遇到了同样的问题,并使用Microsoft Sysinternals的Process Explorer查找不再存在的进程ID。

事实证明,该流程已被多个DrWatson流程引用。杀死这些进程释放​​了端口。DrWatson用于向Microsoft发送内存转储,这花费了几个小时,因为崩溃的进程当时占用了数十GB的内存。


7

我认为您应该尝试一下CurrPorts

CurrPorts是网络监视软件,它显示本地计算机上所有当前打开的TCP / IP和UDP端口的列表。对于列表中的每个端口,还将显示有关打开该端口的进程的信息,包括进程名称,进程的完整路径,进程的版本信息(产品名称,文件描述等),时间该过程已创建,并且创建了该用户。

此外,CurrPorts允许您关闭不需要的TCP连接,终止打开端口的进程,并将TCP / UDP端口信息保存到HTML文件,XML文件或制表符分隔的文本文件中。

CurrPorts还会自动用未识别的应用程序拥有的粉红色可疑TCP / UDP端口标记(没有版本信息和图标的应用程序)

替代文字


4
它显示在列表中进程名称“ System”下。我尝试右键单击该项目以强制关闭端口,但没有任何反应。
斯雷克尔2010年

7

可能的问题是您的进程已经启动了另一个(子)进程,该进程继承了套接字句柄,并且仍在运行。

有多种方法可以防止这种情况发生,例如:ProcessStartInfo.UseShellExecute = true;


1
谢谢,这是一个很好的。我当时是subprocess.call(..., cwd=..., shell=True)在python网络服务器中以应用启动器的身份打电话的,结果证明我必须杀死所有这些子进程才能释放套接字。奇怪的是,我正在使用shell = True。这使我烦恼了好久了。
丹尼尔·F

我不认为使用外壳会导致这种行为。如果你想终止所有子进程,当父母去世,我认为正确的方法是创建一个作业对象JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE标志,添加每个子进程AssignProcessToJobObject,并允许把手接近自然父进程退出时。
qris


1

尝试在netstat命令上抛出“ -b”标志。它将告诉您正在使用端口的可执行文件的名称。然后在任务管理器中找到该进程并在那里杀死它。如果那不起作用,请发布将端口保持打开状态的可执行文件。


我目前无法重现它,但是我很确定,由于尝试查找进程名称的所有其他尝试(和工具)都失败了,因此netstat也无法做到这一点。
斯雷克尔2010年

1

需要提及的术语萦绕这里。

可以在http://msdn.microsoft.com/zh-cn/library/ms739165.aspx中找到详细信息

简而言之:有一个选项告诉套接字系统,即使存在未发送的数据,即使在套接字关闭后也要保持套接字打开。

在C#应用程序中,您可以通过Socket.SetSocketOption指定任何相关选项:http : //msdn.microsoft.com/zh-cn/library/1011kecd.aspx

由于提到的所有内容都与发送和客户端有关,但是我们在工作中遇到了类似的问题,因此一些进一步的搜索显示,可以为侦听器指定延迟选项,如以下示例所示:http : //msdn.microsoft.com /library/system.net.sockets.tcplistener.server.aspx

一些同事谈到应用程序终止/关闭大约两分钟后操作系统保留的端口。鉴于此,很有趣的是,在一定时间后,该端口是否仍处于保留状态。


端口保持打开状态的时间长得多(不记得多久了,但可能要等一个小时才能放弃并重新启动)。
斯雷克尔2010年

我不确定linger选项是否与此特定情况相关,因为它似乎仅指定在调用CloseSocket之后应该发生的事情。由于我要终止该应用程序,因此我怀疑函数是否被称为(?)。
斯雷克尔2010年

1

我也遇到这个问题。终于我找到了原因。这是由于主进程在c / c ++中由popen调用了子进程引起的。但是在调用pclose之前主进程崩溃/关闭。然后,端口将处理仍在运行的主进程,并继续侦听它。


1
我在ServerFault上发现以下答案很有帮助:serverfault.com/a/273727/8856
Harriv 2012年

1

我在xdebug中遇到了同样的问题,它使9000端口保持打开状态。

我设法使用“ taskkill / pid xxxx”关闭了cmd。

可以使用“ netstat -o”来检索使用端口的进程的pid。

我的配置是赢7家庭高级版。


1

我有同样的问题,并通过以下方法解决了问题:

  • 用以下方式找到PID netstat -o
  • 用XP杀死它

有趣的是,netstat有时可以返回pid,但不能返回相应的可执行文件名称!


1

如果死进程启动了一个或多个子进程,则可能导致此问题。如果

BOOL WINAPI CreateProcess(
_In_opt_    LPCTSTR               lpApplicationName,
_Inout_opt_ LPTSTR                lpCommandLine,
_In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_        BOOL                  bInheritHandles,
_In_        DWORD                 dwCreationFlags,
_In_opt_    LPVOID                lpEnvironment,
_In_opt_    LPCTSTR               lpCurrentDirectory,
_In_        LPSTARTUPINFO         lpStartupInfo,
_Out_       LPPROCESS_INFORMATION lpProcessInformation
);

用于启动子进程,它取决于继承句柄的值,因此

bInheritHandles = false 

如果父进程已停止并且客户端进程仍在运行,则Windows将不会阻止该端口。


1

当根本原因是某些子进程创建了继承端口的子进程时,父进程崩溃了,而子进程仍持有该端口时,也遇到了类似的问题。解决方案是确定子进程仍在运行并停止它。在此示例中,不存在的过程PID为7336

> wmic process get processid,parentprocessid | findstr/i 7336
7336             23828

要停止此过程:

> taskkill /f /pid 23828

这就解决了问题。


0

我不认为您已安装防火墙(或尝试过任何Windows网络服务)?

一些防火墙表现出这种行为,并且可以保持端口开放。

如果确实有一个,请尝试将其禁用,然后启动程序并关闭它,然后看看会发生什么。


不幸的是,这并不是真正的选择,因为我无法控制计算机上的防火墙。
斯雷克尔2010年

@Srekel-它是什么防火墙?当您遇到问题时,我个人认为是造成问题的原因。
William Hilsum 2010年

0

由于您的进程被列为系统,因此很可能可以在“系统”命令提示符下将其终止。系统帐户具有比普通管理员更多的特权。

您可以通过为cmd.exe计划任务来获取“系统” cmd.exe(计划程序以System身份运行):

at 15:23 /interactive "cmd.exe" 

在不久的将来将时间更改为某些时间。确保您也在计算机控制台上(如果您在常规的终端服务器会话中,则不会看到新的cmd.exe。mstsc登录到控制台)。我想还有其他方法可以做到这一点,但这在过去对我有用。


0

我有同样的问题。该进程在崩溃时进行调试,并且仍然有一个处于挂起状态的vsjitdebugger.exe进程徘徊,这显然是指正在调试的进程。杀死vsjitdebugger.exe进程即可解决此问题。


0

TCPView和Process Explorer的混合使用对我有用;)我首先查看了使用TCPView中端口的进程ID。在Process Explorer中隔离该进程,并使用Process Explorer终止该进程。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.