Ausgabe über FIFO verteilen

Ausgabe über FIFO verteilen

Ich versuche, sehr lange Make-Ausgaben mit der folgenden Methode zu verteilen

mkfifo myfifo 
make 2>&1 | tee myfifo | grep -E "errors|warnings" myfifo > errors.log | cat myfifo

Die Idee ist, dass ein Teil der Ausgabe in Protokolldateien kopiert werden soll, während die gesamte Ausgabe zur Standardausgabe der Konsole umgeleitet wird.

Zunächst scheint es zu funktionieren, stoppt dann aber plötzlich und bleibt eingefroren, bis ich Strg-Z drücke.

Eine Anwendung der Prozesssubstitution

make 2>&1 | tee >(grep -E "errors|warnings" > errors.log)

ist nicht möglich, da die Shell standardmäßig mit strikter POSIX-Konformität kompiliert wurde.

Plattform – Ubuntu-Distribution. Shell Bash 4.2 (und nur eine verfügbar)

Antwort1

Das

make 2>&1 | tee myfifo | grep -E "errors|warnings" myfifo > errors.log | cat myfifo
          P1           P2                                              P3

Befehl macht wenig Sinn. Er startet diese 4 Befehle gleichzeitig mit Pipes dazwischen:

  • make 2>&1: stdout und stderr gehen an P1
  • tee myfifo: stdin von P1, stdout nach P2. teeSchreibt also die Ausgabe sowohl nach P1 myfifoals auch nach P2.
  • grep -E "errors|warnings" myfifo > errors.log: stdin von P2, aber Sie übergeben einen Dateinamen ( myfifo) an grep, also grepwird nicht von dessen stdin gelesen. stdout geht an errors.log, nichts wird an P3 geschrieben
  • cat myfifo: stdin von P3, aber da wieder catein Dateiname angegeben wird, wird dieser stattdessen gelesen. Also grepwerden beide gleichzeitig catgelesen myfifo.

Da nichts von P2 gelesen wird, teebleibt es hängen, wenn P2 voll ist. Außerdem catwerden die Teile von nicht angezeigt, myfifodie von gelesen wurden grep.

make 2>&1 | tee myfifo | grep -e errors -e warnings > errors.log | cat myfifo

kommt dem, was Sie meinten, näher, denke ich. Auch hier wird P3 nicht verwendet, aber wir verwenden es, |um gleichzeitig zu starten catund darauf zu warten.

Oder Sie könnten Folgendes tun:

make 2>&1 | tee myfifo & grep -e errors -e warnings > errors.log
wait

Wenn Sie mehr s benötigen grep, benötigen Sie mehr FIFOs:

make 2>&1 | tee fifo2grep1 fifo2grep2 &
grep errors fifo2grep1 > errors.log &
grep warnings fifo2grep2 > warnings.log
wait

Auf Systemen, die dies unterstützen /dev/fd/x, können Sie außerdem Folgendes tun:

make 2>&1 | { tee /dev/fd/3 | grep -e errors -e warnings 3>&-; } 3>&1

(das ist normalerweise, was die Prozesssubstitution in Shells macht, die sie unterstützen).

Mit 2 greps wird daraus:

make 2>&1 |
 {
   {
     tee /dev/fd/3 /dev/fd/4 |
       grep errors > errors.log 3>&- 4>&-
   } 4>&1 |
     grep warnings > warnings.log 3>&-
 } 3>&1

Antwort2

Nachdem grep -E "errors|warnings" myfifo > errors.logdie Pipe keine Daten mehr enthält, cat myfifowird der nächste Befehl, der aus der Pipe liest, blockiert.

Wenn ich Ihre Frage richtig verstehe, möchten Sie alle Nachrichten auf stdout drucken und alle Fehler- und Warnmeldungen an umleiten errors.log. Wenn Sie also Pipe verwenden möchten, verwenden Sie zwei:

 mkfifo pipe1 pipe2 
 make 2>&1 | tee pipe1 pipe2 | grep -E "errors|warnings" pipe1 > errors.log | cat pipe2

verwandte Informationen