在Linux和其他类UNIX操作系统中,两个(或更多)进程共享Internet套接字possible。假设进程之间没有父子关系,有没有办法告诉最初创建套接字的进程是什么?
澄清:我需要使用/proc
文件系统或类似程序从“外部”进程确定。我无法修改进程的代码。我已经可以通过阅读/proc/<pid>/fd
来分辨哪些进程正在共享套接字,但这并不能告诉我最初创建它们的进程。
答案 0 :(得分:20)
您可以使用netstat。您应该查看“本地地址”和“PID /程序名称”列。
xxx@xxx:~$ netstat -tulpen
(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 (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 127.0.0.1:4005 0.0.0.0:* LISTEN 1000 68449 7559/sbcl
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN 0 3938 -
tcp6 0 0 :::6000 :::* LISTEN 0 3937 -
udp 0 0 0.0.0.0:68 0.0.0.0:* 0 4528 -
答案 1 :(得分:7)
不是'sof -Ua'有帮助吗?
答案 2 :(得分:4)
您可以通过解析/ proc / net / tcp(以及其他协议的类似“文件”)找到共享套接字。 / proc / net / tcp here上有一些文档。
您需要找到套接字(可能是通过其IP地址/端口号?)并解析出inode编号。获得inode后,您可以搜索所有/proc/*/fd/*
,为每个链接调用stat
并检查st_ino
struct stat
成员,直至找到匹配项。
inode编号应该在两个进程之间匹配,所以当你通过所有/proc/*/fd/*
时,你应该找到它们。
如果您知道的是第一个的进程ID和套接字fd,您可能不需要通过/ proc / net / tcp,您需要做的就是统计/proc/<pid>/fd/<fd>
并搜索其余的/proc/*/fd/*
的匹配inode。如果你想获取ip地址/端口号,你需要/ proc / net / tcp - 如果你知道inode号就可以找到
答案 3 :(得分:0)
为了创建测试用例,请考虑多个ssh-agent
进程正在运行并具有开放套接字的情况。即用户多次运行ssh-agent
并丢失代理启动时给出的套接字/ PID信息:
$ find /tmp -path "*ssh*agent*" 2>/dev/null
/tmp/ssh-0XemJ4YlRtVI/agent.14405
/tmp/ssh-W1Tl4i8HiftZ/agent.21283
/tmp/ssh-w4fyViMab8wr/agent.10966
稍后,用户希望以编程方式确定特定ssh-agent套接字的PID所有者(即/tmp/ssh-W1Tl4i8HiftZ/agent.21283):
$ stat /tmp/ssh-W1Tl4i8HiftZ/agent.21283
File: '/tmp/ssh-W1Tl4i8HiftZ/agent.21283'
Size: 0 Blocks: 0 IO Block: 4096 socket
Device: 805h/2053d Inode: 113 Links: 1
Access: (0600/srw-------) Uid: ( 4000/ myname) Gid: ( 4500/ mygrp)
Access: 2018-03-07 21:23:08.373138728 -0600
Modify: 2018-03-07 20:49:43.638291884 -0600
Change: 2018-03-07 20:49:43.638291884 -0600
Birth: -
在这种情况下,因为ssh-agent
很好地命名了它的套接字,因为人类旁观者可以猜测套接字属于PID 21284,因为套接字名称包含一个数字组件,该组件与用{标识的PID一次性完成{1}}:
ps
假设PID是如此可靠以至于总是只被一个人关闭似乎是非常不明智的,但也有人可能认为并非所有套接字创建者都会如此好地命名套接字。
@ Cypher的答案指向了识别套接字所有者的PID问题的直接解决方案,但是不完整,因为$ ps -ef | grep ssh-agent
myname 10967 1 0 16:54 ? 00:00:00 ssh-agent
myname 14406 1 0 20:35 ? 00:00:00 ssh-agent
myname 21284 1 0 20:49 ? 00:00:00 ssh-agent
实际上只能通过提升的权限来识别此PID。如果没有提升权限,则不会有任何结果:
lsof
但是,在提升权限的情况下,会识别出PID:
$ lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283
$
在这种情况下,PID(myname)和套接字的所有者是进行查询的所有者,因此似乎不需要提升权限。此外,执行查询的任务不应该能够提升权限,所以我寻找另一个答案。
这让我想起了@ whoplisp的回答,提出$ sudo lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
ssh-agent 21284 myname 3u unix 0xffff971aba04cc00 0t0 1785049 /tmp/ssh-W1Tl4i8HiftZ/agent.21283 type=STREAM
作为OP问题的解决方案。虽然它可能对OP有效,但命令行限制太大而无法用作通用命令,在这种情况下完全无效(即使权限提升)。
netstat -tulpen
但是,如果使用不同的命令行, $ sudo netstat -tulpen | grep -E -- '(agent.21283|ssh-agent)'
$
可以接近:
netstat
可悲的是,在这里,如果没有提升权限,PID就难以捉摸:
$ netstat -ap | grep -E -- '(agent.21283)'
(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)
unix 2 [ ACC ] STREAM LISTENING 1785049 - /tmp/ssh-W1Tl4i8HiftZ/agent.21283
然而,在这两个解决方案中,$ sudo netstat -ap | grep -E -- '(agent.21283|ssh-agent)'
unix 2 [ ACC ] STREAM LISTENING 1765316 10967/ssh-agent /tmp/ssh-w4fyViMab8wr/agent.10966
unix 2 [ ACC ] STREAM LISTENING 1777450 14406/ssh-agent /tmp/ssh-0XemJ4YlRtVI/agent.14405
unix 2 [ ACC ] STREAM LISTENING 1785049 21284/ssh-agent /tmp/ssh-W1Tl4i8HiftZ/agent.21283
显然在比赛中获胜:
lsof
根据$ time sudo netstat -ap | grep -E -- '(agent.21283|ssh-agent)' >/dev/null
real 0m5.159s
user 0m0.010s
sys 0m0.019s
$ time sudo lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283 >/dev/null
real 0m0.120s
user 0m0.038s
sys 0m0.066s
手册页存在另一种工具:
netstat
遗憾的是,$ man netstat | grep -iC1 replace
NOTES
This program is mostly obsolete. Replacement for netstat is ss. Replacement for netstat -r is ip route. Replacement for netstat -i
is ip -s link. Replacement for netstat -g is ip maddr.
还需要提升权限才能识别PID,但它会同时执行ss
和netstat
次执行:
lsof
总之,似乎对于某些PID识别,似乎需要提升权限。
注意:并非所有操作系统都需要提升权限。例如,SCO Openserver 5.0.7的$ time sudo ss -ap | grep -E "(agent.21283|ssh-agent)"
u_str LISTEN 0 128 /tmp/ssh-w4fyViMab8wr/agent.10966 1765316 * 0 users:(("ssh-agent",pid=10967,fd=3))
u_str LISTEN 0 128 /tmp/ssh-0XemJ4YlRtVI/agent.14405 1777450 * 0 users:(("ssh-agent",pid=14406,fd=3))
u_str LISTEN 0 128 /tmp/ssh-W1Tl4i8HiftZ/agent.21283 1785049 * 0 users:(("ssh-agent",pid=21284,fd=3))
real 0m0.043s
user 0m0.018s
sys 0m0.021s
似乎没有提升权限就可以正常工作。
警告:对于OP找到套接字“原始创建者”的资格,这个答案可能会失败。在使用的示例中,毫无疑问PID 21283是套接字创建的发起者,因为此PID在套接字名称中标识。 lsof
和lsof
都没有将PID 21283识别为原始创建者,但显然PID 21284是当前的维护者。
答案 4 :(得分:-2)
我不知道如何使用sendmsg()将套接字从一个进程“发送”到另一个进程。
我知道如果第二个进程尝试使用相同的端口,bind()系统调用将返回EADDRINUSE。