Question

Dans un shell Unix, si je veux combiner stderr et stdout dans le flux stdout pour une manipulation ultérieure, je peux ajouter ce qui suit à la fin de ma commande:

2>&1

Donc, si je veux utiliser head sur la sortie de g ++ , je peux faire quelque chose comme ceci:

g++ lots_of_errors 2>&1 | head

afin que je puisse voir que les premières erreurs.

J'ai toujours du mal à me souvenir de cela, et je dois constamment aller le chercher, principalement parce que je ne comprends pas bien la syntaxe de ce truc en particulier.

Quelqu'un peut-il expliquer cela et expliquer, caractère par caractère, ce que 2 > & amp; 1 signifie?

Était-ce utile?

La solution

Le descripteur de fichier 1 est la sortie standard ( stdout ).
Le descripteur de fichier 2 correspond à l'erreur standard ( stderr ).

Voici un moyen de rappeler cette construction (bien que ce ne soit pas tout à fait précis): au début, 2 > 1 peut sembler être un bon moyen de rediriger stderr vers stdout . Cependant, il sera en réalité interprété comme "rediriger stderr vers un fichier nommé 1 ". & amp; indique que ce qui suit est un descripteur de fichier et non un nom de fichier. La construction devient alors: 2 > & amp <1> code .

Autres conseils

echo test > afile.txt

redirige stdout vers afile.txt . C’est la même chose que de faire

echo test 1> afile.txt

Pour rediriger stderr, vous devez:

echo test 2> afile.txt

> & amp; est la syntaxe permettant de rediriger un flux vers un autre descripteur de fichier: 0 correspond à stdin, 1 à stdout et 2 à stderr.

Vous pouvez rediriger stdout vers stderr en faisant:

echo test 1>&2 # or echo test >&2

Ou vice versa:

echo test 2>&1

En bref, 2 > redirige stderr vers un fichier (non spécifié), en ajoutant & amp; 1 / code> redirige stderr vers stdout.

Quelques astuces sur la redirection

Certaines particularités syntaxiques à ce sujet peuvent avoir des comportements importants. Il existe quelques exemples de redirections, STDERR , STDOUT et des arguments ordering .

1 - Écraser ou ajouter?

Le symbole > signifie redirection .

  • > signifie envoyer à un fichier complet , écrasant la cible si elle existe (voir noclobber fonction bash à # 3 plus tard).
  • > > signifie que envoyer en plus de serait ajouté à la cible s'il existait.

Dans tous les cas, le fichier serait créé s'il n'existait pas.

2 - La ligne de commande du shell est dépendante de l'ordre !!

Pour tester cela, nous avons besoin de une commande simple qui enverra quelque chose sur les deux sorties :

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(Dans l’espoir que vous n’ayez pas de répertoire nommé / tnt , bien sûr;). Eh bien, nous l’avons!

Voyons donc:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

La dernière ligne de commande affiche STDERR sur la console. Il ne semble pas que ce soit le comportement attendu ... Mais ...

Si vous souhaitez effectuer un post-filtrage sur une sortie, sur l’autre ou sur les deux:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

Notez que la dernière ligne de commande de ce paragraphe est identique à celle du paragraphe précédent. semble ne pas être le comportement attendu (donc, il pourrait même s'agir d'un comportement attendu).

Eh bien, il y a quelques astuces sur les redirections, pour opération différente sur les deux sorties :

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

Remarque: le descripteur & 9 apparaîtrait spontanément en raison de ) 9 > & 2 .

Addendum: nota! Avec la nouvelle version de ( & 4.0 ), une nouvelle fonctionnalité et une syntaxe plus sexy permettent de réaliser ce type de tâches:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

Et enfin pour un tel formatage en sortie en cascade:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Addendum: nota! Même syntaxe nouvelle, dans les deux sens:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

STDOUT passe par un filtre spécifique, STDERR et enfin les deux sorties fusionnées passent par un troisième filtre de commande.

3 - Un mot sur l'option noclobber et la syntaxe > |

C'est à peu près l'écrasement :

Bien que set -o noclobber demande à bash de ne pas remplacer les fichiers existants, la syntaxe > | vous permet de franchir cette limitation:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

Le fichier est écrasé à chaque fois, bon maintenant:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

Passez avec > | :

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

