不同的进程在netstat中显示为相同的PID

时间:2015-07-30 00:11:00

标签: python-2.7 python-multiprocessing netstat

我使用Python多处理模块生成了一些进程。 但是,当我调用netstat -nptl时,每个ip:端口侦听器列在同一个PID下。

我在Ubuntu 14.04上使用Python 2.7。

netstat -V
>> net-tools 1.60
>> netstat 1.42 (2001-04-15)

相关代码:

import unittest
import multiprocessing
import socket
import os
import time
import ex1


class Listener(multiprocessing.Process):
    def __init__(self, _ttl):
        super(Listener, self).__init__()
        self.ttl = _ttl
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.bind(('localhost', 0))

    def get_pid(self):
        return self.pid

    def get_name(self):
        return self.socket.getsockname()

    def run(self):
        self.socket.listen(1)
        time.sleep(self.ttl)

    def listen(self):
        self.start()


class TestEx1(unittest.TestCase):
    def test_is_legal_ip(self):
        # Legal IP
        assert(ex1.is_legal_ip("1.1.1.1:55555"))
        assert(ex1.is_legal_ip("0.1.1.255:55555"))
        assert(ex1.is_legal_ip("0.0.0.0:55555"))
        assert(ex1.is_legal_ip("255.255.255.255:55555"))
        assert(ex1.is_legal_ip("0.1.2.3:55555"))

        # Illegal IP
        assert(not ex1.is_legal_ip("256.1.1.1:55555"))
        assert(not ex1.is_legal_ip("1.256.1:55555"))
        assert(not ex1.is_legal_ip("1.1.1.1.1:55555"))
        assert(not ex1.is_legal_ip("1.a.1.1:55555"))
        assert(not ex1.is_legal_ip("1.1001.1.1:55555"))

    def test_address_to_pid(self):
        # Create 3 listener processes
        listener1 = Listener(22)
        listener2 = Listener(22)
        listener3 = Listener(22)

        # Start listening
        listener1.listen()
        listener2.listen()
        listener3.listen()

        print listener1.get_pid()
        print listener2.get_pid()
        print listener3.get_pid()


        # For each listener, get appropriate ip:port
        address1 = str(str(listener1.get_name()[0])) + \
            ":" + str(listener1.get_name()[1])
        address2 = str(str(listener2.get_name()[0])) + \
            ":" + str(listener2.get_name()[1])
        address3 = str(str(listener3.get_name()[0])) + \
            ":" + str(listener3.get_name()[1])

        # Check if address_to_pid() works as expected.
        #assert(str(ex1.address_to_pid(address1)) == str(listener1.get_pid()))
        #assert(str(ex1.address_to_pid(address2)) == str(listener2.get_pid()))
        #assert(str(ex1.address_to_pid(address3)) == str(listener3.get_pid()))

        # Waits for the listener processes to finish
        listener2.join()
        listener2.join()
        listener3.join()


if __name__ == "__main__":
    unittest.main()

输出:

4193
4194
4195
..
----------------------------------------------------------------------
Ran 2 tests in 22.019s

OK

Netstat -nptl输出:

(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.1.1:53            0.0.0.0:*               LISTEN      -               
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      -               
tcp        0      0 127.0.0.1:37529         0.0.0.0:*               LISTEN      4192/python     
tcp        0      0 127.0.0.1:53402         0.0.0.0:*               LISTEN      4192/python     
tcp        0      0 127.0.0.1:49214         0.0.0.0:*               LISTEN      4192/python     
tcp        1      0 192.168.46.136:49475    209.20.75.76:80         CLOSE_WAIT  2968/plugin_host
tcp       70      0 192.168.46.136:60432    91.189.92.7:443         CLOSE_WAIT  3553/unity-scope-ho
tcp6       0      0 ::1:631                 :::*                    LISTEN      -   

1 个答案:

答案 0 :(得分:0)

使用我的Mac OS 10.9.5(Python 2.7.3),我可以重现相同的行为。经过几次尝试和错误之后,事实证明它是因为套接字对象在进程之间共享。 (lsof -p <pid>有助于识别侦听套接字。)

当我对Listener类进行了以下更改时,每个进程都开始通过自己的PID监听自己的端口号。

def get_name(self):
    # this method cannot refer to socket object any more
    # self.sockname should be initialized as "not-listening" at __init__
    return self.sockname

def run(self):
    # Instantiate socket at run
    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.socket.bind(('localhost', 0))
    self.sockname = self.socket.getsockname()
    # Listener knows sockname
    print self.sockname
    self.socket.listen(1)
    time.sleep(self.ttl)

此行为应与Ubuntu的Python和netstat相同。

self.sockname仍然是&#34; not-listening&#34;在原始过程中

要将端口侦听为独立进程,需要在Listener对象的run方法上创建套接字(新进程在创建对象副本后调用此方法)。但是,在新进程中此复制对象中更新的变量不会反映到原始进程中的原始对象。