distribuir a produção através do FIFO

distribuir a produção através do FIFO

Estou tentando distribuir uma saída make muito longa usando o seguinte método

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

A ideia é que o subconjunto da saída seja copiado para os arquivos de log, enquanto toda a saída seria redirecionada para o stdout do console.

Parece funcionar no início, mas de repente para e permanece congelado até eu pressionar Ctrl-Z.

Um uso de substituição de processo

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

não é possível, porque o shell foi compilado com conformidade estrita com POSIX padrão.

plataforma - distro com sabor de Ubuntu. shell bash 4.2 (e apenas um disponível)

Responder1

Que

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

comando faz pouco sentido. Ele inicia esses 4 comandos simultaneamente com pipes intermediários:

  • make 2>&1: stdout e stderr vão para P1
  • tee myfifo: stdin de P1, stdout para P2. Então teeescreve a saída para ambos myfifoe P2.
  • grep -E "errors|warnings" myfifo > errors.log: stdin de P2, mas você está passando um nome de arquivo ( myfifo) para grep, portanto grepnão lerá seu stdin. stdout vai para errors.log, nada grava em P3
  • cat myfifo: stdin de P3 mas, novamente, como catrecebe um nome de arquivo, ele o lê. Então, ambos grepe catlidos myfifosimultaneamente.

Como nada é lido em P2, teeirá travar quando P2 estiver cheio. Também catnão exibirá as partes myfifoque foram lidas por grep.

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

está mais próximo do que você quis dizer, eu acho. Novamente, P3 não é usado, mas estamos usando o |para iniciar catsimultaneamente e esperar por ele.

Ou você poderia fazer:

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

Se precisar de mais greps, você precisa de mais fifos:

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

Em sistemas que suportam /dev/fd/x, você também pode fazer:

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

(normalmente é isso que a substituição de processos faz em shells que a suportam).

Com 2 greps, isso se torna:

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

Responder2

Depois que grep -E "errors|warnings" myfifo > errors.logo pipe não contém mais dados. Portanto, o próximo comando cat myfifolido no pipe será bloqueado.

Se entendi sua pergunta corretamente, você deseja imprimir todas as mensagens em stdout e redirecionar todas as mensagens de erro e aviso para errors.log. Então, se você quiser usar pipe, use dois:

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

informação relacionada