Désactiver cette option et / ou se renseigner s’il est déjà défini.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 - Dernier tour et plus encore ...

Pour rediriger les deux résultats d'une commande donnée, nous voyons qu'une syntaxe correcte pourrait être:

$ ls -ld /tmp /tnt >/dev/null 2>&1

pour ce cas spécial , il existe une syntaxe de raccourci: & amp; > ... ou > & amp;

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

Remarque: si 2 > & amp; 1 existent, 1 > & amp; 2 est une syntaxe correcte. aussi:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b- Maintenant, je vais vous laisser réfléchir à:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c - Si vous êtes intéressé par plus d’informations

Vous pouvez lire le manuel en tapant:

man -Len -Pless\ +/^REDIRECTION bash

dans une console; -)

J'ai trouvé cet article génial sur la redirection: Tout sur les redirections

Rediriger la sortie standard et l'erreur standard vers un fichier

  

$ commande & amp; > fichier

Ce one-liner utilise l'opérateur & amp; > pour rediriger les deux flux de sortie - stdout et stderr - de commande en fichier. C'est le raccourci de Bash pour rediriger rapidement les deux flux vers la même destination.

Voici à quoi ressemble le tableau de descripteur de fichier après la redirection des deux flux par Bash:

 Entrez la description de l'image ici

Comme vous pouvez le constater, stdout et stderr désignent maintenant le fichier . Donc, tout ce qui est écrit sur stdout et stderr est écrit dans le fichier .

Il existe plusieurs façons de rediriger les deux flux vers la même destination. Vous pouvez rediriger chaque flux les uns après les autres:

  

$ command > fichier 2 > & amp; 1

Il s'agit d'un moyen beaucoup plus courant de rediriger les deux flux vers un fichier. D'abord, stdout est redirigé vers le fichier, puis stderr est dupliqué pour être identique à stdout. Ainsi, les deux flux finissent par pointer vers le fichier .

Lorsque Bash voit plusieurs redirections, il les traite de gauche à droite. Passons en revue les étapes et voyons comment cela se passe. Avant d'exécuter des commandes, le tableau de descripteur de fichier de Bash se présente comme suit:

 Entrez la description de l'image ici

Maintenant, Bash traite le premier fichier > de redirection. Nous avons déjà vu cela auparavant et cela fait stdout point to file:

 Entrez la description de l'image ici

Next Bash voit la deuxième redirection 2 > & amp; 1. Nous n'avons pas vu cette redirection auparavant. Celui-ci duplique le descripteur de fichier 2 pour être une copie du descripteur de fichier 1 et nous obtenons:

 Entrez la description de l'image ici

Les deux flux ont été redirigés vers un fichier.

Cependant soyez prudent ici! Écriture

  

commande > fichier 2 > & amp; 1

n'est pas la même chose que d'écrire:

  

$ command 2 > & amp; 1 > file

L'ordre des redirections est important dans Bash! Cette commande redirige uniquement la sortie standard vers le fichier. Le stderr continuera d’imprimer sur le terminal. Pour comprendre pourquoi cela se produit, reprenons les étapes. Ainsi, avant d'exécuter la commande, la table de descripteur de fichier se présente comme suit:

 Entrez la description de l'image ici

Bash traite maintenant les redirections de gauche à droite. Il voit d’abord 2 > & 1; il duplique donc stderr sur stdout. La table de descripteur de fichier devient:

 Entrez la description de l'image ici

Bash voit maintenant la deuxième redirection, > fichier , et redirige la sortie standard vers le fichier:

 Entrez la description de l'image ici

Voyez-vous ce qui se passe ici? Stdout pointe maintenant sur fichier, mais stderr pointe toujours sur le terminal! Tout ce qui est écrit sur stderr est toujours imprimé à l'écran! Alors soyez très très prudent avec l'ordre des redirections!

Notez également que dans Bash, l'écriture

  

$ commande & amp; > fichier

est exactement le même que:

  

$ commande > & amp; fichier

Les numéros font référence aux descripteurs de fichier (fd).

  • zéro est stdin
  • L'un est stdout
  • Deux est stderr

2 > & amp; 1 redirige le dd 2 vers 1.

Ceci fonctionne pour un nombre quelconque de descripteurs de fichier si le programme les utilise.

