Python端口检测脚本在Linux上失效:返回全部端口
问题分析与解决方案
你的脚本逻辑存在根本性问题,再加上Windows和Linux的权限机制差异,才导致了不同平台的结果差异:
为什么Linux下会返回全部端口?
Linux系统里,普通用户无权绑定1-1024范围的特权端口——哪怕这些端口根本没有被任何服务占用,bind()调用也会直接失败。你的脚本把所有bind()失败的端口都判定为“开放端口”,自然会把1到65535的所有端口都列出来。而Windows下你大概率是以管理员身份运行脚本,或者系统对普通用户绑定特权端口的限制更宽松,只有真正被占用的端口才会触发bind()失败,所以看起来结果“正常”。
你的脚本逻辑错在哪?
你混淆了「端口被占用(无法绑定)」和「端口开放(有服务监听)」两个完全不同的概念:
bind()失败只能说明当前程序没法用这个端口,可能是端口被其他程序占了,也可能是自身权限不够,不能直接等同于“端口开放”。- 真正的开放端口是指有服务在该端口监听外部连接,正确的检测方式是尝试连接这个端口,而不是绑定它。
修正后的代码
下面是能正确检测本地开放端口的Python脚本:
import socket def scan_local_open_ports(): open_ports = [] # 获取本地IP地址 local_ip = socket.gethostbyname(socket.gethostname()) # 扫描1到65535的所有端口 for port in range(1, 65536): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(0.1) # 设置超时时间,避免扫描耗时过长 try: # connect_ex返回0表示连接成功,即端口有服务监听(开放) if sock.connect_ex((local_ip, port)) == 0: open_ports.append(port) except Exception: pass finally: sock.close() return open_ports if __name__ == "__main__": open_ports = scan_local_open_ports() print(*open_ports, sep=';')
额外说明
connect_ex()方法返回错误码,0代表连接成功,其他值代表连接失败。- 必须设置超时时间,否则扫描全端口会花费大量时间。
- Linux下扫描1-1024的特权端口时,需要以root用户运行脚本,否则会因权限问题无法检测部分端口。
内容的提问来源于stack exchange,提问作者Stuart Dyer
相关产品推荐
相关产品推荐

