
Estoy intentando distribuir resultados de creación muy largos utilizando el siguiente método
mkfifo myfifo
make 2>&1 | tee myfifo | grep -E "errors|warnings" myfifo > errors.log | cat myfifo
La idea es que un subconjunto de resultados se copie en archivos de registro, mientras que el resultado completo se redirija a la salida estándar de la consola.
Al principio parece funcionar, pero de repente se detiene y permanece congelado hasta que presiono Ctrl-Z.
Un uso de la sustitución de procesos.
make 2>&1 | tee >(grep -E "errors|warnings" > errors.log)
no es posible, porque el shell se compiló con el estricto cumplimiento de POSIX predeterminado.
plataforma - distribución con sabor a ubuntu. shell bash 4.2 (y solo uno disponible)
Respuesta1
Eso
make 2>&1 | tee myfifo | grep -E "errors|warnings" myfifo > errors.log | cat myfifo
P1 P2 P3
El comando tiene poco sentido. Inicia esos 4 comandos al mismo tiempo con tuberías intermedias:
make 2>&1
: stdout y stderr van a P1tee myfifo
: entrada estándar desde P1, salida estándar a P2. Entoncestee
escribe la salida tanto en comomyfifo
en P2.grep -E "errors|warnings" myfifo > errors.log
: stdin de P2 pero le está pasando un nombre de archivo (myfifo
)grep
, por lo quegrep
no leerá desde su stdin. La salida estándar va aerrors.log
, nada escribe en P3.cat myfifo
: stdin de P3 pero nuevamente, cuandocat
se le da un nombre de archivo, lo lee. Entonces ambosgrep
ycat
leenmyfifo
simultáneamente.
Como no se lee nada de P2, tee
se bloqueará cuando P2 esté lleno. Tampoco cat
se mostrarán las partes myfifo
que han sido leídas por grep
.
make 2>&1 | tee myfifo | grep -e errors -e warnings > errors.log | cat myfifo
Está más cerca de lo que quisiste decir, creo. Nuevamente, no se usa P3, pero estamos usando |
para iniciar cat
simultáneamente y esperar.
O podrías hacer:
make 2>&1 | tee myfifo & grep -e errors -e warnings > errors.log
wait
Si necesitas más grep
s, necesitas más fifos:
make 2>&1 | tee fifo2grep1 fifo2grep2 &
grep errors fifo2grep1 > errors.log &
grep warnings fifo2grep2 > warnings.log
wait
En sistemas que soportan /dev/fd/x
, también puedes hacer:
make 2>&1 | { tee /dev/fd/3 | grep -e errors -e warnings 3>&-; } 3>&1
(Eso es típicamente lo que hace la sustitución de procesos en los shells que lo admiten).
Con 2 grep
s, eso se convierte en:
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
Respuesta2
Después de que grep -E "errors|warnings" myfifo > errors.log
la tubería ya no contenga datos. Por lo tanto cat myfifo
, se bloqueará el siguiente comando que se lea desde la tubería.
Si entiendo su pregunta correctamente, desea imprimir todos los mensajes en la salida estándar y redirigir todos los mensajes de error y advertencia a errors.log
. Entonces, si quieres usar pipe, usa dos:
mkfifo pipe1 pipe2
make 2>&1 | tee pipe1 pipe2 | grep -E "errors|warnings" pipe1 > errors.log | cat pipe2