Comment obtenir uniquement le PID, sans aucune information supplémentaire, d'un processus exécuté sur le port 3000?

18

J'utilise CentOS 7. Je veux obtenir le PID (s'il existe) du processus en cours d'exécution sur le port 3000. Je voudrais obtenir ce PID afin de le sauvegarder dans une variable dans un script shell. Jusqu'à présent, j'ai

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

mais je ne peux pas comprendre comment isoler le PID tout seul sans toutes ces informations supplémentaires.

Dave
la source
sudo ss -lptnH "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'. Avez-vous besoin d'explications?
user996142
2
Aucune explication nécessaire, mais cela se traduit par une erreur «ss: option non valide -« H »».
Dave
Vous avez probablement un ancien sssans de cette option. Devrait fonctionner même sans:sudo ss -lptn "sport = :22" | awk -F " " '{printf $6}' | sed 's/.\+pid=\([0-9]\+\).\+/\1/g'
user996142
2
@ user996142 pas un commentaire très utile. pourrait être une bonne réponse cependant
aaaaa dit réintégrer Monica

Réponses:

33

Une autre solution possible:

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

Par exemple:

# 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
la source
J'ai essayé "lsof -t -i: 3000 TCP: LISTEN" et obtenu l'erreur "lsof: erreur d'état sur TCP: LISTEN: aucun fichier ou répertoire"
Dave
@Dave Exécutez-le sans TCP:LISTEN.
Xiong Chiamiov
2
@J'ai oublié la -sclé. Je l'ai corrigé dans le modèle. Un exemple avait cette clé.
Yurij Goncharuk
Le bon outil pour le travail.
Johannes Kuhn
10

Essaye ça:

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

(nécessite un psmiscpackage)

Veuillez noter que cela n'est fiable que lorsqu'il est exécuté par l'utilisateur root. Les autres utilisateurs ne peuvent qu'espérer trouver des processus exécutés avec le même utilisateur.


Explication ennuyeuse pour l'accès root uniquement avec un exemple ici.
Quelle que soit la méthode utilisée (fuser, ss, lsof, ...), ils finissent tous par faire correspondre la liste disponible des descripteurs de processus à une liste disponible de connexions réseau (par exemple pour TCP il est disponible en /proc/net/tcp).
Par exemple, essayer d'obtenir le pid en utilisant le port 22/tcp(avec 22 = 0x0016) finirait par faire ce genre de comparaison:

Entrée 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

avec:
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]

Comme ce descripteur fd est uniquement disponible pour son utilisateur (qui se trouve être root dans cet exemple) ou root, seul cet utilisateur ou root peut découvrir que le pid est 358.

UN B
la source
4

Bien que lsof's -tsoit le moyen le plus simple d'obtenir le PID, lsofil a également des moyens de sélectionner d'autres champs en utilisant l' -Foption:

$ 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

Avec une telle sortie (notez que le PID et les descripteurs de fichiers sont toujours imprimés):

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

Donc, si vous vouliez l'ID du groupe de processus au lieu du PID, vous pouvez faire:

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

C'est exactement ce dont vous avez besoin

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

Avertissement: je ne peux tester cela que sur RedHat.

Devrait être possible avec netstat?

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

-n pour les ports numériques
-l pour les ports d'écoute
-p pour voir les PID

Vous pouvez utiliser les commutateurs --inet ou --inet6 pour indiquer netstatde ne rechercher que IPv4 ou IPv6 respectivement, sinon vous pourriez obtenir deux résultats.

Alternativement, vous pouvez dire awkd'imprimer une seule fois

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

Dans awknous utilisons simplement la sortie ' / ' de netstat'du programme PID / comme séparateur.

Robert Riedl
la source