Aus Raspberry Pi Geek 08/2022

Datenströme mit Pipes umleiten (Seite 2)

Abbildung 2: Mit Pipes lassen sich beliebig viele Kommandos miteinander verknüpfen.

Abbildung 2: Mit Pipes lassen sich beliebig viele Kommandos miteinander verknüpfen.

Die Richtung der Umlenkung gibt bei anonymen Pipes die Shell vor. Sie erfolgt immer von links nach rechts. Der komplette Durchlauf der Kommandokette beendet alle Prozesse und hebt die Umlenkungen auf.

In manchen Aufrufen und Skripts benötigt man Pipes aber längerfristig oder für mehrere Prozesse. In diesem Fall kommen benannte Pipes zum Einsatz. Sie liegen wie andere Dateien im File-System, überstehen aber einen Reboot. Sie lassen sich von mehreren Prozessen verwenden, wobei der Datenfluss lesend und schreibend ohne Einschränkung erfolgt.

Benannte Pipes

Um eine dauerhafte Pipe zu erzeugen, verwenden Sie das Kommando mkfifo. Das Beispiel aus Listing 2 legt die Pipe /var/tmp/testpipe an. Mittels ls sehen Sie den Erfolg der Aktion. Der Marker p ganz links in der Ausgabe (Zeile 3) weist darauf hin, dass es sich um eine Pipe handelt. In diese lässt sich nun die Ausgabe eines Kommandos umlenken. Das Kommando wartet so lange mit dem Abarbeiten, bis ein anderer Prozess die Pipe ausliest (Listing 3).

Listing 2

Benannte Pipe anlegen

$ mkfifo /var/tmp/testpipe
$ ls -l /var/tmp/testpipe
prw-r--r-- 1 root root 0 Jan 4 23:35 /var/tmp/testpipe

Listing 3

Benannte Pipes verwenden

### Session 1: Schreiben
$ echo "3.1415" >/var/tmp/testpipe
### Session 2: Lesen
$ ls -l /var/tmp/testpipe
prw-r--r- 1 root root 0 Jan 4 23:35 /var/tmp/testpipe
$ pi=$(cat /var/tmp/testpipe)
$ ls -l /var/tmp/testpipe
prw-r--r- 1 root root 0 Jan 4 23:42 /var/tmp/testpipe
$ echo $pi
3.1415

Sie erkennen, dass der Aufruf den Zeitstempel von 23:35 Uhr nach dem Auslesen auf 23:42 Uhr setzt. Die Größe der Datei beträgt aber nach wie vor 0 Byte, da die Pipe ja theoretisch nur Daten durchreicht. Tatsächlich stellt das Betriebssystem aber einen Puffer bereit, der jedoch in der allgemeinen Handhabung keine Rolle spielt.

Dass aus Sicht der Prozesse das Schreiben in eine Pipe erst mit dem Auslesen beginnt, lässt sich an einem einfachen Beispiel zeigen. In einer Session schreibt ein Aufruf das aktuelle Datum mit Uhrzeit in die Variable start und deren Inhalt danach in die Pipe. Im Anschluss liest er nochmals Datum und Uhrzeit und speichert sie in der Variablen ende. Deren Wert schreibt der Prozess ebenfalls sofort in die Pipe. Die zweite Session liest beide Zeilen aus der Pipe und gibt sie aus.

Um zu zeigen, dass die Ausgabe tatsächlich innerhalb kürzester Zeit geschieht, starten wir zuerst einen Testlauf ohne Umlenkung (Listing 4). Nun werden nochmals die beiden Variablen mit Zeitstempeln belegt und die Ausgaben jeweils in die Pipe geschrieben. Kurz darauf wird aus einer zweiten Session die Pipe Zeile für Zeile ausgelesen und das Ergebnis auf dem Bildschirm ausgegeben (Listing 5). Sie sehen, dass eine Differenz von etlichen Sekunden zwischen Start und Ende liegt. Die Differenz ergibt sich aus der Tatsache, dass der zweite Zeitstempel erst nach dem Lesen der ersten Zeile aus der Pipe entsteht.

Listing 4

Variablen festlegen

# start=$(date +'%H:%M:%S') ; echo $start
# ende=$(date +'%H:%M:%S'); echo $ende
23:04:44
23:04:44

Listing 5

Pipe auslesen

### Terminal 1:
$ start=`date +'%H:%M:%S'` ; echo $start >/var/tmp/testpipe ; ende=`date +'%H:%M:%S'` ; echo $ende >/var/tmp/testpipe
### Terminal 2:
$ read start </var/tmp/testpipe ; read ende </var/tmp/testpipe ; echo "Start: $start" ; echo "Ende: $ende"
Start: 23:08:40
Ende: 23:08:52

Anwendungsbeispiel

Das folgende Beispiel realisiert eine Netzwerkverbindung auf Basis benannter Pipes, die dazu dient, auf einem entfernten Rechner Kommandos auszuführen.

Der interessante Aspekt für die Kommunikation zwischen zwei Rechnern besteht darin, dass es für den lesenden oder schreibenden Prozess keine Rolle spielt, was vor oder hinter der Pipe geschieht, da sich das Lesen und Schreiben für den jeweiligen Prozess nicht ändert. Das Beispiel setzt voraus, dass zwischen den beiden verwendeten Rechnern ein Zugang ohne Passwort erfolgt, im Beispiel via SSH.

Das Kommando ssh erlaubt es, neben dem Zielrechner auch eine Kommandokette zu übergeben. Das Konstrukt baut sich dann so auf wie in der ersten Zeile von Listing 6. SSH nimmt in diesem Fall die Verbindung zum Zielsystem auf, führt die angegebenen Kommandos aus und beendet danach die Verbindung. Einfacher wäre es, eine Funktion aufzurufen, die ein auszuführendes Kommando übergeben bekommt, es auf dem anderen Rechner ausführt und die Ausgabe auf dem lokalen Bildschirm ausgibt (zweite Zeile).

Listing 6

Remote-Befehl

$ ssh [-q] Ziel "Befehl1 [; Befehl2 [;...]]"
$ rcmd "Befehl1 [; Befehl2 [;...]]"
DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 6 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
RASPBERRY PI GEEK KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Raspberry Pi Geek bei Google Play Readly Logo
Nach oben