2010-03-01 14 views
14

En Linux y otros sistemas operativos tipo UNIX, es possible para que dos (o más) procesos compartan un socket de Internet. Suponiendo que no existe una relación padre-hijo entre los procesos, ¿hay alguna manera de decir qué proceso creó originalmente un socket?Buscar proceso original de propiedad de un socket Linux

Aclaración: Necesito determinar esto desde "fuera" de los procesos usando el sistema de archivos /proc o similar. No puedo modificar el código de los procesos. Ya puedo decir qué procesos están compartiendo sockets al leer /proc/<pid>/fd, pero eso no me dice qué proceso los creó originalmente.

+0

Por favor especificar en qué haría para organizar el intercambio de una toma sin relación padre-hijo. – bmargulies

+0

La pregunta que he vinculado lo explica. También lo he visto suceder en mi caja de Linux. –

+0

Oh, correcto. Me olvidé completamente de eso. – bmargulies

Respuesta

-1

No sé sobre el uso de sendmsg() para "enviar" un socket de un proceso a otro.

Sé que la llamada al sistema bind() devolverá EADDRINUSE si un segundo proceso intenta utilizar el mismo puerto.

3

Probablemente pueda encontrar los sockets compartidos mediante el análisis/proc/net/tcp (y "archivos" similares para otros protocolos). Hay algunos documentos en/proc/net/tcp here.

¿Necesitaría encontrar el zócalo (quizás por sus direcciones IP/números de puerto?) Y analizar el número de inodo. Una vez que tenga el inodo, puede buscar a través de /proc/*/fd/*, llamando al stat para cada enlace e inspeccionar el miembro st_ino de struct stat hasta que encuentre una coincidencia.

El número de inodo debe coincidir entre los 2 procesos, por lo que cuando haya pasado todos /proc/*/fd/* debería haber encontrado ambos.

Si lo que sabes es el identificador de proceso y el zócalo fd de la primera, es posible que no necesita ir a través de/proc/net/tcp, todo lo que necesita hacer es stat del /proc/<pid>/fd/<fd> y buscar en el resto de /proc/*/fd/* de un inodo coincidente. Sin embargo, necesitaría/proc/net/tcp si desea obtener las direcciones IP/número de puerto, que puede encontrar si conoce el número de inodo

+0

Quizás no me explique bien. Ya sé cómo saber qué procesos están compartiendo sockets. Lo hago usando exactamente el método que describiste. Pero esto no me ayuda a determinar qué proceso poseía originalmente el socket. Tal vez deba hacer una suposición basada en la edad de cada proceso. –

+0

Sería muy útil si actualiza su pregunta para indicar lo que está buscando, y que lo hace desde fuera de cualquiera de los programas involucrados. Sin embargo, no hay información directa sobre el propietario o creador original en ninguna parte. Lo más parecido que obtendrás es llamar a 'lstat' en los enlaces en/proc/pid/fd/fd y adivinar que la marca de tiempo más antigua (ctime likely) fue el creador original. – nos

+0

Se ha actualizado la pregunta para aclarar. –

7

¿No tiene 'lsof -Ua' ayuda?

+0

buena respuesta con información añadida: Sí funciona aunque creo que es innecesario, ya que -a resultados parecen el mismo con y sin -a, sino que, por alguna Linux, parece 'lsof' es en gran parte neutralizado y requiere permisos elevados para encontrar esta información . Por ejemplo, yo quería saber el PID del /tmp/ssh-W1Tl4i8HiftZ/agent.21283, pero 'lsof -ua /tmp/ssh-W1Tl4i8HiftZ/agent.21283' no muestra nada en absoluto - ni siquiera un mensaje de error. Por otro lado, 'sudo lsof -Ua /tmp/ssh-W1Tl4i8HiftZ/agent.21283' fue muy revelador y mostró un PID. Lamentablemente, sudo o permisos elevados no son viables para muchas tareas. – kbulgrien

18

Puede usar netstat para esto. Debe buscar en las columnas 'Dirección local' y 'PID/Nombre del programa'.

[email protected]:~$ 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  -    
0

Para efectos crean un caso de prueba, considere una situación en la que múltiples ssh-agent procesos se están ejecutando y tienen sockets abiertos. Es decir. Un usuario ejecuta ssh-agent varias veces y pierde la información de socket/PID dado cuando el agente comenzó:

$ find /tmp -path "*ssh*agent*" 2>/dev/null 
/tmp/ssh-0XemJ4YlRtVI/agent.14405 
/tmp/ssh-W1Tl4i8HiftZ/agent.21283 
/tmp/ssh-w4fyViMab8wr/agent.10966 

Más tarde, el usuario quiere determinar mediante programación el propietario PID de un conector especial ssh-agent (es decir,/tmp/ssh -W1Tl4i8HiftZ/agente.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: - 

En este caso, porque ssh-agent llamado su zócalo bien como un observador humano puede adivinar que el socket pertenece a PID 21284, porque el nombre de socket contiene un componente numérico que es de una sola vez a partir de un PID identificados con 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 

parece muy imprudente hacer cualquier suposición de que los PID será tan fiable como siempre solamente estar fuera por uno, sino que también, uno podría suponer que no todos los creadores de socket nombrarán a los zócalos muy bien

@ La respuesta de Cypher a una solución directa al problema de identificación del PID del propietario del socket, pero está incompleta ya que lsof realmente solo puede identificar este PID con permisos elevados. Sin permisos elevados, no hay resultados son próximas:

$ lsof /tmp/ssh-W1Tl4i8HiftZ/agent.21283 
$ 

con permisos elevados, sin embargo, el PID se identifica:

$ 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 

En este caso, el propietario de la PID (myname) y el zócalo era el uno haciendo la consulta, por lo que parecía que los permisos elevados no deberían ser necesarios. Además, se suponía que la tarea que realizaba la consulta no podía elevar los permisos, por lo que busqué otra respuesta.

Esto me llevó a la respuesta de @ whoplisp proponiendo netstat -tulpen como una solución al problema del OP. Si bien puede haber sido efectivo para el OP, la línea de comando es demasiado restrictiva para servir como un comando de propósito general y fue completamente ineficaz en este caso (incluso con permisos elevados).

$ sudo netstat -tulpen | grep -E -- '(agent.21283|ssh-agent)' 
$ 

netstat, sin embargo, puede acercarse si se utiliza una línea de comandos diferentes:

$ 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 

Lamentablemente, también en este caso, el PID es difícil de alcanzar sin permisos elevados:

$ 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 

De las dos soluciones, sin embargo, lsof claramente gana en las carreras:

$ 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 

Sin embargo, existe otra herramienta de acuerdo con la página netstat hombre:

$ 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. 

Lamentablemente, ss también requiere permisos elevados para identificar el PID, pero, es mejor que ambos netstat y lsof Tiempos de ejecución:

$ 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 

En conclusión, podría parecer que para cierta identificación PID, parece que se requieren permisos elevados.

Nota: no todos los sistemas operativos requieren permisos elevados. Por ejemplo, lsof de SCO Openserver 5.0.7 parecía funcionar bien sin elevar los permisos.

Advertencia: esta respuesta puede fallar con respecto a la calificación del OP para encontrar "el creador original" del socket.En el ejemplo utilizado, sin duda PID 21283 fue el creador de la creación del socket ya que este PID se identifica en el nombre del socket. Ni lsof ni netstat identificaron PID 21283 como el creador original, aunque claramente PID 21284 es el mantenedor actual.

Cuestiones relacionadas