Je veux déterminer quel processus a l'autre extrémité d'une prise UNIX.
Plus précisément, je pose une question à propos de celui créé avec socketpair()
, bien que le problème soit le même pour toute prise UNIX.
J'ai un programme parent
qui crée une socketpair(AF_UNIX, SOCK_STREAM, 0, fds)
et fork()
s. Le processus parent ferme fds[1]
Et conserve fds[0]
Pour communiquer. L'enfant fait le contraire, close(fds[0]); s=fds[1]
. Ensuite, l'enfant exec()
s Un autre programme, child1
. Les deux peuvent communiquer en arrière via ce socketpair.
Maintenant, disons que je sais qui parent
est, mais je veux savoir qui child1
Est. Comment puis-je faire cela?
Il y a plusieurs outils à ma disposition, mais aucun ne peut me dire quel processus est à l'autre extrémité de la prise. J'ai essayé:
lsof -c progname
lsof -c parent -c child1
ls -l /proc/$(pidof server)/fd
cat /proc/net/unix
Fondamentalement, je peux voir les deux prises et tout ce qui leur concerne, mais ne peut pas dire qu'ils sont connectés. J'essaie de déterminer quelle fd dans le parent communique avec quel processus enfant.
Vous CANmaintenant Obtenez ces informations avec ss
:
# ss -xp
Maintenant, vous pouvez voir dans la colonne Peer
Colonne (numéro d'inode) qui correspond à un autre ID dans la colonne Local
. Les identifiants correspondants sont les deux extrémités d'une prise.
Noter la UNIX_DIAG
L'option doit être activée dans votre noyau.
Linux n'a pas exposé ces informations à Userland.
Cependant, par à la recherche de la mémoire du noyau , nous pouvons accéder à ces informations.
Remarque: cette réponse le fait en utilisant gdb
, cependant, s'il vous plaît voir @ Stéphanechatzelas 'réponse qui est plus élaboré à cet égard.
# lsof | grep whatever
mysqld 14450 (...) unix 0xffff8801011e8280 (...) /var/run/mysqld/mysqld.sock
mysqld 14450 (...) unix 0xffff8801011e9600 (...) /var/run/mysqld/mysqld.sock
Il y a 2 sockets différentes, 1 écoute et 1 établi. Le numéro hexa est l'adresse au noyau correspondant unix_sock
structure , ayant un attribut peer
étant l'adresse L'autre extrémité de la prise (Aussi un unix_sock
instance de structure).
Maintenant, nous pouvons utiliser gdb
pour trouver le peer
dans la mémoire du noyau:
# gdb /usr/lib/debug/boot/vmlinux-3.2.0-4-AMD64 /proc/kcore
(gdb) print ((struct unix_sock*)0xffff8801011e9600)->peer
$1 = (struct sock *) 0xffff880171f078c0
# lsof | grep 0xffff880171f078c0
mysql 14815 (...) unix 0xffff880171f078c0 (...) socket
Vous y allez, l'autre extrémité de la prise est détenue par mysql
, PID 14815.
Votre noyau doit être compilé avec KCORE_ELF
utiliser /proc/kcore
. De plus, vous avez besoin d'une version de votre image de noyau avec des symboles de débogage. Sur Debian 7, apt-get install linux-image-3.2.0-4-AMD64-dbg
fournira ce fichier.
Si vous n'avez pas (ou ne voulez pas garder) l'image du noyau de débogage sur le système, vous pouvez donner gdb
le décalage de la mémoire sur "manuellement" accéder à la valeur peer
. Cette valeur de compensation diffère généralement avec la version du noyau ou l'architecture.
Sur mon noyau, je sais que le décalage est de 680 octets, soit 85 fois 64 bits. Donc je peux faire:
# gdb /boot/vmlinux-3.2.0-4-AMD64 /proc/kcore
(gdb) print ((void**)0xffff8801011e9600)[85]
$1 = (void *) 0xffff880171f078c0
Voilà, même résultat que ci-dessus.
Si vous avez le même noyau exécuté sur plusieurs machines, il est plus facile d'utiliser cette variante car vous n'avez pas besoin de l'image de débogage, seule la valeur de décalage.
Pour (facilement) découvrir cette valeur de compensation au début, vous avez besoin de l'image de débogage:
$ pahole -C unix_sock /usr/lib/debug/boot/vmlinux-3.2.0-4-AMD64
struct unix_sock {
(...)
struct sock * peer; /* 680 8 */
(...)
}
Vous y allez, 680 octets, il s'agit de 85 x 64 bits, ou 170 x 32 bits.
La majeure partie du crédit pour cette réponse va à MVG .
Erkki Seppala a en fait un outil qui récupère ces informations du noyau Linux avec GDB. C'est disponible ici .
Depuis le noyau Linux 4.2, il existe CONFIG_UNIX_DIAG
, qui fournit des informations supplémentaires sur les prises de domaine UNIX, à savoir le Virtual File System
(VFS) Informations, qui contient les informations manquantes jusqu'à présent pour relier l'inode à partir du chemin du processus. Il peut déjà être interrogé à l'aide de l'outil ss
de iproute2 commençant par la version V4.19.0 ~ 55 :
$ ss --processes --unix --all --extened
...
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
u_str LISTEN 0 5 /tmp/socket 13381347 * 0 users:(("nc",pid=12550,fd=3)) <-> ino:1569897 dev:0/65025 peers:
Le numéro de périphérique et le chemin d'accès Vous pouvez obtenir de
$ stat -c 'ino:%i dev:0/%d' /tmp/socket
ino:1569946 dev:0/65025
ss
prend également en charge le filtrage:
ss --processes --unix --all --extended 'sport = /tmp/socket'
mais sachez que cela pourrait ne pas énumérer la bonne prise pour vous, en tant que Evil Processus Pourriez renommer votre prise d'origine et remplacez-la avec son propre Evil One:
mv /tmp/socket /tmp/socket.orig
nc -U -l /tmp/socket.evil &
mv /tmp/socket.evil /tmp/socket
lsof /tmp/socket
, fuser /tmp/socket
et ss --processes --unix --all --extended 'sport = /tmp/socket'
répertoriera tous le processus d'origine non le remplacement diabolique. Utilisez plutôt quelque chose comme ça:
id=$(stat -c 'ino:%i dev:0/%d' /tmp/socket)
ss --processes --unix --all --extended | grep -F "$id"
Ou écrivez votre propre programme LITTE basé sur le modèle contenu dans Man 7 sock_diag .
4.89 de LSOF Prises en charge Affichage des options de terminaison.
Cité de lsof.8:
+|-E +E specifies that process intercommunication channels should be
displayed with endpoint information and the channels
of the endpoints should also be displayed. Currently
only pipe on Linux is implemented.
Endpoint information is displayed in the NAME column
in the form "PID,cmd,FDmode". PID is the endpoint
process ID; cmd is the endpoint process command; FD is
the endpoint file's descriptor; and mode is the
endpoint file's access mode. Multiple occurrences of
this information can appear in a file's NAME column.
-E specfies that Linux pipe files should only be
displayed with endpoint information.
Exemple de sortie:
mozStorag 21535 22254 yamato 6u unix 0xf... 0t0 348924 type=STREAM pino=351122 4249,dbus-daem,55u
mozStorag 21535 22254 yamato 10u unix 0xf... 0t0 356193 type=STREAM pino=356194 21535,gdbus,11u
mozStorag 21535 22254 yamato 11u unix 0xf... 0t0 356194 type=STREAM pino=356193 21535,gdbus,10u
mozStorag 21535 22254 yamato 21u unix 0xf... 0t0 355141 type=STREAM pino=357544 4249,dbus-daem,60u
mozStorag 21535 22254 yamato 26u unix 0xf... 0t0 351134 type=STREAM pino=355142 5015,gdbus,17u
mozStorag 21535 22254 yamato 69u unix 0xf... 0t0 469354 type=STREAM pino=468160 4545,alsa-sink,21u
mozStorag 21535 22254 yamato 82u unix 0xf... 0t0 449383 type=STREAM pino=449384 12257,Chrome_Ch,3u
mozStorag 21535 22254 yamato 86u unix 0xf... 0t0 355174 type=SEQPACKET pino=355175 21535,gdbus,95u
mozStorag 21535 22254 yamato 95u unix 0xf... 0t0 355175 type=SEQPACKET pino=355174 21535,gdbus,86u 12257,Chrome_Ch,4u
mozStorag 21535 22254 yamato 100u unix 0xf... 0t0 449389 type=STREAM pino=456453 3614,Xorg,38u
mozStorag 21535 22254 yamato 105u unix 0xf... 0t0 582613 type=STREAM pino=586261
obexd 22163 yamato 1u unix 0xf... 0t0 361859 type=STREAM pino=365931
obexd 22163 yamato 2u unix 0xf... 0t0 361860 type=STREAM pino=365934
obexd 22163 yamato 3u unix 0xf... 0t0 361241 type=DGRAM pino=10028
obexd 22163 yamato 6u unix 0xf... 0t0 361242 type=STREAM pino=361864 4249,dbus-daem,70u