Linux-Tools-Pipe-Verhalten: Ist es ein Fehler oder ein Feature?

Indeks
  1. Warum haben einige Programme andere Ausgaben, wenn sie gepiped werden?
  2. Und wie tun sie das?
  3. Einige Beispiele für pipe-fähige Befehle
    1. Fortschrittsanzeige
    2. Trennung von Ausgabe und Fehler

Entdecken Sie die Funktionsweise von Pipes in der Linux-Befehlszeile, wie sie Ausgaben verändern und warum dies entscheidend für effiziente Datenverarbeitung ist.

Wenn Sie Erfahrung mit der Linux-Befehlszeile haben, haben Sie wahrscheinlich eine Pipe verwendet, um Aufgaben durch die Kombination einfacher Programme zu lösen. So funktioniert UNIX.

Eine Pipe verbindet den Ausgabe-Stream eines Programms mit dem Eingangs-Stream eines anderen. Hinter den Kulissen kann jedoch mehr vor sich gehen, als es den Anschein hat.

Warum haben einige Programme andere Ausgaben, wenn sie gepiped werden?

Werfen Sie einen Blick auf ls, einen der gebräuchlichsten und nützlichsten Befehle. Sie wissen wahrscheinlich, wie es funktioniert:

Wenn Sie ls ohne Argumente und ohne spezielle Konfiguration ausführen, erhalten Sie eine Liste von Dateien im aktuellen Verzeichnis, im mehrspaltigen Format. Schauen Sie sich jedoch an, was passiert, wenn Sie ls pipen:

Hier benutze ich cat, um die Auswirkungen des Pipelining der ls-Ausgabe zu demonstrieren. Sie können die Ausgabe von ls auch in eine Datei umleiten, mit einem Befehl wie ls > outputfile.

Es ist nicht nur ls, das dies tut. Warum ist eine solche Funktion unter Linux-Programmen also so verbreitet? Es stellt sich heraus, dass die spezielle Handhabung von gepipten Ausgaben aus mehreren Gründen nützlich sein kann.

Im Fall von ls und anderen Werkzeugen, die formatierte Ausgaben erzeugen, ist es sinnvoll, diese Ausgabe zu vereinfachen, wenn sie gepiped wird. Der Befehl, an den Sie pipen, erwartet Eingaben im Format "eine pro Zeile" nach der gängigen Unix-Konvention von zeilenorientierten Werkzeugen. Wenn ls seine spaltenbasierte Ausgabe an andere Programme senden würde, fänden diese es schwierig, sie genau zu parsen.

Einige Programme, insbesondere neuere, formatieren ihre normale Ausgabe noch signifikanter, indem sie ANSI-Sequenzen verwenden, um Text zu färben oder kursiv zu setzen. Solcher Text wäre für andere Werkzeuge kompliziert zu parsen, und jegliche zusätzliche Arbeit, die notwendig ist, um die Eingabe zu verarbeiten, ist unerwünscht.

Und wie tun sie das?

Wenn Sie ein Programm ausführen, übergibt Ihre Shell Datei-Deskriptoren für die Standard-Eingabe, -Ausgabe und -Fehlerstreams. Typischerweise sind diese mit Ihrem Terminal verbunden, sodass die Tasten, die Sie drücken, über die Standard-Eingabe ankommen und die Ausgabe des Programms auf Ihrem Bildschirm erscheint. Sie können diese Streams jedoch auch woanders hin senden, über Pipes oder Dateiumleitungen.

Meistens kümmert sich ein Programm nicht um diese Details. Wenn die Eingabe von Ihrer Tastatur oder einem anderen Prozess kommt, behandelt ein Werkzeug wie grep sie identisch. Dies gibt uns sehr leistungsfähige Werkzeuge, die wir auf verschiedene Weise kombinieren können. Dennoch kann es, wie im Beispiel von ls oben, vorkommen, dass ein Programm gelegentlich wissen muss, ob ein Eingabe- oder Ausgabestrom mit dem Terminal oder etwas anderem verbunden ist. Dafür gibt es die C-Bibliotheksfunktion isatty:

