8

在从 bash 翻译一些脚本时,我遇到了许多使用 netstat -an 来查找我们的服务是否正在侦听的情况。虽然我知道我可以只使用 subprocess.call 或其他甚至 popen 我宁愿使用 pythonic 解决方案,所以我没有利用我们正在运行的 unix 环境。

从我读过的内容来看,套接字模块应该有一些东西,但我没有看到任何检查监听端口的东西。可能是我不理解一个简单的技巧,但到目前为止,我知道如何连接到套接字,并编写一些东西让我知道连接何时失败。但不一定我找到了专门检查端口以查看其是否正在侦听的东西。

有任何想法吗?

4

6 回答 6

11

尝试连接怎么样...

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = s.connect_ex(('127.0.0.1', 3306))

if result == 0:
    print('socket is open')
s.close()
于 2011-09-15T20:13:14.140 回答
6

我知道这个问题很老,但我为初学者写这个。如果要识别系统上的侦听端口,可以使用下面的代码。

from socket import *

Port = 0 #First port.
while Port <= 65535: #Port 65535 is last port you can access.
    try:
        try:
            Socket = socket(AF_INET, SOCK_STREAM, 0) #Create a socket.
        except:
            print("Error: Can't open socket!\n")    
            break #If can't open socket, exit the loop.
        Socket.connect(("127.0.0.1", Port)) #Try connect the port. If port is not listening, throws ConnectionRefusedError. 
        Connected = True
    except ConnectionRefusedError:
        Connected = False       
    finally:
        if(Connected and Port != Socket.getsockname()[1]): #If connected,
            print("{}:{} Open \n".format("127.0.0.1", Port)) #print port.
        Port = Port + 1 #Increase port.
        Socket.close() #Close socket.
于 2016-06-22T12:44:30.663 回答
3

在 Linux 上,我们可以使用 strace 来查看 netstat -ln 正在从 /proc 文件系统读取和解析各种值。

$ strace netstat -ln 2>&1| grep '/proc'
open("/proc/net/tcp", O_RDONLY)         = 3
open("/proc/net/tcp6", O_RDONLY)        = 3
open("/proc/net/udp", O_RDONLY)         = 3
open("/proc/net/udp6", O_RDONLY)        = 3
open("/proc/net/raw", O_RDONLY)         = 3
open("/proc/net/raw6", O_RDONLY)        = 3
open("/proc/net/unix", O_RDONLY)        = 3
open("/proc/net/ipx/socket", O_RDONLY)  = -1 ENOENT (No such file or directory)
open("/proc/net/ipx", O_RDONLY)         = -1 ENOENT (No such file or directory)
open("/proc/net/ax25", O_RDONLY)        = -1 ENOENT (No such file or directory)
open("/proc/net/x25", O_RDONLY)         = -1 ENOENT (No such file or directory)
open("/proc/net/x25", O_RDONLY)         = -1 ENOENT (No such file or directory)
open("/proc/net/nr", O_RDONLY)          = -1 ENOENT (No such file or directory)

所以你可以从 Python 中读取这些文件并提取你需要的数据。

$ cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 8190 1 00000000 300 0 0 2 -1
   1: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 6458 1 00000000 300 0 0 2 -1
   2: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 10425 1 00000000 300 0 0 2 -1
   3: 8D0BA8C0:8801 689255D1:01BB 01 00000000:00000000 00:00000000 00000000  1000        0 1680975 1 00000000 24 4 16 6 -1
   4: 8D0BA8C0:D142 97E67D4A:01BB 06 00000000:00000000 03:000012E8 00000000     0        0 0 3 00000000
   5: 8D0BA8C0:D1A1 96E67D4A:01BB 01 00000000:00000000 00:00000000 00000000  1000        0 1672130 1 00000000 24 4 18 5 -1
   6: 8D0BA8C0:D148 97E67D4A:01BB 01 00000000:00000000 00:00000000 00000000  1000        0 1679875 1 00000000 24 4 20 5 -1

