output tanto stderr quanto stdout no console e armazena-os em um arquivo ao mesmo tempo

4

posso produzir stdout e stderr na tela do console e armazenar um deles em um arquivo de log?

Eu escrevo um script de shell de teste:

#!/bin/sh

echo OUT! >&1
echo ERR! >&2

Eu posso enviar os dois na tela apenas executando o script:

$./test 
OUT!
ERR!

Eu posso gerar stderr e capturar stdout no arquivo de log por:

$./test | tee 1>log
ERR!

$cat log 
OUT!

Não consigo produzir nada além de capturar todos os stdout e stderro no arquivo de log por:

$./test 2>&1| tee 1>log

$cat log 
OUT!
ERR!

Eu posso produzir os dois stdout e stderr e capturar todos eles em um arquivo de log:

$./test 2>&1 | tee log
OUT!
ERR!

$cat log 
OUT!
ERR!

Eu posso produzir ambos podem pegar stdout no arquivo de log por:

$./test | tee 2>&1 log
ERR!
OUT!

$cat log 
OUT!

Minhas perguntas são:

  1. como apenas a saída stdout e pegar stderr no arquivo? (Eu tentei ./test|tee 2>log , mas não funciona)
  2. como apenas produzir ambos e pegar stderr no arquivo?
por How Chen 04.01.2015 / 04:41

2 respostas

5
  1. how to just output stdout and catch stderr into file?(I tried ./test|tee 2>log, but doesn't work)
$ ./test 2>log
OUT!
$ cat log
ERR!
  1. how to just output both and catch stderr into file?
$ ./test 2>&1 >/dev/tty | tee log
OUT!
ERR!
$ cat log
ERR!

Se essa expressão fosse parte de um pipeline maior, convém evitar o uso de /dev/tty . Uma maneira de fazer isso é trocar stdout e stderr. Para fazer essa troca, precisamos criar um terceiro identificador de arquivo da seguinte forma:

$ exec 3>&1; ./test 2>&1 1>&3 | tee log; exec 3>&-
OUT!
ERR!
$ cat log
ERR!

A primeira instrução, exec 3>&1 , atribui o identificador de arquivo 3 ao stdout atual (o que quer que seja). Em seguida, ./test 2>&1 1>&3 | tee log canaliza o stderr para o comando tee enquanto envia stdout para o identificador de arquivo 3. Por fim, para uma boa limpeza, exec 3>&- fecha o identificador de arquivo 3.

Notas e comentários adicionais

Em relação a:

I can output stderr and catch stdout into log file by:

$./test | tee 1>log
ERR!
$cat log 
OUT!

Isso pode ser simplificado para:

$ ./test >log
ERR!
$ cat log
OUT!

Além disso, em relação a:

I can output nothing but catch all stdout and stderro into log file by:

$ ./test 2>&1| tee 1>log
$ cat log 
OUT!
ERR!

Isso pode ser simplificado para:

$ ./test >log 2>&1
$ cat log
OUT!
ERR!

Ou, com bash , mas não o shell POSIX, uma forma ainda mais simples é possível:

$ ./test &>log
$ cat log
OUT!
ERR!
    
por 04.01.2015 / 04:51
5

Os redirecionamentos de shells devem ser bastante suficientes. Primeiro, redirecionar stderr para um arquivo ...

$ ./test 2> myfile.txt

Aqui, stdout permanece na tela, pois não foi redirecionado. myfile.txt conterá ERR.

Então, se você quiser produzir ambos, e ainda capturar stderr em um arquivo, você provavelmente terá que ir em duas etapas com uma pequena substituição de comando ...

$ ./test 2> >(tee myfile.txt >&2)

Isso enviará o fluxo de erro para o processo tee , que será reimpresso. stdout permanece intocado. Para mais informações, dê uma olhada nesta questão do Stack Overflow .

Da mesma forma, se você quiser capturar stdout em um arquivo e deixar stderr intocado ...

$ ./test > >(tee myfile.txt)
    
por 04.01.2015 / 04:51