Vous pouvez consulter /usr/include/unistd.h si vous les oubliez:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

Cela dit, j'ai écrit des outils en C qui utilisent des descripteurs de fichier non standard pour la journalisation personnalisée. Vous ne les voyez donc pas, à moins que vous ne les redirigiez vers un fichier ou quelque chose du genre.

Cette construction envoie le flux d'erreur standard ( stderr ) à l'emplacement actuel de la sortie standard ( stdout ) - ce problème de devise semble apparaître. ont été négligés par les autres réponses.

Vous pouvez rediriger n'importe quel handle de sortie vers un autre en utilisant cette méthode, mais elle est le plus souvent utilisée pour canaliser les flux stdout et stderr dans un seul flux à des fins de traitement.

Quelques exemples:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

Notez que ce dernier ne sera pas diriger stderr vers fichier_ outfile2 - il le redirige vers ce que stdout était lorsque l'argument a été rencontré ( outfile1 ) et que then redirige stdout vers outfile2 .

Cela permet des ruses assez sophistiquées.

2 > & amp; 1 est une construction shell POSIX. Voici une ventilation, jeton par jeton:

2 : " Erreur standard ". descripteur de fichier de sortie.

> & amp; : Dupliquez un opérateur de descripteur de fichier de sortie (variante de Redirection de sortie , opérateur > ). Étant donné [x] & amp; [y] , le descripteur de fichier désigné par x est conçu pour être une copie du descripteur de fichier de sortie y .

1 " Sortie standard " descripteur de fichier de sortie.

L'expression 2 > & amp; 1 copie le descripteur de fichier 1 vers l'emplacement 2 , ainsi toute sortie écrite dans 2 ("erreur standard") de l'environnement d'exécution est identique au fichier initialement décrit par 1 ("sortie standard").

Explication complémentaire:

Descripteur de fichier : "Un nombre entier non négatif unique par processus utilisé pour identifier un fichier ouvert aux fins de l'accès au fichier."

Sortie / erreur standard : reportez-vous à la remarque suivante dans le Redirection de la documentation du shell:

  

Les fichiers ouverts sont représentés par des nombres décimaux commençant par zéro. La plus grande valeur possible est définie par l'implémentation; Cependant, toutes les mises en œuvre doivent prendre en charge au moins 0 à 9 inclus, pour une utilisation par l'application. Ces numéros sont appelés "descripteurs de fichier". Les valeurs 0, 1 et 2 ont une signification spéciale et des utilisations conventionnelles et sont impliquées par certaines opérations de redirection; ils sont appelés entrée standard, sortie standard et erreur standard, respectivement. Les programmes utilisent généralement l'entrée standard et écrivent la sortie sur la sortie standard. Les messages d'erreur sont généralement écrits sur une erreur standard. Les opérateurs de redirection peuvent être précédés d’un ou de plusieurs chiffres (sans caractères intermédiaires autorisés) pour désigner le numéro du descripteur de fichier.

2 est l'erreur standard de la console.

1 est la sortie standard de la console.

Il s’agit de l’Unix standard et Windows suit également POSIX.

E.g. quand tu cours

perl test.pl 2>&1

l'erreur standard est redirigée vers la sortie standard afin que vous puissiez voir les deux sorties ensemble:

perl test.pl > debug.log 2>&1

Après l'exécution, vous pouvez voir toutes les sorties, y compris les erreurs, dans le fichier debug.log.

perl test.pl 1>out.log 2>err.log

La sortie standard passe ensuite à out.log et l'erreur type à err.log.

Je vous suggère d'essayer de les comprendre.

Pour répondre à votre question: il faut toute sortie d'erreur (normalement envoyée à stderr) et l'écrit sur la sortie standard (stdout).

Ceci est utile avec, par exemple, "plus" lorsque vous avez besoin de pagination pour toutes les sorties. Certains programmes, tels que l’impression d’informations d’utilisation sur stderr.

Pour vous aider à vous souvenir

  • 1 = sortie standard (où les programmes impriment une sortie normale)
  • 2 = erreur standard (où les programmes impriment des erreurs)

& 2; " & amp; 1 " pointe simplement tout ce qui est envoyé à stderr, à stdout à la place.

Je vous recommande également de lire ce message sur la redirection des erreurs , où ceci le sujet est traité en détail.