监听套接字的远程地址为 00000000:0000

地址:端口对是十六进制的。请参阅:*如何将每个 /proc/net/tcp 条目与每个打开的套接字匹配?

您可以与 /proc//fd 交叉引用。例如,sshd 在我的笔记本电脑上运行。

$ cat /var/run/sshd.pid
522

$ sudo ls -l /proc/522/fd
total 0
lrwx------ 1 root root 64 2011-09-15 21:32 0 -> /dev/null
lrwx------ 1 root root 64 2011-09-15 21:32 1 -> /dev/null
lrwx------ 1 root root 64 2011-09-15 21:32 2 -> /dev/null
lrwx------ 1 root root 64 2011-09-15 21:32 3 -> socket:[6456]
lrwx------ 1 root root 64 2011-09-15 21:32 4 -> socket:[6458]

套接字 6456 对应于 /proc/net/tcp 的第二行中列出的 inode 6458。

所以你可以从 proc 获取所有这些信息,但你最终可能会重新发明 netstat -lntp

于 2011-09-15T21:35:10.013 回答
3
import psutil
connections = psutil.net_connections()

参考: https ://stackoverflow.com/a/6244270

于 2020-06-22T12:05:21.480 回答
2

您可以尝试连接到有问题的端口,或者模拟netstat.

执行后者将是特定于操作系统的。在 Linux 上,您可以检查/proc/net/tcp. 它看起来像这样:

  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:C809 00000000:0000 0A 00000000:00000000 00:00000000 00000000   117        0 8381 1 ffff8802f22a8000 300 0 0 2 -1                      
   1: 00000000:16CC 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1026        0 14336 1 ffff8802f2249440 300 0 0 2 -1                     
   2: 00000000:006F 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7876 1 ffff8802f2248000 300 0 0 2 -1                      
   3: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 8163 1 ffff8802f3578000 300 0 0 2 -1                      
   4: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 981582 1 ffff8800d7a53600 300 0 0 2 -1                    
   5: 00000000:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 9129 1 ffff8802edc886c0 300 0 0 2 -1                      
   6: 00000000:021A 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 9016 1 ffff8802edc88000 300 0 0 2 -1                      
   7: 00000000:2B1C 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1026        0 783709 1 ffff8803119cca40 300 0 0 2 -1                    
   8: 00000000:977C 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 24292 1 ffff8802f224e540 300 0 0 2 -1                     

您正在寻找("status") 列0A中的行。--等st中冒号后面的数字是 TCP 端口号(十六进制),在该端口号上有侦听进程。local_addressC80916CC

于 2011-09-15T20:13:17.843 回答
0

我知道我迟到了几年,但现有的答案都不够好。

我是谷歌,正在为完全相同的问题寻找一个好的、优雅的解决方案,但已经发布的答案似乎都不够好,相反,我找到了自己的解决方案,我想在这里发布它们以帮助未来被重定向到这里的读者谷歌。

大多数操作系统都有一个名为 的可执行文件netstat,可用于捕获侦听端口,在此示例中,我使用的是 Windows 10 和 Python 3.9.6 x64,但这是用 Python 编写的,因此您可以轻松地将其调整为您自己的用例。

由于所有名称解析,使用plainnetstat将非常慢,使用netstat -n将成倍地加快,因为它不会浪费时间解析名称。

在 Python 3.9.6 中,用于subproces.run()运行 os 调用,并用于capture_output=True捕获 stdout,然后使用.stdout结果进程的属性获取输出,结果为二进制形式,用于.decode()获取字符串。

然后输出应如下所示:


