1. Betrachten Sie Snippet Nr. 1:
$ cat test.txt > test.txt
cat: test.txt: input file is output file
Es scheint, dass cat
der Deskriptor der Eingabedatei auf test.txt verweist. Wenn er dann versucht, den Deskriptor der Ausgabedatei auf test.txt zu setzen, wird der obige Fehler ausgegeben. Hier scheint cat
der Redirect-Operator bekannt zu sein und versucht daher, den Ausgabedateideskriptor auf test.txt zu setzen
2. Betrachten Sie Snippet Nr. 2:
$ cat 1.txt
1:CAT
2:dog
$ sed 's/cat/CAT/g' test.txt
1:CAT
2:dog
$ sed 's/cat/CAT/g' test.txt > test.txt
$ cat test.txt # Note that test.txt is now empty
$
Hier sehen wir, dass sed
test.txt (letztes Argument) im Lesemodus geöffnet und gleichzeitig test.txt
als Dateiausgabedeskriptor festgelegt wird. Außerdem '>'
überschreibt der Bediener den Inhalt der Datei, BEVOR er sed
mit dem Lesen beginnt.
Mir ist bekannt, dass Befehle in einer Pipeline parallel ausgeführt werden, aber keine Informationen über das Verhalten von Umleitungsoperatoren gefunden wurden. Alle unterstützenden Links wären hilfreich.
quelle
Antworten:
Zusätzlich zu den Unterlagen jordanm Punkte, möchte ich sicherstellen, eine falsche Vorstellung in Ihrer Frage das ausgeführte Programm dargestellt zu korrigieren ist nicht Umleitungen zu behandeln. Es ist ihnen kaum bewusst. Die Shell verarbeitet Weiterleitungen.
Ein Programm wird mit drei geöffneten Dateien gestartet: stdin (# 0), stdout (# 1) und stderr (# 2). Wenn Sie nur ein Programm über Ihre Shell-Eingabeaufforderung ausführen, werden diese mit Ihrem Endgerät verbunden, sodass das Programm liest, was Sie eingeben (stdin), und Ausgabe (stdout) und Fehler (stderr) auf Ihr Terminal druckt.
Als Beispiel laufe ich einfach
cat
in einem Terminal (wastty
heißt/dev/pts/31
). Ich kann überprüfen, mit welchen Dateien es geöffnet istlsof
:In der Tat können wir sehen, dass das Terminal für alle drei geöffnet ist. Versuchen wir stattdessen einen ziemlich albernen Katzenaufruf :
cat < /dev/zero > /dev/null 2>/dev/full
, der alle drei umleitet:Die Shell implementierte diese Umleitungen, indem sie die drei Geräte als stdin, stdout und stderr (anstelle des Terminals) übergab. Die Schale implementiert in ähnlicher Weise Rohre. Versuchen wir es
cat | dd > /dev/null
(eine ziemlich dumme Pfeife):Beachten Sie, wie die Shell ein Rohr geöffnet hat und es verwendet hat, um das stdout von
cat
mit dem stdin von zu verbindendd
. Und weiter , wie es angeschlossendd
ist stdout/dev/null
.Die ausgeführten Befehle kennen die Umleitungen nicht wirklich. Sie verwenden einfach stdin, stdout, stderr wie gewohnt. Dies können alle das Terminal sein oder sie können zu / von einer Datei, einem Gerät oder einer Pipe zu einem anderen Programm umgeleitet werden. Oder sogar einen Netzwerk-Socket, wenn Ihre Shell dies unterstützt.
Selbst die lächerlich kompliziertesten Pipelines sind nur Anweisungen an die Shell, wie diese drei Dateihandles verbunden werden, bevor das Programm ausgeführt wird.
(HINWEIS: Einige Programme verhalten sich anders, wenn eines davon an ein Terminal angeschlossen ist. Bei interaktiver Verwendung ist dies jedoch normalerweise benutzerfreundlicher. Wechselt beispielsweise
ls
zur einspaltigen Ausgabe und zu keiner Farbe, wenn stdout nicht a ist Terminal - das ist normalerweise das, was Sie möchten, wenn Sie es an ein anderes Programm übergeben möchten. Einige Programme behandeln die Eingabeaufforderung anders, wenn stdin kein Terminal ist. Und so weiter.)quelle
cat
hinter den Kulissen funktioniert, und zum Glück haben Sie das illustriert.Die Umleitung erfolgt zuerst in der Shell. In Ihrem Beispiel:
Das erste, was passiert, ist das Öffnen von Bash
test.txt
, wodurch die Datei abgeschnitten wird. Es ist jetzt leer, bevorcat
estest.txt
als Argument ausgeführt wird.Aus dem Umleitungsbereich der Bash-Manpage:
Ich sehe in der POSIX-Spezifikation nichts, was darauf hindeutet, dass es zuerst auftreten sollte, aber mir ist keine Shell bekannt, in der dies nicht der Fall ist.
quelle