Du point de vue du programmeur, cela signifie précisément ceci:

dup2(1, 2);

Voir la page de manuel .

Comprendre que 2 > & amp; 1 est une copie explique également pourquoi ...

command >file 2>&1

... n'est pas la même chose que ...

command 2>&1 >file

Le premier enverra les deux flux dans le fichier , tandis que le second enverra les erreurs dans stdout et la sortie ordinaire dans le fichier .

Les gens, souvenez-vous toujours de paxdiablo à propos de l'emplacement actuel de la cible de la redirection ... Il est important .

Mon mnémonique personnelle pour l'opérateur 2 > & amp; 1 est la suivante:

  • Pensez que & amp; signifie 'et' ou 'add' (le caractère est un ampère - et , n'est-ce pas?)
  • Cela devient donc: 'redirigez 2 (stderr) vers où 1 (stdout) est / est actuellement et ajoutez les deux les flux .

Le même mnémonique fonctionne pour l'autre redirection fréquemment utilisée, 1 > & amp; 2 :

  • Pensez à & amp; qui signifie et ou add ... (vous avez une idée de l'esperluette, oui?)
  • Cela devient donc: 'redirigez 1 (stdout) vers où 2 (stderr) est déjà / est actuellement et ajoutez les deux les flux .

Et souvenez-vous toujours: vous devez lire les chaînes de redirections "de la fin", de droite à gauche ( pas de gauche à droite).

Sous réserve que / foo n'existe pas sur votre système et que / tmp ne & & 8238;

$ ls -l /tmp /foo

imprimera le contenu de / tmp et imprimera un message d'erreur pour / foo

$ ls -l /tmp /foo > /dev/null

enverra le contenu de / tmp à / dev / null et affichera un message d'erreur pour / foo

$ ls -l /tmp /foo 1> /dev/null

fera exactement la même chose (notez le 1 )

$ ls -l /tmp /foo 2> /dev/null

imprimera le contenu de / tmp et enverra le message d'erreur à / dev / null

$ ls -l /tmp /foo 1> /dev/null 2> /dev/null

enverra à la fois la liste et le message d'erreur à / dev / null

$ ls -l /tmp /foo > /dev/null 2> &1

est un raccourci

Cela revient à transmettre l'erreur au stdout ou au terminal.

C’est-à-dire que cmd n’est pas une commande:

$cmd 2>filename
cat filename

command not found

L'erreur est envoyée au fichier comme suit:

2>&1

Une erreur type est envoyée au terminal.

  

Entrée de redirection

     

La redirection d’entrée provoque le fichier dont le nom   résultats de l'expansion du mot à ouvrir pour la lecture au dossier   descripteur n, ou l’entrée standard (descripteur de fichier 0) si n est   non spécifié.

     

Le format général de redirection des entrées est le suivant:

[n]<word
     

Redirection de la sortie

     

La redirection de la sortie provoque le fichier dont   nom résulte de l'extension du mot à ouvrir pour écrire sur   descripteur de fichier n, ou la sortie standard (descripteur de fichier 1) si n   n'est pas spécifié. Si le fichier n'existe pas, il est créé. si ça   existe-t-il est tronqué à la taille zéro.

     

Le format général de redirection de la sortie est le suivant:

[n]>word
     

Descripteurs de fichiers en mouvement

     

L'opérateur de redirection,

[n]<&digit-
     

déplace le chiffre du descripteur de fichier vers le descripteur de fichier n, ou   entrée standard (descripteur de fichier 0) si n n'est pas spécifié.   le chiffre est fermé après avoir été dupliqué en n.

     

De même, l'opérateur de redirection

[n]>&digit-
     

déplace le chiffre du descripteur de fichier vers le descripteur de fichier n, ou   sortie standard (descripteur de fichier 1) si n n'est pas spécifié.

Réf.:

man bash

Saisissez / ^ REDIRECT pour accéder à la section redirection et en savoir plus ...

Une version en ligne est disponible: 3.6 Redirections

PS:

Souvent, man était l'outil puissant pour apprendre Linux.

0 pour l'entrée, 1 pour stdout et 2 pour stderr.

Un conseil : somecmd > 1.txt 2 > & amp; 1 est correct, alors que somecmd 2 > & amp; 1> gt; 1.txt est totalement faux sans effet!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top