Active Connections

  Proto  Local Address          Foreign Address        State
  TCP    10.70.0.6:1134         40.83.240.146:443      ESTABLISHED
  TCP    10.70.0.6:1283         117.18.232.200:443     CLOSE_WAIT
  TCP    10.70.0.6:1609         198.252.206.25:443     ESTABLISHED
  TCP    10.70.0.6:1621         198.252.206.25:443     ESTABLISHED
  TCP    10.70.0.6:1691         74.125.24.102:443      ESTABLISHED
  TCP    10.70.0.6:1727         142.251.10.94:443      ESTABLISHED
  TCP    10.70.0.6:1728         142.251.10.100:443     TIME_WAIT
  TCP    10.70.0.6:1731         172.217.194.119:443    TIME_WAIT
  TCP    10.70.0.6:1735         74.125.24.113:443      ESTABLISHED
  TCP    10.70.0.6:1787         104.244.42.130:443     ESTABLISHED
  TCP    10.70.0.6:1796         151.101.1.69:443       ESTABLISHED
  TCP    10.70.0.6:1797         151.101.196.193:443    ESTABLISHED
  TCP    10.70.0.6:1799         74.125.130.132:443     ESTABLISHED
  TCP    10.70.0.6:1800         198.252.206.25:443     ESTABLISHED
  TCP    10.70.0.6:1805         3.209.45.230:443       TIME_WAIT
  TCP    10.70.0.6:1806         3.219.6.82:443         TIME_WAIT
  TCP    10.70.0.6:1807         3.211.239.214:443      TIME_WAIT
  TCP    10.70.0.6:1816         140.82.113.26:443      ESTABLISHED
  TCP    127.0.0.1:1053         127.0.0.1:1055         ESTABLISHED
  TCP    127.0.0.1:1055         127.0.0.1:1053         ESTABLISHED
  TCP    127.0.0.1:1057         127.0.0.1:1058         ESTABLISHED
  TCP    127.0.0.1:1058         127.0.0.1:1057         ESTABLISHED
  TCP    127.0.0.1:1061         127.0.0.1:1062         ESTABLISHED
  TCP    127.0.0.1:1062         127.0.0.1:1061         ESTABLISHED
  TCP    127.0.0.1:1763         127.0.0.1:1764         ESTABLISHED
  TCP    127.0.0.1:1764         127.0.0.1:1763         ESTABLISHED
  TCP    127.0.0.1:1766         127.0.0.1:1767         ESTABLISHED
  TCP    127.0.0.1:1767         127.0.0.1:1766         ESTABLISHED
  TCP    127.0.0.1:1810         127.0.0.1:2015         ESTABLISHED
  TCP    127.0.0.1:1811         127.0.0.1:2015         ESTABLISHED
  TCP    127.0.0.1:1820         127.0.0.1:1821         ESTABLISHED
  TCP    127.0.0.1:1821         127.0.0.1:1820         ESTABLISHED
  TCP    127.0.0.1:1829         127.0.0.1:9614         SYN_SENT
  TCP    127.0.0.1:2015         127.0.0.1:1810         ESTABLISHED
  TCP    127.0.0.1:2015         127.0.0.1:1811         ESTABLISHED
  TCP    127.0.0.1:14845        127.0.0.1:14846        ESTABLISHED
  TCP    127.0.0.1:14846        127.0.0.1:14845        ESTABLISHED
  TCP    127.0.0.1:15004        127.0.0.1:15005        ESTABLISHED
  TCP    127.0.0.1:15005        127.0.0.1:15004        ESTABLISHED
  TCP    127.0.0.1:15013        127.0.0.1:15014        ESTABLISHED
  TCP    127.0.0.1:15014        127.0.0.1:15013        ESTABLISHED
  TCP    127.0.0.1:16976        127.0.0.1:16977        ESTABLISHED
  TCP    127.0.0.1:16977        127.0.0.1:16976        ESTABLISHED
  TCP    127.0.0.1:19278        127.0.0.1:19279        ESTABLISHED
  TCP    127.0.0.1:19279        127.0.0.1:19278        ESTABLISHED
  TCP    127.0.0.1:19280        127.0.0.1:19281        ESTABLISHED
  TCP    127.0.0.1:19281        127.0.0.1:19280        ESTABLISHED
  TCP    127.0.0.1:20695        127.0.0.1:21385        ESTABLISHED
  TCP    127.0.0.1:21385        127.0.0.1:20695        ESTABLISHED
  TCP    127.0.0.1:23460        127.0.0.1:23461        ESTABLISHED
  TCP    127.0.0.1:23461        127.0.0.1:23460        ESTABLISHED
  TCP    127.0.0.1:23462        127.0.0.1:23463        ESTABLISHED
  TCP    127.0.0.1:23463        127.0.0.1:23462        ESTABLISHED
  TCP    127.0.0.1:28343        127.0.0.1:28344        ESTABLISHED
  TCP    127.0.0.1:28344        127.0.0.1:28343        ESTABLISHED
  TCP    127.0.0.1:30307        127.0.0.1:30308        ESTABLISHED
  TCP    127.0.0.1:30308        127.0.0.1:30307        ESTABLISHED
  TCP    127.0.0.1:30311        127.0.0.1:30312        ESTABLISHED
  TCP    127.0.0.1:30312        127.0.0.1:30311        ESTABLISHED
  TCP    127.0.0.1:30313        127.0.0.1:30314        ESTABLISHED
  TCP    127.0.0.1:30314        127.0.0.1:30313        ESTABLISHED
  TCP    127.0.0.1:30316        127.0.0.1:30317        ESTABLISHED
  TCP    127.0.0.1:30317        127.0.0.1:30316        ESTABLISHED
  TCP    127.0.0.1:30319        127.0.0.1:30320        ESTABLISHED
  TCP    127.0.0.1:30320        127.0.0.1:30319        ESTABLISHED
  TCP    127.0.0.1:30584        127.0.0.1:30585        ESTABLISHED
  TCP    127.0.0.1:30585        127.0.0.1:30584        ESTABLISHED
  TCP    127.0.0.1:30623        127.0.0.1:30624        ESTABLISHED
  TCP    127.0.0.1:30624        127.0.0.1:30623        ESTABLISHED
  TCP    127.0.0.1:49669        127.0.0.1:49670        ESTABLISHED
  TCP    127.0.0.1:49670        127.0.0.1:49669        ESTABLISHED
  TCP    127.0.0.1:49690        127.0.0.1:49692        ESTABLISHED
  TCP    127.0.0.1:49692        127.0.0.1:49690        ESTABLISHED
  TCP    [::1]:3306             [::1]:23468            ESTABLISHED
  TCP    [::1]:3306             [::1]:23469            ESTABLISHED
  TCP    [::1]:23468            [::1]:3306             ESTABLISHED
  TCP    [::1]:23469            [::1]:3306             ESTABLISHED

