distribuir la salida a través de FIFO

distribuir la salida a través de FIFO

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 P1
  • tee myfifo: entrada estándar desde P1, salida estándar a P2. Entonces teeescribe la salida tanto en como myfifoen P2.
  • grep -E "errors|warnings" myfifo > errors.log: stdin de P2 pero le está pasando un nombre de archivo ( myfifo) grep, por lo que grepno leerá desde su stdin. La salida estándar va a errors.log, nada escribe en P3.
  • cat myfifo: stdin de P3 pero nuevamente, cuando catse le da un nombre de archivo, lo lee. Entonces ambos grepy catleen myfifosimultáneamente.

Como no se lee nada de P2, teese bloqueará cuando P2 esté lleno. Tampoco catse mostrarán las partes myfifoque 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 catsimultáneamente y esperar.

O podrías hacer:

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

Si necesitas más greps, 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 greps, 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.logla 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

información relacionada