[英]Find original owning process of a Linux socket
In Linux and other UNIX-like operating systems, it is possible for two (or more) processes to share an Internet socket. 在Linux和其他类UNIX操作系统,它是可能的两个(或多个)进程共享一个互联网插座。 Assuming there is no parent-child relationship between the processes, is there any way to tell what process originally created a socket?
假设进程之间没有父子关系,有没有办法告诉最初创建套接字的进程是什么?
Clarification: I need to determine this from "outside" the processes using the /proc
filesystem or similar. 澄清:我需要使用
/proc
文件系统或类似程序从“外部”进程确定。 I can't modify the code of the processes. 我无法修改进程的代码。 I can already tell what processes are sharing sockets by reading
/proc/<pid>/fd
, but that doesn't tell me what process originally created them. 我已经可以通过读取
/proc/<pid>/fd
告诉哪些进程正在共享套接字,但这并不能告诉我最初创建它们的进程。
You can use netstat for this. 你可以使用netstat。 You should look in the columns 'Local Address' and 'PID/Program name'.
您应该查看“本地地址”和“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'吗?
You can likely find the shared sockets by parsing /proc/net/tcp (and similar "files" for other protocols). 您可以通过解析/ proc / net / tcp(以及其他协议的类似“文件”)来找到共享套接字。 There's some docs on /proc/net/tcp here .
有上的/ proc /净/ TCP一些文档在这里 。
You would need to find the socket (perhaps by its IP addresses/port numbers ?) and parse out the inode number. 您需要找到套接字(可能通过其IP地址/端口号?)并解析出inode编号。 Once you have the inode, you can search through all of
/proc/*/fd/*
, calling stat
for every link and inspect the st_ino
member of struct stat
until you find a match. 获得inode之后,您可以搜索所有
/proc/*/fd/*
,为每个链接调用stat
并检查struct stat
的st_ino
成员,直到找到匹配项。
The inode number should match between the 2 processes, so when you've gone through all /proc/*/fd/*
you should have found them both. inode编号应该在两个进程之间匹配,所以当你经历了所有
/proc/*/fd/*
你应该找到它们。
If what you do know is the process id and socket fd of the first, you might not need to go through /proc/net/tcp, all you need to do is stat the /proc/<pid>/fd/<fd>
and search the rest of /proc/*/fd/*
for a matching inode. 如果您知道的是第一个的进程ID和套接字fd,您可能不需要通过/ proc / net / tcp,您需要做的就是统计
/proc/<pid>/fd/<fd>
并在/proc/*/fd/*
的其余部分搜索匹配的inode。 You'd need /proc/net/tcp if you want to fetch the ip addresses/port number though - which you can find if you know the inode number 如果你想获取ip地址/端口号,你需要/ proc / net / tcp - 如果你知道inode号就可以找到
For purposes creating a test case, consider a situation where multiple ssh-agent
processes are running and have open sockets. 为了创建测试用例,请考虑多个
ssh-agent
进程正在运行并具有打开套接字的情况。 Ie A user runs ssh-agent
multiple times and loses the socket/PID information given when the agent started: 即用户多次运行
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
Later, the user wants to programmatically determine the PID owner of a particular ssh-agent socket (ie /tmp/ssh-W1Tl4i8HiftZ/agent.21283): 稍后,用户希望以编程方式确定特定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: -
In this case, because ssh-agent
named its socket nicely as a human onlooker can guess that the socket belongs to PID 21284, because the socket name contains a numeric component that is one-off from a PID identified with ps
: 在这种情况下,因为
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
It seems highly unwise to make any assumption that the PIDs will be so reliable as to always only be off by one, but also, one might suppose that not all socket creators will name the sockets so nicely. 似乎非常不明智地假设PID将如此可靠以至于总是只被一个人关闭,而且,人们可能会认为并非所有套接字创建者都会如此好地命名套接字。
@Cypher's answer points to a straightforward solution to the problem of identifying the PID of the socket owner, but is incomplete as lsof
actually can only identify this PID with elevated permissions. @ Cypher的答案指向了识别套接字所有者的PID问题的直接解决方案,但是不完整,因为
lsof
实际上只能通过提升的权限来识别此PID。 Without elevated permissions, no results are forthcoming: 如果没有提升权限,则不会有任何结果:
$ lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283
$
With elevated permissions, however, the PID is identified: 但是,通过提升权限,可以识别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
In this case, the owner of the PID (myname) and socket was the one doing the query, so it seemed elevated permissions should not be needed. 在这种情况下,PID(myname)和套接字的所有者是进行查询的所有者,因此似乎不需要提升权限。 Furthermore, the task performing the query was not supposed to be able to elevate permissions, so I looked for another answer.
此外,执行查询的任务不应该能够提升权限,所以我寻找另一个答案。
This led me to @whoplisp's answer proposing netstat -tulpen
as a solution to the OP's problem. 这让我想到了@whoplisp的回答,提出
netstat -tulpen
作为OP问题的解决方案。 While it may have been effective for the OP, the command line is too restrictive to serve as a general purpose command and was completely ineffective in this case (even with elevated permissions). 虽然它可能对OP有效,但命令行限制太大而无法用作通用命令,并且在这种情况下完全无效(即使具有提升的权限)。
$ sudo netstat -tulpen | grep -E -- '(agent.21283|ssh-agent)'
$
netstat
, however, can come close if a different command-line is used: 但是,如果使用不同的命令行,
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
Sadly, here too, the PID is elusive without elevated permissions: 可悲的是,在这里,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
Of the two solutions, however, lsof
clearly wins at the races: 然而,在这两种解决方案中,
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
Yet another tool exists according to the netstat
man page: 根据
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.
Sadly, ss
also requires elevated permissions to identify the PID, but, it beats both netstat
and lsof
execution times: 遗憾的是,
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
In conclusion, it might seem that for some PID identification, it appears that elevated permissions are required. 总之,似乎对于某些PID识别,似乎需要提升权限。
Note: Not all operating systems require elevated permissions. 注意:并非所有操作系统都需要提升权限。 For example, SCO Openserver 5.0.7's
lsof
seemed to work just fine without elevating permissions. 例如,SCO Openserver 5.0.7的
lsof
似乎工作得很好而没有提升权限。
Caveat: This answer may fail with respect to the OP's qualification for finding "the original creator" of the socket. 警告:关于OP找到套接字“原始创建者”的资格,这个答案可能会失败。 In the example used, no doubt PID 21283 was the originator of the socket's creation as this PID is identified in the socket name.
在使用的示例中,毫无疑问PID 21283是套接字创建的发起者,因为此PID在套接字名称中标识。 Neither
lsof
nor netstat
identified PID 21283 as the original creator, though clearly PID 21284 is the current maintainer. lsof
和netstat
都没有将PID 21283识别为原始创建者,但显然PID 21284是当前的维护者。
I don't know about using sendmsg() to "send" a socket from one process to another. 我不知道使用sendmsg()将套接字从一个进程“发送”到另一个进程。
I do know that the bind() system-call will return EADDRINUSE if a second process attempts to use the same port. 我知道如果第二个进程尝试使用相同的端口,bind()系统调用将返回EADDRINUSE。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.