Como obtenho apenas o PID, sem qualquer informação extra, de um processo em execução na porta 3000?

16

Estou usando o CentOS 7. Desejo obter o PID (se houver) do processo em execução na porta 3000. Eu gostaria de obter esse PID para salvá-lo em uma variável em um shell script. Até agora eu tenho

[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))

mas não consigo descobrir como isolar o PID sozinho sem toda essa informação extra.

    
por Dave 14.05.2018 / 22:04

5 respostas

30

Outra solução possível:

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

Por exemplo:

# 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
    
por 14.05.2018 / 22:22
10

Tente isto:

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

(requer psmisc package)

Por favor, note que isto é confiável somente quando executado pelo usuário root. Outros usuários podem apenas esperar encontrar processos em execução com o mesmo usuário.

Explicação chata para acesso somente raiz com um exemplo aqui.
Qualquer que seja o método usado (fuser, ss, lsof, ...), todos eles acabam combinando a lista disponível de descritores de processo com uma lista disponível de conexões de rede (por exemplo, para tcp está disponível em /proc/net/tcp ). Por exemplo, tentar obter o pid usando a porta 22/tcp (com 22 = 0x0016) acabaria fazendo esse tipo de comparação:

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

com:% 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 descritor fd está disponível apenas para seu usuário (que é o root neste exemplo) ou root, somente esse usuário ou root pode descobrir que o pid é 358.

    
por 14.05.2018 / 22:11
4

Enquanto lsof -t é a maneira mais simples de obter o PID, lsof também tem maneiras de selecionar outros campos usando a opção -F :

$ 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

Com saída assim (note que os descritores PID e de arquivo são sempre impressos):

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

Então, se você quisesse o ID do grupo de processos em vez do PID, poderia fazer:

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

Isso é exatamente o que você precisa

sudo lsof -n -i :3000  | awk '/LISTEN/{print $2}'
12726
12730
12732
    
por 15.05.2018 / 09:31
1

Advertência: Eu só posso testar isso no RedHat.

Deve ser possível com netstat ?

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

-n para portas numéricas
-l para portas de escuta -p para ver PIDs

Você pode usar as chaves - inet ou - inet6 para dizer ao netstat para procurar somente para IPv4 ou IPv6 respectivamente, caso contrário, você pode obter dois resultados.

Como alternativa, você pode informar awk para imprimir somente uma vez

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

Em awk , usamos apenas o ' / ' da saída de netstat do PID / programa como um separador.

    
por 15.05.2018 / 08:39