如何获取一个进程正在监听的端口?

23

如何使用Python获取进程正在侦听的端口?已知进程的pid。

5个回答

33

你可以使用psutil

>>> import psutil
>>> p = psutil.Process(2549)
>>> p.name()
'proftpd: (accepting connections)'
>>> p.connections()
[connection(fd=1, family=10, type=1, local_address=('::', 21), remote_address=(), status='LISTEN')]

...要筛选侦听套接字:

>>> [x for x in p.get_connections() if x.status == psutil.CONN_LISTEN]
[connection(fd=1, family=10, type=1, local_address=('::', 21), remote_address=(), status='LISTEN')]
>>>

谢谢。psutil是一个很好的模块。但唯一的问题是使用该模块需要先安装它。而安装psutil需要安装gcc和Python头文件。因此,使用psutil的项目将很难安装。 - mtoloo
psutil需要gcc,因为它包含需要编译的C代码。我不会说安装它很难,特别是在Linux上。例如,在Ubuntu上,你只需要运行"apt-get install python-dev"和"pip install psutil"就可以了。 - Giampaolo Rodolà

24

我的回答分为两部分:

1. 在shell中获取信息

对于第一部分,netstat 可以工作,但我更喜欢使用 lsof,因为它可以用来提取更详细和简洁的列表。要使用的确切选项可能会根据您的操作系统、内核和编译选项而有所不同,但我认为您需要像这样做:

lsof -a -p23819 -i4

在这里,23819 是你要选择的 PID,i4 代表所有 IPv4 套接字(虽然你可能需要使用 i6 来处理 IPv6,具体情况而定)。从那里,你可以通过管道操作使用 grep 命令来选择只监听套接字。

lsof -a -p23819 -i4 | grep LISTEN

(在lsof 4.82版本中,除了使用grep选择监听套接字之外,还可以使用-sTCP:LISTEN标志。然而,在4.78版本中似乎没有这个选项)

2. 从Python调用lsof

您可以使用subprocess模块从Python调用lsof并读取输出,如下所示:

from subprocess import Popen, PIPE
p1 = Popen(['lsof', '-a', '-p23819', '-i4'], stdout=PIPE)
p2 = Popen(["grep", "LISTEN"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

希望这能帮到你!


4

如果您不想解析像netstat或lsof这样的程序的输出,您可以通过/proc文件系统查找文件中的文档。 /proc/<pid>/net/tcp 对您可能特别有用。 当然,这些文件的格式可能会在内核版本之间更改,因此解析命令输出通常被认为更可靠。


1

您可以使用netstat -lnp命令,最后一列将包含pid和进程名称。在Python中,您可以解析此命令的输出。


0

有一件事没有提到。Python中的大多数端口应用程序都需要一个命令行参数。您可以解析/proc/pid/cmdline并解析出端口号。这避免了在具有大量连接的服务器上使用ss或netstat所带来的巨大开销。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接