Wie Dateideskriptoren arbeiten?
Kann mir jemand sagen warum das nicht funktioniert? Ich bin Herumspielen mit Datei-Deskriptoren, aber fühle mich ein wenig verloren.
#!/bin/bash
echo "This"
echo "is" >&2
echo "a" >&3
echo "test." >&4
Den ersten drei Zeilen laufen, in Ordnung, aber die letzten beiden Fehler aus. Warum?
Du musst angemeldet sein, um einen Kommentar abzugeben.
File-Deskriptoren 0, 1 und 2 sind für stdin, stdout und stderr, bzw..
Dateideskriptoren 3, 4, .. 9 sind für zusätzliche Dateien. Um Sie zu nutzen, müssen Sie diese vorher geöffnet werden. Zum Beispiel:
Für mehr Informationen werfen Sie einen Blick auf Advanced Bash-Scripting Guide: Kapitel 20. I/O-Umleitung.
exec 3>&1
Ursachenecho hi >&3
zu print "Hallo" zur Standardausgabe ausgegeben.Es ist eine alte Frage, aber eine Sache Bedarf noch der Klärung.
Während die Antworten von Carl Norum und dogbane korrekt sind, ist die Annahme zu ändern Sie Ihr Skript, um es Arbeit.
Was ich möchte darauf hinweisen, dass Sie nicht brauchen, um das Skript ändern,:
Es funktioniert, wenn Sie es aufrufen, anders:
was bedeutet, dass die Umleitung Dateideskriptoren 3 und 4 zu 1 (das ist die standard-Ausgabe).
Der Punkt ist, dass das script ist vollkommen in Ordnung in dem Wunsch, zu schreiben, um die Deskriptoren können als nur 1 und 2 (stdout und stderr) , wenn diese Deskriptoren werden von der übergeordneten Prozess.
Dein Beispiel ist eigentlich ganz interessant, weil dieses Skript schreiben können, um 4 unterschiedliche Dateien:
Nun haben Sie die Ausgabe in 4 separate Dateien:
Was ist interessanter ist, dass Ihr Programm nicht haben, um die Schreibberechtigung für diese Dateien, da es nicht wirklich öffnen.
Zum Beispiel, wenn ich
sudo -s
zu ändern, Benutzer zu root, erstellen Sie ein Verzeichnis als root an, und führen Sie den folgenden Befehl als mein normaler Benutzer (bzw in meinem Fall) wie folgt:Bekomme ich eine Fehlermeldung:
Aber wenn ich die Umleitung außerhalb von
su
:(beachten Sie den Unterschied in Anführungszeichen) es funktioniert und ich bekomme:
sind 4 Dateien, die im Besitz von root in ein Verzeichnis im Besitz von root - auch wenn das script nicht über die Berechtigungen zum erstellen dieser Dateien.
Ein weiteres Beispiel wäre die Verwendung von chroot-Gefängnis oder ein container und ein Programm ausführen im inneren, wo es hätte nicht auf diese Dateien zugreifen, auch wenn es als root laufen und trotzdem umleiten diejenigen Deskriptoren außen, wo Sie brauchen, ohne tatsächlich Zugriff auf das gesamte file-system oder irgendetwas anderes zu diesem Skript.
Der Punkt ist, dass Sie haben entdeckt, ein sehr interessanter und nützlicher Mechanismus. Sie müssen nicht zu öffnen, alle Dateien in Ihrem Skript, wie vorgeschlagen wurde, in anderen Antworten. Manchmal ist es nützlich, lenken Sie während der Skript-Aufruf.
Um es zusammenzufassen, diese:
ist eigentlich äquivalent zu:
ausführen des Programms als:
ist das gleiche wie:
Die Nummer 1 ist einfach nur ein Standard-Zahl, und es ist stdout.
Aber auch dieses Programm:
kann produzieren ein "Bad descriptor" Fehler. Wie? Bei der Ausführung als:
Ist die Ausgabe:
Hinzufügen
>&-
(das ist das gleiche wie1>&-
) bedeutet die Schließung der standard-Ausgabe. Hinzufügen2>&-
würde bedeuten, schließen die stderr.Können Sie selbst tun eine etwas komplizierte Sache. Ihre ursprüngliche Drehbuch:
beim ausführen mit nur:
Drucke:
Aber Sie können Deskriptoren 3 und 4 funktionieren, aber die Nummer 1 scheitern, indem Sie Folgendes ausführen:
It-Ausgänge:
Wenn Sie wollen-Deskriptoren 1 und 2 fehlschlagen, führen Sie es wie folgt:
Erhalten Sie:
Warum? Nicht alles, was scheitern? Es hat aber ohne stderr (file descriptor Nummer 2) Sie nicht sehen, die Fehler Meldungen!!!
Ich denke, es ist sehr nützlich, zu Experimentieren, auf diese Weise zu erhalten ein Gefühl von wie die Deskriptoren und Ihre Umleitung arbeiten.
Dein script ist ein sehr Interessantes Beispiel in der Tat - und ich behaupte, dass , es ist nicht gebrochen, Sie waren nur mit es falsch! 🙂
./fdtest
ohne3>&1 4>&1
gibt es eine Möglichkeit fürfdtest
zu bestimmen, dass die Dateideskriptoren 3 und 4 nicht gibt?Es fehlschlägt, weil diese Datei-Deskriptoren, nicht Punkt-zu nichts! Die normale Standard-file-Deskriptoren sind die standard-Eingabe
0
, die standard-Ausgabe1
, und die standard-Fehler-stream2
. Da Ihr Skript nicht öffnen andere Dateien, es gibt keine anderen gültigen Datei-Deskriptoren. Sie können eine Datei öffnen, in der bash mitexec
. Hier ist eine änderung Ihrer Beispiel:"Und jetzt werden wir es:
Wie Sie sehen können, die extra-Ausgabe gesendet wurde, um die angeforderten Dateien.
stdout
oderstderr
. Warum würden Sie brauchen oder nutzen wollen, andere Dateien für, die?Hinzufügen auf der Antwort von rsp und beantworten Sie die Frage in den Kommentaren der Antwort von @MattClimbs.
Können Sie testen, ob der Dateideskriptor geöffnet ist oder nicht, indem Sie versuchen, einen redirect zu früh und wenn es scheitert, öffnen Sie die gewünschte nummerierte Datei-Deskriptor für so etwas wie
/dev/null
. Ich mache das regelmäßig in Skripten und nutzen Sie die zusätzliche Datei-Deskriptoren zu pass zurück weitere details oder Antworten überreturn #
.script.sh
Die stderr umgeleitet
/dev/null
zu verwerfen möglichbash: #: Bad file descriptor
Antwort und die||
wird verwendet, um den Prozess der folgende Befehlexec #>/dev/null
wenn die Vorherige beendet mit einem nicht-null-status. In dem Fall, dass der Datei-Deskriptor ist bereits geöffnet, die beiden tests zurückkehren würde eine null-status und dieexec ...
Befehl nicht ausgeführt werden.Aufruf des scripts ohne Umleitungen ergibt:
In diesem Fall, die Umleitungen für
a
undtest
sind aus-geliefert zu/dev/null
Ruft das script mit einer Umleitung definiert ergibt:
Die erste Umleitung
3>temp.txt
überschreibt die Dateitemp.txt
während4>>temp.txt
fügt an die Datei an.In das Ende können Sie festlegen, default-Dateien umgeleitet, um in den Skript-wenn Sie möchten, etwas anderes als
/dev/null
oder ändern Sie können die Ausführung der Methode an das Skript und leiten diese zusätzliche Datei-Deskriptoren, wohin Sie wollen.