简体   繁体   English

找到Linux套接字的原始拥有进程

[英]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 statst_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,但它会击败netstatlsof执行时间:

$ 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. lsofnetstat都没有将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.

相关问题 如何在Linux中通过inode结构找到套接字端口? - How to find socket port by inode struct in Linux? 在内存中查找Process(linux-kernel)页面 - Find page in memory for Process (linux-kernel) 具有PPID 1的Linux on重新启动过程不会清理资源(套接字) - Linux on reboot process with PPID 1 do not clean up resources (socket) 如何在Linux中获取给定进程的TCP套接字文件描述符? - How to get the file descriptors of TCP socket for a given process in Linux? 查找连接到Linux上任何进程的stdin的tty设备文件 - Find tty device file connected to stdin of any process on Linux 在Linux中查找会话负责人或控制进程组TTY的方法有哪些? - What are the ways to find the session leader or the controlling TTY of a process group in Linux? 如何在Linux内核中找到打开的inode的所有者进程? - How to find the owner process of an opened inode in Linux kernel? 如何在 linux/ubuntu 中找到进程使用的确切堆栈和堆内存? - How to find exact stack and heap memory used by a process in linux/ubuntu? Linux C socket在使用epoll时如何防止2个分叉进程接受相同的连接? - Linux C socket how to prevent 2 forked process from accepting the same connection when using epoll? 在TCP套接字请求(c / linux)中的线程进程上一段时间后,连接被拒绝 - Connection refused after some time on threaded process in tcp socket requests (c/linux)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM