[英]Find original owning process of a Linux socket
在Linux和其他类UNIX操作系统,它是可能的两个(或多个)进程共享一个互联网插座。 假设进程之间没有父子关系,有没有办法告诉最初创建套接字的进程是什么?
澄清:我需要使用/proc
文件系统或类似程序从“外部”进程确定。 我无法修改进程的代码。 我已经可以通过读取/proc/<pid>/fd
告诉哪些进程正在共享套接字,但这并不能告诉我最初创建它们的进程。
你可以使用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 -
不会'帮助'-Ua'吗?
您可以通过解析/ proc / net / tcp(以及其他协议的类似“文件”)来找到共享套接字。 有上的/ proc /净/ TCP一些文档在这里 。
您需要找到套接字(可能通过其IP地址/端口号?)并解析出inode编号。 获得inode之后,您可以搜索所有/proc/*/fd/*
,为每个链接调用stat
并检查struct stat
的st_ino
成员,直到找到匹配项。
inode编号应该在两个进程之间匹配,所以当你经历了所有/proc/*/fd/*
你应该找到它们。
如果您知道的是第一个的进程ID和套接字fd,您可能不需要通过/ proc / net / tcp,您需要做的就是统计/proc/<pid>/fd/<fd>
并在/proc/*/fd/*
的其余部分搜索匹配的inode。 如果你想获取ip地址/端口号,你需要/ proc / net / tcp - 如果你知道inode号就可以找到
为了创建测试用例,请考虑多个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,因为套接字名称包含一个数字组件,该组件是用ps
标识的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将如此可靠以至于总是只被一个人关闭,而且,人们可能会认为并非所有套接字创建者都会如此好地命名套接字。
@ Cypher的答案指向了识别套接字所有者的PID问题的直接解决方案,但是不完整,因为lsof
实际上只能通过提升的权限来识别此PID。 如果没有提升权限,则不会有任何结果:
$ lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283
$
但是,通过提升权限,可以识别PID:
$ 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
在这种情况下,PID(myname)和套接字的所有者是进行查询的所有者,因此似乎不需要提升权限。 此外,执行查询的任务不应该能够提升权限,所以我寻找另一个答案。
这让我想到了@whoplisp的回答,提出netstat -tulpen
作为OP问题的解决方案。 虽然它可能对OP有效,但命令行限制太大而无法用作通用命令,并且在这种情况下完全无效(即使具有提升的权限)。
$ sudo netstat -tulpen | grep -E -- '(agent.21283|ssh-agent)'
$
但是,如果使用不同的命令行, netstat
可能会关闭:
$ 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
可悲的是,在这里,PID是难以捉摸的,没有提升权限:
$ 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.
遗憾的是, ss
还需要提升权限才能识别PID,但它会击败netstat
和lsof
执行时间:
$ 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
总之,似乎对于某些PID识别,似乎需要提升权限。
注意:并非所有操作系统都需要提升权限。 例如,SCO Openserver 5.0.7的lsof
似乎工作得很好而没有提升权限。
警告:关于OP找到套接字“原始创建者”的资格,这个答案可能会失败。 在使用的示例中,毫无疑问PID 21283是套接字创建的发起者,因为此PID在套接字名称中标识。 lsof
和netstat
都没有将PID 21283识别为原始创建者,但显然PID 21284是当前的维护者。
我不知道使用sendmsg()将套接字从一个进程“发送”到另一个进程。
我知道如果第二个进程尝试使用相同的端口,bind()系统调用将返回EADDRINUSE。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.