Tee não obtém saída inteira do tubo

11

Eu tenho um script executando comandos como:

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH;./some_app -i $INDEX | tee $LOG
echo "Number of errors: $(grep "ERROR" $LOG | wc -l)"

O problema provavelmente está no cano para tee. Parece que não obtém toda a saída. Quando o aplicativo sai, faltam as últimas linhas da saída (geralmente aquelas que contêm um erro fatal). Quando executo o aplicativo sem canal tee, os recebo na saída.

Como forçar o script a aguardar que o tee conclua o processamento de toda a saída?

Ladislav Mrnka
fonte
Funciona bem se você o adiciona a um arquivo, não ao stdout?
Pilot6

Respostas:

22

O erro fatal provavelmente está saindo em STDERR (2), não em STDOUT (1). Você pode redirecionar o STDERR para o STDOUT com 2>&1e o pipe também deve capturá-lo.

./some_app -i $INDEX 2>&1 | tee $LOG

Se você tiver problemas de armazenamento em buffer, poderá forçá-lo a um estado sem buffer:

stdbuf -o0 ./some_app -i $INDEX 2>&1 | tee $LOG
Oli
fonte
Bom, estamos nos aproximando. Agora vejo que um erro fatal está sendo impresso, mas novamente não está completo. A linha com o erro acaba no meio e a saída do eco continua. Ainda há algum problema com o buffer de liberação ou simplesmente aguardando a conclusão dessa parte.
Ladislav Mrnka
Editado. Bastante raro na minha experiência, que algo desliza completamente através de buffers na saída, mas vale a pena tentar.
Oli
1
Feito! Obrigado. Posso estar fazendo muitas perguntas, mas alguém entende por que eu preciso desativar o buffer ao canalizar para outro processo?
Ladislav Mrnka
@ Oli Um muito bom!
Pilot6
6

Como as mensagens de erro normalmente são mostradas no STDERR (descritor de arquivo 2), você precisa redirecionar o STDOUT e o STDERR para tee:

./some_app -i "$INDEX" |& tee "$LOG"

Quando você ./some_app -i $INDEX | tee $LOGestá redirecionando apenas o STDOUT para tee.

|& fará com que STDOUT e STDERR sejam redirecionados.

Se você não pode redirecionar apenas o STDOUT (como estava):

./some_app -i "$INDEX" | tee "$LOG"

Por outro lado, se você deseja redirecionar apenas o STDERR:

./some_app -i "$INDEX" 2>&1 >/dev/null | tee "$LOG"
heemail
fonte