Найти оригинальный процесс владения сокетом Linux - PullRequest
16 голосов
/ 01 марта 2010

В Linux и других UNIX-подобных операционных системах возможно для двух (или более) процессов совместно использовать интернет-сокет. Предполагая, что между процессами нет родительско-дочерних отношений, есть ли способ узнать, какой процесс изначально создал сокет?

Пояснение: Мне нужно определить это "извне" процессов, использующих файловую систему /proc или аналогичную. Я не могу изменить код процессов. Я уже могу сказать, какие процессы совместно используют сокеты, прочитав /proc/<pid>/fd, но это не говорит мне, какой процесс первоначально создал их.

Ответы [ 5 ]

20 голосов
/ 03 июля 2011

Вы можете использовать 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        -               
7 голосов
/ 06 апреля 2010

не помогает 'lsof -Ua'?

4 голосов
/ 02 марта 2010

Вероятно, вы можете найти общие сокеты, проанализировав / proc / net / tcp (и подобные «файлы» для других протоколов). Есть несколько документов на / proc / net / tcp здесь .

Вам нужно найти сокет (возможно, по его IP-адресам / номерам портов?) И проанализировать номер инода. Получив индекс, вы можете выполнять поиск по всем /proc/*/fd/*, вызывая stat для каждой ссылки и проверять st_ino член struct stat, пока не найдете совпадение.

Номер инода должен совпадать между двумя процессами, поэтому, пройдя все /proc/*/fd/*, вы должны были найти их оба.

Если вы знаете, что это идентификатор процесса и сокет fd первого, вам может не понадобиться проходить через / proc / net / tcp, все, что вам нужно сделать, это указать /proc/<pid>/fd/<fd> и выполнить поиск по остальным /proc/*/fd/* для соответствующего инода. Вам понадобится / proc / net / tcp, если вы хотите получить IP-адреса / номер порта, хотя вы можете найти его, если знаете номер индекса

0 голосов
/ 08 марта 2018

В целях создания тестового примера рассмотрим ситуацию, когда несколько процессов 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

Позже пользователь хочет программно определить владельца PID конкретного сокета ssh-agent (т.е. /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, идентифицируемого ps :

$ 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 будут настолько надежными, что всегда будут отключаться только одним, но также можно предположить, что не все создатели сокетов будут так красиво называть сокеты.

@ Ответ Сайфера указывает на простое решение проблемы идентификации 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, командная строка слишком ограничена, чтобы служить командой общего назначения, и в этом случае была совершенно неэффективна (даже с повышенными разрешениями).

$ 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, казалось, работал нормально, без повышения разрешений.

Предостережение: этот ответ может не соответствовать квалификации ОП для нахождения "первоначального создателя" сокета. В использованном примере, без сомнения, PID 21283 был инициатором создания сокета, так как этот PID указан в имени сокета. Ни lsof, ни netstat не идентифицировали PID 21283 как первоначального создателя, хотя ясно, что PID 21284 является текущим сопровождающим.

0 голосов
/ 01 марта 2010

Я не знаю, как использовать sendmsg () для "отправки" сокета из одного процесса в другой.

Я знаю, что системный вызов bind () вернет EADDRINUSE, если второй процесс попытается использовать тот же порт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...