
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 P1tee myfifo
: stdin de P1, stdout para P2. Entãotee
escreve a saída para ambosmyfifo
e P2.grep -E "errors|warnings" myfifo > errors.log
: stdin de P2, mas você está passando um nome de arquivo (myfifo
) paragrep
, portantogrep
não lerá seu stdin. stdout vai paraerrors.log
, nada grava em P3cat myfifo
: stdin de P3 mas, novamente, comocat
recebe um nome de arquivo, ele o lê. Então, ambosgrep
ecat
lidosmyfifo
simultaneamente.
Como nada é lido em P2, tee
irá travar quando P2 estiver cheio. Também cat
não exibirá as partes myfifo
que 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 cat
simultaneamente 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 grep
s, 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 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
Responder2
Depois que grep -E "errors|warnings" myfifo > errors.log
o pipe não contém mais dados. Portanto, o próximo comando cat myfifo
lido 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