Zum Lesen aus dem Dateideskriptor 6 kann ich <&6
oder </dev/fd/6
(aka /proc/self/fd/6
) verwenden. Normalerweise funktionieren beide gleich gut. Wenn dieser Dateideskriptor jedoch ein Socket ist, passieren seltsame Dinge. Beispielsweise:
$ 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
Hier ls
zeigt sich, dass der Deskriptor tatsächlich vorhanden ist. Ein Zugriff auf die Daten ist auf diese Weise jedoch nicht möglich. Wenn ich cat <&6
stattdessen benutze, funktioniert alles wieder gut.
Was ist der Unterschied zwischen beiden Arten des Zugriffs auf den Dateideskriptor?
Gibt es eine gute Möglichkeit, auf einen Deskriptor zuzugreifen, wenn die Nummer in einer Variablen angegeben ist? ( </dev/fd/$fd
würde funktionieren, <&$fd
tut es aber nicht.)
(Die obige Situation kann unter Linux beobachtet werden, aber nicht unter OpenBSD. - Der Dateideskriptor scheint dort ein normales Zeichengerät zu sein.)
quelle
Antworten:
/dev/fd/
Dies liegt daran, dass das Lesen von Einträgen, die Sockets darstellen, unter Linux nicht implementiert ist. Eine gute Beschreibung der Argumentation finden Sie hier. Sie können alsostat
auf den Linkls
zugreifen , und deshalb sehen Sie ihn mit , aber der Zugriff ist absichtlich nicht zulässig.Nun zum zweiten Teil - warum funktioniert das
bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345
? Dies liegt daran, dass der Socket von der Socket / Datei-API und nicht vom/proc
Dateisystem gelesen wird . Folgendes habe ich beobachtet:bash
Die in Ihrem Terminal ausgeführte Instanz erstellt einen Socket mit fd 6.bash
läuft und ruft andup2(6, 0)
, um Ihren Socket alscat
's anzuschließenstdin
.dup2
Anruf nicht fehlgeschlagen ist, liest die Katze ausstdin
.Sie können es reproduzieren und beobachten mit:
Wenn Sie sich fragen, warum der
bash
untergeordnete Prozess Zugriff auf fd 6 hat - Dateideskriptoren überlebenfork
, und wenn sie nicht zum Schließen markiert sindexec
, werden sie dort auch nicht geschlossen.quelle
Um Ihre direkte Frage zu beantworten: " Was ist der Unterschied ?":
Wenn Sie von umleiten
<&6
, verwendet die Shell einendup2()
Systemaufruf, um den Dateideskriptor zu duplizieren. Wenn Sie (versuchen) umzuleiten</dev/fd/6
, wird es verwendetopen()
.Der Kernel unterstützt
open()
Sockets in nicht/dev/fd
. sie sind in dem Verzeichnis fürDekorationnur Informationen.quelle