Skip to main content

ports-to-pids.py (Source)

#!/usr/bin/env python3
import re
import subprocess
from pathlib import Path
"""
    Get a list of all open ports on localhost, and find the pids of the processes that opened them.
"""
ports = {}
with open('/proc/net/tcp') as f:
    next(f)
    for line in f:
        m = re.match(r'^\s+\d+:\s+(?P<ip>[A-Z0-9]+):(?P<port>[A-Z0-9]{4})(?:\s+\S+){7}\s+(?P<inode>\S+)', line)
        ip = int(m.group('ip'),16)
        port = int(m.group('port'),16)
        inode = int(m.group('inode'))
        if ip != 0 or port<1000:
            continue
        ports[inode] = port
        #break
pids = [int(x.strip()) for x in subprocess.run(['ps','axo','pid'], capture_output=True, encoding='ascii').stdout.strip().split('\n')[1:]]
port_to_pid = {}
for pid in pids:
    ppath = Path('/proc',str(pid))
    try:
        cwd = str((ppath / 'cwd').readlink().resolve())
        for f in (ppath /'fd').iterdir():
            if f.is_socket():
                link = f.readlink()
                if m := re.match(r'socket:\[(\d+)\]', link.name):
                    inode = int(m.group(1))
                    try:
                        port = ports[inode]
                        port_to_pid[port] = (pid, cwd)
                    except KeyError:
                        continue
    except (FileNotFoundError, PermissionError):
        continue
for port,(pid,cwd) in sorted(port_to_pid.items()):
    print(f'{port}\t{pid}\t{cwd}')