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

时间:2010-03-01 19:37:32

标签: c linux sockets

在Linux和其他类UNIX操作系统中,两个(或更多)进程共享Internet套接字possible。假设进程之间没有父子关系,有没有办法告诉最初创建套接字的进程是什么?

澄清:我需要使用/proc文件系统或类似程序从“外部”进程确定。我无法修改进程的代码。我已经可以通过阅读/proc/<pid>/fd来分辨哪些进程正在共享套接字,但这并不能告诉我最初创建它们的进程。

5 个答案:

答案 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,但它会同时执行ssnetstat次执行:

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在套接字名称中标识。 lsoflsof都没有将PID 21283识别为原始创建者,但显然PID 21284是当前的维护者。

答案 4 :(得分:-2)

我不知道如何使用sendmsg()将套接字从一个进程“发送”到另一个进程。

我知道如果第二个进程尝试使用相同的端口,bind()系统调用将返回EADDRINUSE。

相关问题