【问题标题】:Different processes showed as same PID within netstat不同的进程显示为与 netstat 相同的 PID
【发布时间】:2015-07-30 00:11:00
【问题描述】:

我使用 Python 多处理模块生成了几个进程。 但是,当我调用 netstat -nptl 时,每个 ip:port 侦听器都列在同一个 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      -   

【问题讨论】:

  • 如果在 Listener 的 run 方法中调用 bind,netstat 中显示的 pid 会发生什么情况?
  • 完全一样的结果。

标签: python-2.7 python-multiprocessing netstat


【解决方案1】:

使用我的 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 在原始进程中仍然“不听”

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

【讨论】:

  • 但是我现在如何检索套接字的 IP 和 PORT?
  • 使用netstat获取端口号对我来说是不可接受的。我无法在 Listener 中找到 PORT?
  • 为什么需要打印?我可以在不使用打印的情况下解决此问题吗?
  • 当然。打印只是为了让您确认侦听器现在获取端口号。
  • 不幸的是它对我不起作用:AttributeError: 'Listener' object has no attribute 'sockname'
猜你喜欢
  • 2020-09-17
  • 2020-06-23
  • 2012-06-16
  • 1970-01-01
  • 2013-05-14
  • 2018-07-02
  • 2011-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多