comment trouver l'espace de noms d'un processus particulier?

25

J'ai déjà posé une question sur la façon de lister tous les espaces de noms sous Linux , mais il n'y avait pas de réponses correctes et exactes, donc je veux trouver une méthode qui peut m'aider à trouver l'espace de noms du PID d'un processus ou d'un groupe de processus. Comment cela peut-il se faire sous Linux?

zerospiel
la source

Réponses:

39

Je vais essayer de répondre à la fois à cette question et à votre question précédente car elles sont liées.

Les portes des espaces de noms sont des fichiers dans /proc/*/ns/*et /proc/*/task/*/ns/*.

Un espace de noms est créé par un processus qui partage son espace de noms. Un espace de noms peut alors être rendu permanent en liant le nsfichier à un autre endroit.

C'est ce que ip netnsfait par exemple pour les espaces de noms nets . Il ne partage pas son netespace de noms et lie-monte /proc/self/ns/netà ./run/netns/netns-name

Dans un /procespace de noms pid monté, vous pouvez répertorier tous les espaces de noms contenant un processus en procédant comme suit:

# readlink /proc/*/task/*/ns/* | sort -u
ipc:[4026531839]
mnt:[4026531840]
mnt:[4026531856]
mnt:[4026532469]
net:[4026531956]
net:[4026532375]
pid:[4026531836]
pid:[4026532373]
uts:[4026531838]

Le nombre entre crochets est le numéro d'inode.

Pour obtenir cela pour un processus donné:

# ls -Li /proc/1/ns/pid
4026531836 /proc/1/ns/pid

Maintenant, il peut y avoir des espaces de noms permanents qui ne contiennent aucun processus. Les découvrir peut être beaucoup plus délicat AFAICT.

Tout d'abord, vous devez garder à l'esprit qu'il peut y avoir plusieurs espaces de noms de montage .

# awk '$9 == "proc" {print FILENAME,$0}' /proc/*/task/*/mountinfo | sort -k2 -u
/proc/1070/task/1070/mountinfo 15 19 0:3 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
/proc/19877/task/19877/mountinfo 50 49 0:3 / /run/netns/a rw,nosuid,nodev,noexec,relatime shared:2 - proc proc rw
/proc/19877/task/19877/mountinfo 57 40 0:3 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw
/proc/1070/task/1070/mountinfo 66 39 0:3 / /run/netns/a rw,nosuid,nodev,noexec,relatime shared:2 - proc proc rw
/proc/19877/task/19877/mountinfo 68 67 0:3 / /mnt/1/a rw,nosuid,nodev,noexec,relatime unbindable - proc proc rw

Ceux /mnt/1/a-ci /run/netns/apeuvent être des fichiers d'espace de noms.

Nous pouvons obtenir un numéro d'inode:

# nsenter --mount=/proc/19877/task/19877/ns/mnt -- ls -Li /mnt/1/a
4026532471 /mnt/1/a

Mais cela ne nous dit pas grand-chose d'autre que ce n'est pas dans la liste calculée ci-dessus.

Nous pouvons essayer de le saisir comme l'un des différents types:

# nsenter --mount=/proc/19877/task/19877/ns/mnt -- nsenter --pid=/mnt/1/a true
nsenter: reassociate to namespace 'ns/pid' failed: Invalid argument
# nsenter --mount=/proc/19877/task/19877/ns/mnt -- nsenter --mount=/mnt/1/a true
nsenter: reassociate to namespace 'ns/mnt' failed: Invalid argument
# nsenter --mount=/proc/19877/task/19877/ns/mnt -- nsenter --net=/mnt/1/a true
#

OK, c'était un netfichier d'espace de noms.

Il semblerait donc que nous ayons une méthode pour répertorier les espaces de noms: répertorier les nsrépertoires de toutes les tâches, puis trouver tous les procpoints de montage dans tous les /proc/*/task/*/mountinfoet déterminer leur type en essayant de les saisir.

Stéphane Chazelas
la source
19

Si vous avez util-linux v2.28 ou supérieur, vous pouvez utiliser lsns :

# lsns
        NS TYPE  NPROCS   PID USER             COMMAND
4026531836 pid       78     1 root             /sbin/init
4026531837 user      79     1 root             /sbin/init
4026531838 uts       78     1 root             /sbin/init
4026531839 ipc       78     1 root             /sbin/init
4026531840 mnt       75     1 root             /sbin/init
4026531857 mnt        1    12 root             kdevtmpfs
4026531957 net       79     1 root             /sbin/init
4026532393 mnt        1  1214 root             /lib/systemd/systemd-udevd
4026532415 mnt        1  2930 systemd-timesync /lib/systemd/systemd-timesyncd
4026532477 mnt        1 32596 root             -bash
4026532478 uts        1 32596 root             -bash
4026532479 ipc        1 32596 root             -bash
4026532480 pid        1 32596 root             -bash

Correction: lsns n'est pas disponible dans util-linux v2.27 comme le disait cette réponse. Voir https://www.kernel.org/pub/linux/utils/util-linux/v2.28/v2.28-ReleaseNotes

Rfraile
la source
Il y a aussi un joli script python que j'ai trouvé, pour ceux sur Linux plus ancien. opencloudblog.com/?p=251
Neil McGill
lsnsest très utile mais il ne montre que le PID le plus bas dans chaque espace de noms - c'est-à-dire qu'il ne peut pas vous dire l'espace de noms pour tout PID arbitraire. +1 de toute façon, car c'est toujours une réponse utile même si elle ne répond pas directement à la question.
cas
9
$ ip netns identify $PID

$PIDest l'ID de processus du processus, que vous pouvez obtenir de différentes manières.

http://man7.org/linux/man-pages/man8/ip-netns.8.html

Ken Sharp
la source
1
Notez que c'est uniquement pour les espaces de noms réseau et uniquement ceux créés à l'aide ip netns(ou au moins créés par quelque chose qui lie les portes des espaces de noms dans / run / netns comme le ip netnsfait). Il recherche essentiellement dans / run / netns des fichiers identiques à /proc/$PID/ns/net.
Stéphane Chazelas
Quelle? /run/netnsn'existe même pas sur mon ordinateur.
Ken Sharp
/run/netnsou partout où ipbind-monte les fichiers spéciaux d'espace de noms. findmnt -t nsfspeut vous dire où il se trouve sur votre système. OTOH, si vous le faites unshare -n sleep 1000 & ip netns identify "$!", vous n'obtiendrez rien.
Stéphane Chazelas
findmnt -t nsfs- rien. unshare -n sleep 1000 & ip netns identify "$!"- unshare: unshare a échoué: opération non autorisée
Ken Sharp
Vous avez besoin des privilèges de superutilisateur (capacité CAP_SYS_ADMIN) pour créer un nouveau réseau. findmnt -t nsfsle fait de ne rien renvoyer suggère que vous n'avez pas de réseau sur l'ATM de votre machine.
Stéphane Chazelas
9

psa maintenant des options de sortie pour les différents types de namespaces associés aux processus: ipcns, mntns, netns, pidns, usernset utsns. Pour cette question, le plus pertinent est l'espace de noms PID, ou pidns.

donc si vous vouliez trouver l'identifiant de l'espace de noms PID pour, par exemple, le pid 459:

# ps -h -o pidns -p 459
4026532661

et pour répertorier tous les processus dans cet espace de noms:

ps -o pidns,pid,cmd | awk '$1==4026532661'

ou avec pgrep, vous pouvez passer directement d'un PID à une liste de tous les processus partageant le même espace de noms PID:

pgrep -a --ns 459

Contrairement à ps, pgreppeut limiter la sortie à un espace de noms spécifique (si vous connaissez le PID de l'un des processus qu'il contient), mais a des capacités de formatage de sortie très limitées (PID uniquement, ou PID et leurs lignes de commande)

Vous pouvez toujours diriger la sortie de pgrep --ns 459vers xargs ps -fbien pour récupérer les informations dont vous avez besoin sur le processus.

cas
la source
0

Espace de noms-Lister :

Vous pouvez utiliser listns.py

Utilisation: ./listns.pyou python2 listns.pyPour répondre précisément à cette question, vous pouvez grep le résultat comme ceci python2 listns.py | grep $PID(remplacez la variable pid)

Source: github-mirror et article tout crédit à Ralf Trezeciak

Espaces de noms réseau :

Pour l'espace de noms réseau, ip netns identify $PIDpeut être utilisé.

Nsutils

Indiquez pidnslistque renvoyer l'espace de noms pid d'un processus

$ pidnslist -ss 8782
pid:[4026531836] 
intika
la source