Por que não '' redireciona mensagens de erro do gcc?

9

Eu armazenei o seguinte programa em new.c

int main() 
{ 
    a;
    return 0; 
}

Retorna uma mensagem de erro. Eu quero enviar esta mensagem para um arquivo. Então eu usei o seguinte comando

gcc new.c > temp.txt

Mas ainda assim eu estava recebendo a saída no terminal. Eu estou usando o Ubuntu 13.04. Como posso fazer isso funcionar?

    
por Alex 22.06.2013 / 15:08

3 respostas

15

Quando você compila um programa com gcc , existem diferentes tipos de saída: para stdout e stderr . Normalmente, o > direcionará stdout stream para um arquivo (por exemplo, o resultado de um printf("hello world\n"); é enviado para stdout ). No entanto, o stderr continua a ser enviado para a tela, já que é considerado "algo excepcional que você precisa saber".

Existe uma maneira de redirecionar o stderr para um arquivo - você faz isso com o seguinte comando (não muito intuitivo):

gcc new.c &> myFile

onde &> é "shorthand" para "redirecionar tudo". Como foi apontado por @CharlesDuffy, o formulário compatível com POSIX é

gcc new.c > myFile 2>&1

Isso significa "compile 'new.c' e envie stdout para myFile . E envie stderr (2) para o mesmo local que stdout ( &1 =" o mesmo lugar que stdout " ).

Você encontrará mais detalhes sobre diferentes redirecionamentos no link e link

A propósito, se você quiser enviar algo de dentro do seu programa especificamente para stderr , você pode fazê-lo com o seguinte

fprintf(stderr, "hello world - this is urgent.\n");

Se você incluir isso em um programa, executar o programa e enviar a saída "normal" para um arquivo, isso ainda aparecerá no console. Então, se você compilar o arquivo acima no executável urgent , digite

./urgent > /dev/null

no console, sua saída aparecerá na tela.

    
por 22.06.2013 / 15:14
11

Como > redireciona apenas stdout e os erros são gravados em stderr , é necessário usar um dos seguintes itens:

gcc new.c &> temp.txt ## redirect both stdout and stderr using bash or zsh only

... ou ...

gcc new.c >temp.txt 2>&1 ## redirect both stdout and stderr in any POSIX shell

&> é uma extensão BASH que redireciona os arquivos stdout e stderr para um arquivo; caso contrário, a abordagem mais fácil é primeiro redirecionar o stdout ( >temp.txt ) e, em seguida, tornar stderr (FD 2) uma cópia do identificador de arquivo já redirecionado no stdout (FD 1), assim: 2>&1 .

    
por 22.06.2013 / 15:13
4

Como os outros disseram, o linux fornece dois fluxos de saída diferentes:

stdout , ou "saída padrão" é onde toda a saída regular vai.
Você pode referenciá-lo usando o descritor de arquivo 1 .

stderr , ou "erro padrão" é um fluxo separado para informações fora de banda.
Você pode referenciá-lo usando o descritor de arquivo 2 .

Por que dois fluxos de saída diferentes? Considere um pipeline de comandos imaginários:

 decrypt $MY_FILE | grep "secret" | sort > secrets.txt

Agora imagine que o comando decrypt falhe e gere uma mensagem de erro. Se ele enviasse essa mensagem para stdout , ela seria enviada para o canal e, a menos que tivesse a palavra "secreta", você nunca a veria. Então você acabaria com um arquivo de saída vazio, sem ideia do que deu errado.

No entanto, como o pipe captura apenas stdout , o comando decrypt pode enviar seus erros para stderr , onde eles serão exibidos no console.

Você pode redirecionar stdout e stderr , juntos ou independentemente:

# Send errors to "errors.txt" and output to "secrets.txt"
# The following two lines are equivalent, as ">" means "1>"
decrypt $MY_FILE 2> errors.txt > secrets.txt
decrypt $MY_FILE 2> errors.txt 1> secrets.txt

Você pode redirecionar os erros para stdout e processá-los como se fossem uma saída normal:

# The operation "2>&1" means "redirect file descriptor 2 to file
# descriptor 1. So this sends all output from stderr to stdout.
# Note that the order of redirection is important.
decrypt $MY_FILE > errors.txt 2>&1 

# This may be confusing.  It will store the normal output in a file
# and send error messages to stdout, where they'll be captured by 
# the pipe and then sorted.
decrypt $MY_FILE 2>&1 > output.txt | sort

Você também pode usar uma notação "abreviada" para redirecionar ambos stdout e stderr para o mesmo arquivo:

decrypt $MY_FILE &> output.txt

E, finalmente, o operador > irá primeiro truncar seu arquivo de saída antes de gravar nele. Se, em vez disso, você quiser anexar dados a um arquivo existente, use o operador >> :

decrypt $MY_FILE 2>> more_errors.txt >> more_secrets.txt
decrypt $MY_FILE >> more_output.txt 2>&1
    
por 22.06.2013 / 15:59

Tags