¿Cómo obtengo solo el PID, sin información adicional, de un proceso que se ejecuta en el puerto 3000?

18

Estoy usando CentOS 7. Quiero obtener el PID (si existe) del proceso que se ejecuta en el puerto 3000. Me gustaría obtener este PID con el fin de guardarlo en una variable en un script de shell. Hasta ahora tengo

[rails@server proddir]$ sudo ss -lptn 'sport = :3000'
State      Recv-Q Send-Q                           Local Address:Port                                          Peer Address:Port
Cannot open netlink socket: Protocol not supported
LISTEN     0      0                                            *:3000                                                     *:*                   users:(("ruby",pid=4861,fd=7),("ruby",pid=4857,fd=7),("ruby",pid=4855,fd=7),("ruby",pid=4851,fd=7),("ruby",pid=4843,fd=7))

pero no puedo entender cómo aislar el PID por sí solo sin toda esta información adicional.

Dave
fuente
sudo ss -lptnH "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'. ¿Necesitas explicación?
user996142
2
No se necesita explicación, pero esto da como resultado un error "ss: opción no válida - 'H'".
Dave
Probablemente tenga un viejo sssin esta opción. Debería funcionar incluso sin él:sudo ss -lptn "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'
user996142
2
@ user996142 no es un comentario muy útil. sin embargo
aaaaa dice que reinstalar a Monica

Respuestas:

33

Otra posible solución:

lsof -t -i :<port> -s <PROTO>:LISTEN

Por ejemplo:

# lsof -i :22 -s TCP:LISTEN
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    1392 root    3u  IPv4  19944      0t0  TCP *:ssh (LISTEN)
sshd    1392 root    4u  IPv6  19946      0t0  TCP *:ssh (LISTEN)
# lsof -t -i :22 -s TCP:LISTEN
1392
Yurij Goncharuk
fuente
Intenté "lsof -t -i: 3000 TCP: LISTEN" y obtuve el error, "lsof: error de estado en TCP: LISTEN: No existe dicho archivo o directorio"
Dave
@Dave Ejecútalo sin TCP:LISTEN.
Xiong Chiamiov
2
@Dave He perdido la -sclave. Lo he arreglado en el patrón. Un ejemplo tenía esta clave.
Yurij Goncharuk
Herramienta adecuada para el trabajo.
Johannes Kuhn
10

Prueba esto:

pid=$(fuser 3000/tcp 2>/dev/null)

(requiere psmiscpaquete)

Tenga en cuenta que esto es confiable solo cuando lo ejecuta el usuario root. Otros usuarios solo pueden esperar encontrar procesos que se ejecuten con el mismo usuario.


Explicación aburrida para el acceso solo root con un ejemplo aquí.
Cualquiera que sea el método utilizado (fusor, ss, lsof, ...) todos terminan haciendo coincidir la lista disponible de descriptores de proceso con una lista disponible de conexiones de red (por ejemplo, para tcp está disponible en /proc/net/tcp).
Por ejemplo, tratar de obtener el pid utilizando el puerto 22/tcp(con 22 = 0x0016) terminaría haciendo este tipo de comparación:

Entrada desde /proc/net/tcp:
0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 141408 1 000000000a9ac1b5 100 0 0 10 0

con:
dr-x------. 2 root root 0 May 14 17:59 /proc/358/fd lrwx------. 1 root root 64 May 14 17:59 /proc/358/fd/3 -> socket:[141408]

Como este descriptor de fd solo está disponible para su usuario (que en este ejemplo es root) o root, solo ese usuario o root puede descubrir que el pid es 358.

AB
fuente
4

Mientras lsof's -tes la forma más simple de obtener el PID, lsoftambién tiene formas de seleccionar otros campos usando la -Fopción:

$ lsof -F'?'
lsof:   ID    field description
     a    access: r = read; w = write; u = read/write
     c    command name
     d    device character code
     D    major/minor device number as 0x<hex>
     f    file descriptor (always selected)
     G    file flaGs
     i    inode number
     k    link count
     K    task ID (TID)
     l    lock: r/R = read; w/W = write; u = read/write
     L    login name
     m    marker between repeated output
     n    comment, name, Internet addresses
     o    file offset as 0t<dec> or 0x<hex>
     p    process ID (PID)
     g    process group ID (PGID)
     P    protocol name
     r    raw device number as 0x<hex>
     R    paRent PID
     s    file size
     S    stream module and device names
     t    file type
     T    TCP/TPI info
     u    user ID (UID)
     0    (zero) use NUL field terminator instead of NL

Con resultados como este (tenga en cuenta que el PID y los descriptores de archivo siempre se imprimen):

$ sudo lsof -F cg -i :22 -s TCP:LISTEN 
p901
g901
csshd
f3
f4

Entonces, si desea la ID del grupo de procesos en lugar del PID, puede hacer lo siguiente:

$ sudo lsof -F g -i :22 -s TCP:LISTEN | awk '/^g/{print substr($0, 2)}'
901
muru
fuente
2

Esto es lo que necesitas exactamente

sudo lsof -n -i :3000  | awk '/LISTEN/{print $2}'
12726
12730
12732
Arushix
fuente
1

Advertencia: solo puedo probar esto en RedHat.

Debería ser posible con netstat?

 sudo netstat -npl --inet | awk '/:3000/' | awk -F "[ /]+" '{print $7}'

-n para puertos numéricos
-l para puertos de escucha
-p para ver PID

Puede usar los interruptores --inet o --inet6 para indicar netstatque solo busque IPv4 o IPv6 respectivamente, de lo contrario, podría obtener dos resultados.

Alternativamente, puede indicar awkque imprima solo una vez

sudo netstat -npl | awk '/:3000/' | awk -F "[ /]+" '{print $7; exit}' 

En awksolo usamos la salida ' / ' from netstat'de PID / program como separador.

Robert Riedl
fuente