使用splitlines()获取单独的行,然后使用列表切片来获取实际表的内容,这里我们使用索引4,然后使用正则表达式拆分对空白字符进行拆分,然后使用索引获取本地地址值,最后使用字符串拆分在冒号和索引上获取端口。

编码:

import psutil
import re
import subprocess

def get_active_ports():
    process = subprocess.run(['netstat', '-n'], capture_output=True)
    report = process.stdout.decode().splitlines()
    ports = set()
    for i in report[4:]:
        ports.add(re.split(':(?!.*:)', re.split('\s+', i)[2])[1])
    return ports

或单线:

set([re.split(':(?!.*:)', re.split('\s+', i)[2])[1] for i in subprocess.run(['netstat', '-n'], capture_output=True).stdout.decode().splitlines()[4:]])

表现:

In [119]: %timeit set([re.split(':(?!.*:)', re.split('\s+', i)[2])[1] for i in subprocess.run(['netstat', '-n'], capture_output=True).stdout.decode().splitlines()[4:]])
11.4 ms ± 315 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

或者,或者,psutil有一种.net_connections()方法,您可以从中获取端口。

只需使用集合理解来获取输出:

set(i.laddr.port for i in psutil.net_connections())

这种方法比前一种方法快得多:

In [103]: %timeit set(i.laddr.port for i in psutil.net_connections())
893 µs ± 13.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
于 2021-08-19T09:48:41.030 回答