10 votes

Pourquoi '>' ne redirige-t-il pas les messages d'erreur de gcc ?

J'ai enregistré le programme suivant dans new.c

int main() 
{ 
    a;
    return 0; 
}

Il renvoie un message d'erreur. Je veux envoyer ce message dans un fichier. J'ai donc utilisé la commande suivante

gcc new.c > temp.txt

Mais je recevais toujours la sortie sur le terminal. J'utilise Ubuntu 13.04. Comment puis-je le faire fonctionner ?

17voto

Sandeep Sherpur Points 109

Lorsque vous compilez un programme avec gcc il existe différents types de sortie : pour stdout y stderr . Normalement, le > dirigera stdout vers un fichier (par exemple, le résultat d'un printf("hello world\n"); est envoyé à stdout ). Cependant, le stderr continue d'être envoyé à l'écran, car il est supposé être "quelque chose d'exceptionnel dont il faut vous informer".

Il existe un moyen de rediriger stderr vers un fichier - vous le faites avec la commande suivante (pas très intuitive) :

gcc new.c &> myFile

&> est un "raccourci bash" pour "rediriger tout". Comme l'a souligné @CharlesDuffy, la forme conforme à POSIX est

gcc new.c > myFile 2>&1

Cela signifie "compiler 'new.c' et envoyer stdout a myFile . Et envoyez stderr (2) au même endroit que stdout ( &1 = "le même endroit que stdout").

Vous trouverez plus de détails sur les différentes redirections à l'adresse suivante http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html y http://mywiki.wooledge.org/BashFAQ/055

A propos, si vous voulez envoyer quelque chose depuis votre programme spécifiquement à stderr vous pouvez le faire avec les éléments suivants

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

Si vous incluez cela dans un programme, exécutez le programme et envoyez la sortie "normale" dans un fichier, cela apparaîtra toujours sur la console. Donc si vous compilez ce qui précède dans l'exécutable urgent puis tapez

./urgent > /dev/null

à la console, votre sortie apparaîtra à l'écran.

11voto

RAC Points 916

Porque > redirige uniquement stdout, et les erreurs sont écrites dans le fichier stderr vous devez utiliser l'une des options suivantes à la place :

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

&> est une extension de BASH qui redirige à la fois stdout y stderr vers un fichier ; sinon, l'approche la plus simple consiste à rediriger d'abord stdout ( >temp.txt ), et ensuite faire de stderr (FD 2) une copie de l'identifiant de fichier déjà redirigé sur stdout (FD 1), comme ceci : 2>&1 .

4voto

Adam Liss Points 306

Comme les autres l'ont dit, linux fournit deux flux de sortie différents :

stdout ou "sortie standard" est l'endroit où vont toutes les sorties régulières.
              Vous pouvez le référencer en utilisant le descripteur de fichier 1 .

stderr ou "erreur standard" est un flux séparé pour les informations hors bande.
              Vous pouvez le référencer en utilisant le descripteur de fichier 2 .

Pourquoi deux flux de sortie différents ? Considérons un pipeline de commandes imaginaires :

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

Maintenant, imaginez le decrypt échoue et génère un message d'erreur. S'il envoie ce message à stdout Il l'envoie dans le tube, et à moins qu'il ne contienne le mot "secret", vous ne le verrez jamais. Donc vous vous retrouveriez avec un fichier de sortie vide, sans aucune idée de ce qui a mal tourné.

Cependant, puisque le tuyau ne capture que stdout le decrypt peut envoyer ses erreurs à stderr où ils seront affichés sur la console.

Vous pouvez rediriger stdout y stderr ensemble ou indépendamment :

# 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

Vous pouvez rediriger les erreurs vers stdout et les traiter comme s'il s'agissait d'une sortie normale :

# 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

Vous pouvez également utiliser une notation " raccourcie " pour rediriger les deux stdout et stderr dans le même fichier :

decrypt $MY_FILE &> output.txt

Et, enfin, le > L'opérateur commencera par tronqué son fichier de sortie avant d'y écrire. Si, au contraire, vous souhaitez ajouter dans un fichier existant, utilisez la fonction >> opérateur :

decrypt $MY_FILE 2>> more_errors.txt >> more_secrets.txt
decrypt $MY_FILE >> more_output.txt 2>&1

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X