Copie stdout e stderr para um arquivo de log e deixe-os no console dentro do próprio script

7

Usando bash, como copio stderr e stdout para um arquivo de log e também os deixo exibidos no console?

Eu gostaria de fazer isso dentro do próprio script usando um exec.

Eu tentei com

exec &>> log.out

echo "This is stdout"
echo "This is stderr" >&2

Mas o acima não imprime nada no console. Como posso conseguir isso em bash?

    
por adarshr 12.03.2013 / 12:47

4 respostas

8

Você está procurando por tee .

Veja man tee para detalhes.

Para combiná-lo com exec , você precisa usar substituição de processo . (Veja man bash para detalhes).

exec &> >(tee  log.out)
echo "This is stdout"
echo "This is stderr" >&2
    
por 12.03.2013 / 12:49
3

Você pode fazer:

: > log # empty log file if necessary
{ { {

  ...the script

} 3>&- | tee -a log >&3 3>&-
exit "${PIPESTATUS[0]}"
} 2>&1 | tee -a log >&2 3>&-
} 3>&1
exit "${PIPESTATUS[0]}"

Você também pode escrever como:

: > log # empty log file if necessary
exec 2> >(tee -a log >&2) > >(tee -a log)

...the script

Mas porque bash não está esperando por aqueles processos iniciados com >(... ), isso tem o efeito desagradável de algumas vezes enviar algo para o terminal após o comando ter retornado, o que pode ter efeitos ainda mais desagradáveis (como descartar silenciosamente essa saída) o terminal "tostop" atributo está ativado.

Em qualquer caso, tornando stdout um canal em ambas as soluções, e porque dois comandos emitem independentemente as mensagens de saída e erro, isso afetará o buffer de saída e a ordem em que as mensagens de saída e erro serão exibidas.

    
por 12.03.2013 / 14:04
3

Eu sei que este é um post antigo, mas por que não fazer isso?

echo "hi" >> log.txt #stdout -> log
echo "hi" | tee -a log.txt #stdout -> log & stdout
echo "hi" &>> log.txt #stdout & stderr -> log
echo "hi" |& tee -a log.txt #stdout & stderr -> log & stdout

E, claro, se você quiser stdout, basta imprimir regularmente.

Você pode fazer isso com qualquer combinação de fluxos que desejar, usando apenas esses dois comandos básicos.

Eu sei que vim até aqui e não obtive uma resposta fácil de entender / implementar, espero que isso ajude a outra pessoa que está com dificuldades.

A propósito, para noobs lá fora como no meu self anterior, todo o comando tee faz a saída stdin para o stdout e o (s) arquivo (s) especificado (s) como argumentos subseqüentes. -a significa acrescentar, assim você não sobrescreve o arquivo com todo uso do comando. Se você tiver outras dúvidas, eu acho que isso é um recurso muito útil para aprender rapidamente bash.

    
por 01.08.2017 / 22:01
1

Mais uma maneira de fazer isso é usar redirecionamentos dentro de funções.

#!/bin/bash

function1 () {
    echo 'STDOUT from function 1'
    echo 'STDERR from function 1' >&2
}

function2 () {
    echo 'STDOUT from function 2'
    echo 'STDERR from function 2' >&2
}


function3 () {
    echo 'STDOUT from function 3'
    echo 'STDERR from function 3' >&2
}

main() {
    function1
    function2
    function3
}

main 2>&1 |tee log.txt

Aqui temos uma função main que invoca todas as outras funções. Agora redirecionando a função STDOUT e STDERR of main para tee .

    
por 24.10.2014 / 16:50