In translating some scripts from bash, I am encountering many uses of netstat -an to find if one of our services is listening. While I know I can just use subprocess.call or other even popen I would rather use a pythonic solution so I am not leveraging the unix environment we are operating in.
From what I have read the socket module should have something but I haven't seen anything that checks for listening ports. It could be me not understanding a simple trick, but so far I know how to connect to a socket, and write something that lets me know when that connection failed. But not necessarily have I found something that specifically checks the port to see if its listening.
Any ideas?
How about trying to connect...
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()
I know this question is old, but i write this for begginners. If you want identifying listening ports on your system, you can use the code below.
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.
You could either try connecting to the port in question, or emulate netstat
.
Doing the latter will be OS-specific. On Linux you can examine /proc/net/tcp
. It looks like this:
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
You're looking for lines that have 0A
in the st
("status") column. The numbers after the colon in local_address
-- C809
, 16CC
etc -- are TCP port numbers (in hex) on which there are listening processes.
On Linux we can use strace to see that netstat -ln is reading and parsing various values from the /proc filesystem.
$ 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)
So you can just read those files from Python and extract the data you need.
$ 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
The listening sockets will have remote address 00000000:0000
The address:port pairs are in hex. See: * How can i match each /proc/net/tcp entry to each opened socket?
You could cross reference with /proc//fd. For example, sshd is running on my laptop.
$ 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]
Socket 6456 corresponds to inode 6458 listed in the second row of /proc/net/tcp.
So you can get all this information from proc, but you may end up reinventing netstat -lntp
来源:https://stackoverflow.com/questions/7436801/identifying-listening-ports-using-python