释放OS X上死进程使用的UDP端口

kto*_*orn 28 sockets macos osx-elcapitan

我在OS X 10.11.6上并尝试运行一个通常8008在启动时侦听UDP端口的程序.

此程序通常还会在其操作期间生成几个辅助子进程,但该端口由父进程绑定.

不幸的是,退出程序时,即使程序(父级+子级)不再存在,有时端口仍保持打开状态.

当发生这种情况时,如果我再次尝试运行该程序,它自然会失败并出现EADDRINUSE错误,在这些情况下无论我尝试什么,我发现的唯一解决方案是重启机器.

我很难相信我不能在没有重启的情况下释放端口.

这是我到目前为止运行的一些诊断(我运行和运行所有这些sudo):

查找使用端口的进程8008lsof:

$ lsof -i -n -P | grep UDP | grep 8008
Run Code Online (Sandbox Code Playgroud)

但令人惊讶的是,没有任何结果.

但是,我有更多运气netstat:

$ netstat -tulnvp udp | grep 8008
udp4  0  0  *.8008    *.*    196724   9216  47205   0
Run Code Online (Sandbox Code Playgroud)

所以,端口确实是绑定的,罪魁祸首是pid 47205,但是:

$ ps aux | grep 47205
Run Code Online (Sandbox Code Playgroud)

不归还任何东西.对于PID 4720647207(最确定的是分配给孩子们的PID)也是如此.我还尝试过grep(程序名称,路径等)的其他变体.

我还寻找任何流程报告47205作为其父级:

$ ps -axo pid,ppid,command | grep 47205
Run Code Online (Sandbox Code Playgroud)

所以孩子们的过程也显然已经死了.

无法做kill任何事情,我尝试了SIGHUP launchd,希望它可以删除任何僵尸子进程:

$ sudo kill HUP 1
$ sudo kill -s HUP 1
Run Code Online (Sandbox Code Playgroud)

但是,唉,netstat仍然显示港口的界限.

最后,我尝试重启loopback接口:

$ sudo ifconfig lo down
$ sudo ifconfig lo up
Run Code Online (Sandbox Code Playgroud)

但是,再一次,没有效果.

自程序上次运行以来我已经等了好几个小时,所以我很确定现在已经发生任何超时,但是端口不会被释放.

关于如何在不重启的情况下强行释放端口的任何想法?

编辑:

  • 有问题的程序是电子包装的Patchwork.
  • 这个问题源于这个github问题.
  • 虽然找到一个解决方案/错误修复,以防止问题首先出现是理想的,我也有兴趣从终端手动关闭该端口的方法

Min*_*ius -1

确实可以手动关闭端口而无需重新启动机器。在各种 Linux 版本上,这通常是通过发出伪装成进程的系统调用(例如close(fd)套接字文件描述符上的系统调用)来使用 GDB 来完成的。

其过程:

  • 打开 UDP 端口:netcat -u 127.0.0.1 33333
  • 检查 UDP 端口:netstat -npu (u for UDP),这将为您提供占用该端口的 PID。
  • 运行:lsof -np $pid让 PID 获取套接字的文件描述符。
  • 然后为该 PID 运行 GDB:sudo gdb -p 73599
  • 当在GDB内部运行时call close(file_descriptor)

例子:

COMMAND   PID  USER   FD   TYPE   DEVICE SIZE/OFF     NODE NAME
netcat  73599 ubunt  cwd    DIR  259,2     4096 13895497 /home/ubunt/Downloads
netcat  73599 ubunt  rtd    DIR  259,2     4096        2 /
netcat  73599 ubunt  txt    REG  259,2    31248 28835938 /bin/nc.openbsd
netcat  73599 ubunt  mem    REG  259,2    47600 23990813 /lib/x86_64-linux-gnu/libnss_files-2.23.so
netcat  73599 ubunt  mem    REG  259,2  1868984 23990714 /lib/x86_64-linux-gnu/libc-2.23.so
netcat  73599 ubunt  mem    REG  259,2   101200 23990866 /lib/x86_64-linux-gnu/libresolv-2.23.so
netcat  73599 ubunt  mem    REG  259,2    81040 23990710 /lib/x86_64-linux-gnu/libbsd.so.0.8.2
netcat  73599 ubunt  mem    REG  259,2   162632 23990686 /lib/x86_64-linux-gnu/ld-2.23.so
netcat  73599 ubunt    0u   CHR 136,19      0t0       22 /dev/pts/19
netcat  73599 ubunt    1u   CHR 136,19      0t0       22 /dev/pts/19
netcat  73599 ubunt    2u   CHR 136,19      0t0       22 /dev/pts/19
netcat  73599 ubunt    3u  IPv4 22142418    0t0      UDP 127.0.0.1:45255->127.0.0.1:33333
Run Code Online (Sandbox Code Playgroud)

然后是GDB:

$sudo gdb -p 73599
...
(gdb) call close(3u)
$1 = 0
Run Code Online (Sandbox Code Playgroud)

您将看到该端口不再存在:

ubunt@ubunt-MS-7A94:~$ lsof -np 73599
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
netcat  73599 ubunt  cwd    DIR  259,2     4096 13895497 /home/ubunt/Downloads
netcat  73599 ubunt  rtd    DIR  259,2     4096        2 /
netcat  73599 ubunt  txt    REG  259,2    31248 28835938 /bin/nc.openbsd
netcat  73599 ubunt  mem    REG  259,2    47600 23990813 /lib/x86_64-linux-gnu/libnss_files-2.23.so
netcat  73599 ubunt  mem    REG  259,2  1868984 23990714 /lib/x86_64-linux-gnu/libc-2.23.so
netcat  73599 ubunt  mem    REG  259,2   101200 23990866 /lib/x86_64-linux-gnu/libresolv-2.23.so
netcat  73599 ubunt  mem    REG  259,2    81040 23990710 /lib/x86_64-linux-gnu/libbsd.so.0.8.2
netcat  73599 ubunt  mem    REG  259,2   162632 23990686 /lib/x86_64-linux-gnu/ld-2.23.so
netcat  73599 ubunt    0u   CHR 136,19      0t0       22 /dev/pts/19
netcat  73599 ubunt    1u   CHR 136,19      0t0       22 /dev/pts/19
netcat  73599 ubunt    2u   CHR 136,19      0t0       22 /dev/pts/19
Run Code Online (Sandbox Code Playgroud)

GDB 可用于 MacOS,因此它也应该适合您的情况。

  • 这个答案并没有它应有的帮助。它关闭 netcat 端口,而不是卡住的进程。尝试 gdb 到卡住的进程不起作用,并且原始侦听套接字仍然打开。 (2认同)