Pour lire à partir du descripteur de fichier 6, je peux utiliser <&6
ou </dev/fd/6
(aka /proc/self/fd/6
). Habituellement, les deux fonctionnent aussi bien. Cependant, si ce descripteur de fichier se trouve être un socket, des choses étranges se produisent. Par exemple:
$ bash -c 'ls -l /dev/fd/6;cat /dev/fd/6' 6</dev/tcp/localhost/12345
lrwx------ 1 michas michas 64 Jan 10 19:50 /dev/fd/6 -> socket:[315010]
cat: /dev/fd/6: No such device or address
Ici ls
, le descripteur est bien présent. Mais l'accès aux données n'est pas possible de cette façon. Si j'utilise à la cat <&6
place, tout fonctionne bien à nouveau.
Quelle est la différence entre les deux façons d'accéder au descripteur de fichier?
Existe-t-il un bon moyen d'accéder à un descripteur si le nombre est donné dans une variable? ( </dev/fd/$fd
fonctionnerait, mais <&$fd
ne fonctionne pas.)
(La situation ci-dessus peut être observée sur Linux, mais pas sur OpenBSD. - On dirait que ce descripteur de fichier est un périphérique de caractères normal là-bas.)
la source
Réponses:
C'est parce que la lecture des
/dev/fd/
entrées qui représentent des sockets n'est pas implémentée sous Linux. Vous pouvez trouver un assez bon résumé sur le raisonnement ici. Vous pouvez donc appelerstat
le lien, et c'est pourquoi vous le voyezls
, mais l'accès est délibérément interdit.Maintenant pour la deuxième partie - pourquoi ça
bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345
marche? C'est parce que le socket est lu à l'aide de l'API socket / fichier, pas le/proc
système de fichiers. Voici ce que j'ai observé se produire:bash
l'instance exécutée dans votre terminal crée une socket avec fd 6.bash
court et appelledup2(6, 0)
, afin de fixer votre prise tellecat
quellestdin
.dup2
appel n'a pas manqué, chat lit à partirstdin
.Vous pouvez le reproduire et l'observer avec:
Si vous vous demandez pourquoi le
bash
processus enfant a accès à fd 6 - les descripteurs de fichiers surviventfork
, et s'ils ne sont pas marqués pour la fermetureexec
, ils n'y sont pas fermés également.la source
Pour répondre à votre question directe, " quelle est la différence ?":
Lorsque vous redirigez depuis
<&6
, le shell utilise undup2()
appel système pour dupliquer le descripteur de fichier. Lorsque vous (tentez de) rediriger depuis</dev/fd/6
, il utiliseraopen()
.Le noyau ne prend pas en charge
open()
les sockets dans/dev/fd
; ils sont présents dans le répertoire pour ladécorationd' information seulement.la source