#include <unistd.h> int isatty(int fd); 

Diese Funktion nimmt einen ganzzahligen Dateideskriptor und gibt 1 zurück, wenn er sich auf ein Terminal bezieht, andernfalls 0. Der Dateideskriptor kann jede ganze Zahl sein, aber die Werte 0, 1 und 2 sind für stdin, stdout und stderr reserviert.

Es gibt eine höherstufige Entsprechung, die Sie in Shell-Skripten verwenden können: den -t Test. Dies ist eine sehr enge Entsprechung der isatty-Funktion:

#!/bin/bash if test -t 0; then echo "Standard-Eingabe ist ein Terminal" else echo "Standard-Eingabe ist KEIN Terminal" fi 

Das Programm verhält sich genau so, wie Sie es sich wünschen und erwarten:

Einige Beispiele für pipe-fähige Befehle

Wie oben erwähnt, funktioniert ls anders, wenn es gepiped wird, und verhält sich im Wesentlichen so, als ob die -1-Option übergeben worden wäre. Wenn Sie aus irgendeinem Grund dieses Verhalten überschreiben möchten, verwenden Sie einfach die -C-Option:

Der ps-Befehl gibt Informationen über laufende Prozesse aus, einschließlich des Befehls, der jeden Prozess gestartet hat. Da Befehle jedoch sehr lang sein können, kürzt das Programm den vollständigen Befehl, um ihn in Ihr Terminal zu passen:

Wenn Sie jedoch die ps-Ausgabe in eine Datei pipen, besteht kein Bedarf für diese Kürzung, sodass das Programm vollständige Befehle ausgibt:

Grep ist ein leistungsfähiges Werkzeug, mit dem Sie in Dateien nach regulären Ausdruckmustern suchen können. Seine Farbausgabe hebt Übereinstimmungen entsprechend hervor:

Wenn jedoch diese Ausgabe umgeleitet wird, handelt grep vernünftig und hört auf, die speziellen Steuerzeichen zu erzeugen, die diese Farben steuern. Andernfalls – und das können Sie mit grep --color=always testen – könnten Sie am Ende eine Datei erhalten, die so aussieht:

Schließlich ist curl eine der interessantesten Anwendungen der Erkennung des Ausgabe-Streams. Wenn Sie ihm eine URL übergeben, druckt das Programm.

Wenn Sie jedoch diese Ausgabe in eine Datei umleiten, macht curl etwas Besseres, als nur still zu bleiben:

Fortschrittsanzeige

Obwohl Sie es auf diesem Screenshot nicht sehen können, zeigt curl einen dynamischen Fortschrittsbalken, der sich aktualisiert, während Ihre Anfrage heruntergeladen wird. Das ist für eine kleine Webseite nicht sehr nützlich, aber bei größeren Antworten, einschließlich großer Datei-Downloads, kann diese Ausgabe äußerst hilfreich sein. Wie macht curl das, während es gleichzeitig Ihre Ausgabe in die Datei umleitet? Es sendet die Fortschrittsinformationen an stderr, nicht an stdout.

Trennung von Ausgabe und Fehler

Sie könnten dies als einen kleinen Missbrauch von stderr betrachten, aber es ist eine clevere Möglichkeit, die normale Ausgabe und die Fortschrittsinformationen getrennt zu halten. Wenn Sie möchten, können Sie curl anweisen, standardmäßig einen Fortschrittsbalken anzuzeigen, und Sie können die Ausgabe oder Fehler immer nach Ihren Wünschen umleiten, unabhängig voneinander.

Bist du neugierig auf weitere Artikel wie Linux-Tools-Pipe-Verhalten: Ist es ein Fehler oder ein Feature?? Entdecke spannende Inhalte in der Kategorie Linux.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Go up