我们的生产代码中有使用“netstat”的 sh 脚本。我们使用命令“netstat -lntup”来检索正在侦听某个端口的所有 pid。我用 ss -lntup 替换了该命令。现在,在大多数情况下,两个命令的输出是相同的,但在某些情况下,“ss”会为同一端口返回多个 pid,例如
# ss -lntup | grep http
tcp LISTEN 0 128 *:80 *:* users:(("httpd",pid=2355,fd=4),("httpd",pid=1962,fd=4),("httpd",pid=1961,fd=4),("httpd",pid=1960,fd=4),("httpd",pid=1955,fd=4))
tcp LISTEN 0 128 *:443 *:* users:(("httpd",pid=2355,fd=6),("httpd",pid=1962,fd=6),("httpd",pid=1961,fd=6),("httpd",pid=1960,fd=6),("httpd",pid=1955,fd=6))
我应该如何解读该列表? pid 是否以某种方式相关?多个进程可以同时监听同一个pid吗?
谢谢
答案1
pid 是否以某种方式相关?
在这种情况下显然是的。它们要么具有共同的父进程,要么其中一个进程是其他进程的父进程。
公共文件句柄(4 表示端口 80,6 表示端口 443)表明父进程在启动子进程之前创建了一个“套接字”。
多个进程可以同时监听同一个端口吗?
不是进程(pid)在端口上监听,而是“套接字”在端口上监听。
套接字是计算机内存中某些与网络相关的对象。
正如 Eduardo Trápani 已经写的那样,如果使用 SO_REUSEPORT,多个套接字可以侦听一个端口。然而,这里的情况(可能)并非如此。我假设只涉及两个套接字(一个在端口 80 上,一个在端口 443 上):
如果一个进程(pid)创建了一个套接字,然后创建了子进程,则该进程及其子进程通常在创建子进程后共享该套接字。
操作系统知道哪个套接字正在侦听哪个端口,但是因为套接字(至少在官方上)在多个 pid 之间共享,所以它无法找出哪个 pid 正在实际侦听。
我假设只有父进程真正使用套接字;但操作系统无法知道这一点。
答案2
pid 是否以某种方式相关?
不必要。但它们必须属于同一个有效用户 ID,以防止端口劫持。
多个进程可以同时监听同
一个pid /端口吗?
是的,使用套接字选项 SO_REUSEPORT。这一页(包括 python 示例)解释了它的工作原理以及它与 SO_REUSEADDR (也用于服务器)的关系。
这是页面的摘录:
SO_REUSEPORT
此选项的行为与 SO_REUSEADDR 的概念类似,但此选项允许我们将多个 TCP/UDP 服务器套接字绑定到完全相同的 IP 和相同端口。
但是套接字有 1 个限制,可以共享完全相同的 IP 和相同端口,这不在 SO_REUSEADDR 中。所有共享 IP/端口的套接字应由具有相同有效用户的进程生成。这可以应用于 UDP/TCP 协议,请注意,仅使用 SO_REUSEADDR 即可绑定多个 UDP 服务器套接字,而无需照顾有效用户(由 root open *:80 执行的 processA 和 userA 执行的 processB 可以使用 SO_REUSEADDR open *:80) 。但 SO_REUSEPORT 不允许。仅从这一点来看,我们可以认为 SO_REUSEPORT 受到更多限制。