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

18

Estou usando o CentOS 7. Quero obter o PID (se houver) do processo em execução na porta 3000. Gostaria de obter esse PID com o objetivo de salvá-lo em uma variável em um script de shell. 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 todas essas informações extras.

Dave
fonte
sudo ss -lptnH "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'. Você precisa de explicação?
User996142
2
Nenhuma explicação é necessária, mas isso resulta em um erro "ss: opção inválida - 'H'".
Dave
Você provavelmente tem um antigo sssem essa opção. Deve funcionar mesmo sem:sudo ss -lptn "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'
user996142 15/05
2
@ user996142 não é um comentário muito útil. pode ser uma boa resposta
aaaaa diz restabelecer Monica

Respostas:

33

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
Yurij Goncharuk
fonte
Tentei "lsof -t -i: 3000 TCP: LISTEN" e obteve o erro, "lsof: erro de status no TCP: LISTEN: esse arquivo ou diretório não existe"
Dave
@ Dave Execute sem TCP:LISTEN.
Xiong Chiamiov
2
@ Dave tenho falta -schave. Eu consertei isso no padrão. Um exemplo tinha essa chave.
Yurij Goncharuk
Ferramenta certa para o trabalho.
Johannes Kuhn
10

Tente o seguinte:

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

(requer psmiscpacote)

Observe que isso é confiável apenas quando executado pela raiz do usuário. 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 (fusor, ss, lsof, ...), todos acabam combinando a lista disponível de descritores de processos 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 esse descritor fd está disponível apenas para seu usuário (que é root neste exemplo) ou root, somente esse usuário ou root pode descobrir que o pid é 358.

AB
fonte
4

Enquanto lsof's -té a maneira mais simples para obter o PID, lsoftambém tem maneiras de selecionar outros campos usando o -Fopção:

$ 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 (observe que os descritores de PID e de arquivo são sempre impressos):

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

Portanto, se você quiser o ID do grupo de processos em vez do PID, poderá:

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

É disso que você precisa exatamente

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

Advertência: 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 --inet ou --inet6 interruptores para contar netstatpara apenas olhar para IPv4 ou IPv6, respectivamente, caso contrário você pode obter dois resultados.

Como alternativa, você pode dizer awkpara imprimir apenas uma vez

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

Em awkapenas usamos a saída ' / ' from netstat'do PID / programa como um separador.

Robert Riedl
fonte