Wie können einige Terminalprogramme Umleitungen und Pipes ignorieren?

370
Hanlon

Ich habe heute Abend mit meiner Netzwerkkarte herumgespielt, als ich beim Laufen etwas bemerkte ip link help. Hier zwei Fälle, in denen ich etwas anderes bemerkt habe:

ip link help | grep set 

und

ip link help > ip_link_help.txt 

Der erste Befehl hat keine Auswirkung, dh, anstatt die Ausgabe von ip link helpvon stdoutbis umzuleiten grep, wird die Pipe einfach ignoriert und die Ausgabe von ip link helpwird an den gesendet stdout.

Der zweite Fall ist etwas anders. Obwohl ip link helpignoriert das Symbol Umleitung >und druckt nur auf die stdout, Datei file.txtwird trotzdem erstellt (aber es ist leer).

0

1 Antwort auf die Frage

3
Kamil Maciorowski

ip link helpdruckt auf Standardfehler (stderr, Dateideskriptor 2); seine Standardausgabe (stdout, Dateideskriptor 1) erhält keine Daten. Normalerweise gehen die beiden Streams zum Terminal, sodass Sie sie auf den ersten Blick nicht wirklich unterscheiden können. |oder >beeinflusst die Standardausgabe. Nachdem Sie es verwendet haben, wissen Sie, dass alle Daten, die umgeleitet werden, für stdout bestimmt sein müssen. alles andere - nach anderswo: in der Regel zu stderr, obwohl einige Programme einige Daten direkt auf das Terminal drucken ( ipgehört nicht dazu).

In Ihrem ersten Fall können Sie stderr zum Dateideskriptor von stdout umleiten und dann eine Pipe erstellen:

ip link help 2>&1 | grep set 

Dabei 2>&1wird der Shell mitgeteilt, dass sie den Dateideskriptor auf das umleiten soll, auf das 2der Dateideskriptor 1verweist. Mit dieser Syntax würde alles, wenn der Befehl etwas an stdout und stderr gedruckt hat, zustande kommen grep.

Im zweiten Fall erstellt die Shell die Datei (falls erforderlich) und schneidet sie ab, bevor sie ausgeführt ipwird. Sie können dies durch Aufrufen von sehen

a_command_that_doesnt_even_exist > foo.txt 

foo.txtwird trotz des offensichtlichen Fehlers erstellt. Dies liegt daran, dass es zuerst erstellt wird, noch bevor die Shell den Befehl ausführt.

Um stderr in der Datei zu erfassen, verwenden Sie nur 2>die Weiterleitung von stderr:

ip link help 2> ip_link_help.txt 

1>Leitet ähnlich nur stdout um. Kurz, das >Sie verwendet haben, ist absolut gleichwertig 1>.


Ein künstliches Beispiel für einen Befehl, der auf drei verschiedene Arten an das Terminal druckt, ist

echo "standard output"; echo "standard error" >&2; echo "terminal" >/dev/tty 

Die Ausgabe ist:

standard output standard error terminal 

Sie können die ersten beiden Zeilen problemlos umleiten. Versuche dies:

(echo "standard output"; echo "standard error" >&2; echo "terminal" >/dev/tty) >stdout.txt 2>stderr.txt 

Dadurch wird jedoch immer noch die letzte Zeile gedruckt.

@ JakeGould Ich werde keinen Bearbeitungskrieg beginnen, habe mich aber bewusst dafür entschieden, Code (den eigentlichen Code, der * zur Ausführung gedacht ist) von zufälliger Ausgabe zu unterscheiden, der * nicht * -Code ist (er soll nicht ausgeführt werden; dennoch ist er es Vorteile wie Formatieren von Code). Kamil Maciorowski vor 5 Jahren 0
Es wird allgemein akzeptiert, dass die Terminalausgabe auch als 'Code' angezeigt werden kann. Das Hinzufügen von Anführungszeichen zu diesem Code wird auf keinen der Stack Exchange-Standorte durchgeführt. JakeGould vor 5 Jahren 0
@JakeGould Es gibt immer Raum für Verbesserungen. :) Kamil Maciorowski vor 5 Jahren 0