
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 P1tee myfifo
: stdin von P1, stdout nach P2.tee
Schreibt also die Ausgabe sowohl nach P1myfifo
als auch nach P2.grep -E "errors|warnings" myfifo > errors.log
: stdin von P2, aber Sie übergeben einen Dateinamen (myfifo
) angrep
, alsogrep
wird nicht von dessen stdin gelesen. stdout geht anerrors.log
, nichts wird an P3 geschriebencat myfifo
: stdin von P3, aber da wiedercat
ein Dateiname angegeben wird, wird dieser stattdessen gelesen. Alsogrep
werden beide gleichzeitigcat
gelesenmyfifo
.
Da nichts von P2 gelesen wird, tee
bleibt es hängen, wenn P2 voll ist. Außerdem cat
werden die Teile von nicht angezeigt, myfifo
die 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 cat
und 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 grep
s 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.log
die Pipe keine Daten mehr enthält, cat myfifo
wird 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