GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Der tragbare (posix) Weg zur Prozesssubstitution?

Einige Shells, wie bash , unterstützen Process Substitution, was eine Möglichkeit ist, die Prozessausgabe als Datei darzustellen, wie hier:

$ diff <(sort file1) <(sort file2)

Dieses Konstrukt ist jedoch nicht POSIX und daher nicht portierbar. Wie kann eine Prozesssubstitution POSIX-freundlich erreicht werden (d. h. eine, die in /bin/sh funktioniert ) ?

Hinweis:Die Frage ist nicht, wie man zwei sortierte Dateien unterscheidet – das ist nur ein erfundenes Beispiel, um die Prozesssubstitution zu demonstrieren!

Akzeptierte Antwort:

Diese Funktion wurde von ksh eingeführt (zuerst dokumentiert in ksh86) und nutzte den /dev/fd/n feature
(in einigen BSDs und AT&T-Systemen früher unabhängig hinzugefügt).
In ksh und bis zu ksh93u würde es nicht funktionieren, es sei denn, Ihr System hätte Unterstützung für /dev/fd/n . zsh, bash und ksh93u+ und höher können temporäre benannte Pipes (in System III hinzugefügte benannte Pipes) verwenden, wobei /dev/fd/n sind nicht verfügbar.

Auf Systemen, auf denen /dev/fd/n verfügbar ist (POSIX gibt diese nicht an),
können Sie eine Prozesssubstitution durchführen (z. B. diff <(cmd1) <(cmd2)). ) selbst mit:

{
  cmd1 4<&- | {
    # in here fd 3 points to the reading end of the pipe
    # from cmd1, while fd 0 has been restored from the original
    # stdin (saved on fd 4, now closed as no longer needed)

    cmd2 3<&- | diff /dev/fd/3 -

  } 3<&0 <&4 4<&- # restore the original stdin for cmd2

} 4<&0 # save a copy of stdin for cmd2

Allerdings funktioniert das nicht mit ksh93 Unter Linux wie dort werden Shell-Pipes mit Socketpairs anstelle von Pipes und dem Öffnen von /dev/fd/3 implementiert wobei fd 3 auf einen Socket zeigt, funktioniert nicht unter Linux.

Obwohl POSIX /dev/fd/n , gibt es benannte Pipes an. Benannte Pipes funktionieren wie normale Pipes, außer dass Sie vom Dateisystem darauf zugreifen können. Das Problem hier ist, dass Sie temporäre erstellen und danach bereinigen müssen, was schwer zuverlässig ist, insbesondere wenn man bedenkt, dass POSIX keinen Standardmechanismus hat (wie ein mktemp -d wie es auf einigen Systemen zu finden ist), um temporäre Dateien oder Verzeichnisse zu erstellen, und die Signalverarbeitung (um beim Auflegen oder Beenden aufzuräumen) ist ebenfalls schwer portierbar.

Sie könnten so etwas tun:

tmpfifo() (
  n=0
  until
    fifo=$1.$$.$n
    mkfifo -m 600 -- "$fifo" 2> /dev/null
  do
    n=$((n + 1))
    # give up after 20 attempts as it could be a permanent condition
    # that prevents us from creating fifos. You'd need to raise that
    # limit if you intend to create (and use at the same time)
    # more than 20 fifos in your script
    [ "$n" -lt 20 ] || exit 1
  done
  printf '%s\n' "$fifo"
)

cleanup() { rm -f -- "$fifo"; }

fifo=$(tmpfifo /tmp/fifo) || exit

cmd2 > "$fifo" & cmd1 | diff - "$fifo"

cleanup

(Hier wird nicht auf die Signalbehandlung geachtet).

Verwandte:Prozess sofort nach dem Öffnen des Terminals abgeschlossen und es ist unmöglich, Befehle hinzuzufügen?
Linux
  1. Neuer übergeordneter Prozess, wenn der übergeordnete Prozess stirbt?

  2. Der maximale Wert der Prozess-ID?

  3. Linux – Der tragbare Weg, um die Standard-Routen-Quelladresse zu erhalten?

  4. Die Ausgabe der Prozesssubstitution ist nicht in Ordnung?

  5. Der schnellste Weg, ein Iso zu extrahieren?

Anpassen von Grub auf einfache Weise:Grub-Customizer

SIGTERM vs. SIGKILL:Was ist der Unterschied?

Prozesssubstitution:Eine ungewöhnliche, aber fortschrittliche Methode zur Eingabe-/Ausgabeumleitung in Linux

Postman Ubuntu 18.04 installieren:Der einfachste Weg!

Gibt es eine Möglichkeit, die Umgebungsvariablen eines anderen Prozesses in Unix zu ändern?

Was ist der beste Weg, um ein Signal an alle Mitglieder einer Prozessgruppe zu senden?