distribui a saída pelo FIFO

2

Estou tentando distribuir um resultado muito longo usando o seguinte método

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

Idéia é que o subconjunto de saída deve ser copiado para os arquivos de log, enquanto a saída inteira seria redirecionada para o stdout do console.

Parece funcionar no começo, mas de repente pára e permanece congelado até que eu pressione 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 compilado com a conformidade estrita do padrão POSIX.

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

    
por Swift 24.04.2017 / 16:52

2 respostas

2

Isso

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

faz pouco sentido. Ele inicia esses 4 comandos simultaneamente com os tubos entre eles:

  • make 2>&1 : stdout e stderr vai para P1
  • tee myfifo : stdin de P1, stdout para P2. Portanto, tee grava a saída em myfifo e P2.
  • grep -E "errors|warnings" myfifo > errors.log : stdin de P2, mas você está passando um nome de arquivo ( myfifo ) para grep , então grep não lerá de seu stdin. stdout vai para errors.log , nada grava em P3
  • cat myfifo : stdin do P3, mas como cat recebe um nome de arquivo, ele o lê. Portanto, grep e cat leem myfifo ao mesmo tempo.

Como nada lê de P2, tee irá travar quando P2 estiver cheio. Além disso, cat não exibirá as partes de myfifo que foram lidas por grep .

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

está mais perto do que você quis dizer. Novamente, o P3 não é usado, mas estamos usando o | para iniciar o cat ao mesmo tempo e esperar por ele.

Ou você poderia fazer:

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

Se você precisar de mais grep s, precisará 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 é o que a substituição do processo faz nos shells que a suportam).

Com 2 grep s, 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
    
por 25.04.2017 / 13:39
0

Após grep -E "errors|warnings" myfifo > errors.log , o pipe não contém mais dados. Assim, o próximo comando cat myfifo , que leu o canal, será bloqueado.

Se eu entendi sua pergunta corretamente, você deseja imprimir todas as mensagens para 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
    
por 25.04.2017 / 13:17