linuxsocketspython-3.xpython-3.2procfs

Finding a process ID given a socket and inode in Python 3


/proc/net/tcp gives me a local address, port, and inode number for a socket (0.0.0.0:5432 and 9289, for example).

I'd like to find the PID for a specific process, given the above information.

It's possible to open every numbered folder in /proc, and then check symlinks for matching socket/inode numbers with a shell command like "$ sudo ls -l /proc/*/fd/ 2>/dev/null | grep socket". However, this seems more computationally expensive than necessary, since <5% of the processes on any given system have open TCP sockets.

What's the most efficient way to find the PID which has opened a given socket? I'd prefer to use standard libraries, and I'm currently developing with Python 3.2.3.

Edit: Removed the code samples from the question, since they are now included in the answer below.


Solution

  • The following code accomplishes the original goal:

    def find_pid(inode):
    
        # get a list of all files and directories in /proc
        procFiles = os.listdir("/proc/")
    
        # remove the pid of the current python process
        procFiles.remove(str(os.getpid()))
    
        # set up a list object to store valid pids
        pids = []
    
        for f in procFiles:
            try:
                # convert the filename to an integer and back, saving the result to a list
                integer = int(f)
                pids.append(str(integer))
            except ValueError:
                # if the filename doesn't convert to an integer, it's not a pid, and we don't care about it
                pass
    
        for pid in pids:
            # check the fd directory for socket information
            fds = os.listdir("/proc/%s/fd/" % pid)
            for fd in fds:
                # save the pid for sockets matching our inode
                if ('socket:[%d]' % inode) == os.readlink("/proc/%s/fd/%s" % (pid, fd)):
                    return pid