Question Dans le shell, que signifie "2> & 1"?


Dans un shell Unix, si je veux combiner stderr et stdout dans le stdout flux pour plus de manipulation, 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 ça:

g++ lots_of_errors 2>&1 | head

donc je ne peux voir que les premières erreurs.

J'ai toujours du mal à me souvenir de cela, et je dois constamment aller voir, et c'est principalement parce que je ne comprends pas complètement la syntaxe de cette astuce particulière.

Quelqu'un peut-il casser cela et expliquer le caractère par caractère 2>&1  veux dire?


1734
2018-05-03 22:57


origine


Réponses:


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

Voici une façon de se souvenir de cette construction (bien que ce ne soit pas tout à fait exact): d'abord, 2>1 peut ressembler à un bon moyen de rediriger stderr à stdout. Cependant, il sera interprété comme "redirection" stderr à un fichier nommé 1". & indique que ce qui suit est un descripteur de fichier et non un nom de fichier. Donc, la construction devient: 2>&1.


1942
2018-05-03 23:04



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 faites:

echo test 2> afile.txt

>& est la syntaxe pour rediriger un flux vers un autre descripteur de fichier - 0 est stdin, 1 est stdout, et 2 est stderr.

Vous pouvez rediriger stdout vers stderr en faisant:

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

Ou vice versa:

echo test 2>&1

Donc, en bref ... 2> redirige stderr vers un fichier (non spécifié), en ajoutant &1 redirige stderr vers stdout.


481
2018-05-03 22:59



Quelques astuces sur la redirection

Certaines particularités de syntaxe à ce sujet peuvent avoir des comportements importants. Il y a quelques petits exemples de redirections, STDERR, STDOUTet arguments commander.

1 - Écrasement ou ajout?

symbole > signifier redirection.

  • > signifier envoyer à l'ensemble du fichier complété, écrasant la cible si elle existe (voir noclobber bash caractéristique à # 3 plus tard).
  • >> signifier envoyer en plus de serait ajouter à la cible si elle existe.

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

2 - Le ligne de commande shell est tributaire de l'ordre !!

Pour tester cela, nous avons besoin une commande simple qui va envoyer 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

(En espérant que vous n'avez pas de répertoire nommé /tnt, bien sûr ;). Eh bien, nous l'avons!

Alors, voyons:

$ 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

Les dernières vidages de ligne de commande STDERR à la console, et il ne semble pas être le comportement attendu ... Mais ...

Si vous voulez en faire post-filtrage à propos d'une sortie, de l'autre ou des 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 dans ce paragraphe est exactement la même que dans le paragraphe précédent, où j'ai écrit ne semble pas être le comportement attendu (donc, cela pourrait même être un comportement attendu).

Eh bien, il y a quelques petites astuces sur les redirections, pour faire une 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

Nota: &9descripteur se produirait spontanément à cause de ) 9>&2.

Addendum: nota! Avec la nouvelle version de  (>4.0) il y a une nouvelle fonctionnalité et une syntaxe plus sexy pour faire ce genre de choses:

$ 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 nouvelle syntaxe, 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 passer par un filtre spécifique, STDERR à un autre et finalement les deux sorties fusionnées passent par un troisième filtre de commande.

3 - Un mot sur noclobber option et >| syntaxe

Ce est à propos de écraser:

Tandis que set -o noclobber instruire bash à ne pas écraser tout fichier existant, le >| la syntaxe vous laisse passer 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, bien 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

Passer à travers 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ésactivation de cette option et / ou demande si elle est déjà définie.

$ 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 ...

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

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

pour ça spécial cas, il existe une syntaxe de raccourci: &> ... ou >&

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

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

Nota: si 2>&1 exister, 1>&2 est une syntaxe correcte aussi:

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

4b- Maintenant, je vais vous laisser penser à:

$ 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 information

Vous pouvez lire le bon manuel en appuyant sur:

man -Len -Pless\ +/^REDIRECTION bash

dans un  console ;-)


256
2018-04-29 16:33



Les chiffres se réfèrent aux descripteurs de fichier (fd).

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

2>&1 redirige fd 2 à 1.

Cela fonctionne pour n'importe quel nombre de descripteurs de fichiers si le programme les utilise.

Vous pouvez regarder /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 C qui utilisent des descripteurs de fichiers non standard pour la journalisation personnalisée, donc vous ne le voyez pas à moins de le rediriger vers un fichier ou quelque chose comme ça.


67
2018-05-03 22:58



Cette construction envoie le flux d'erreur standard (stderr) au actuel emplacement de la sortie standard (stdout) - cette question de monnaie semble avoir été négligée par les autres réponses.

Vous pouvez rediriger n'importe quel handle de sortie vers un autre en utilisant cette méthode, mais il est le plus souvent utilisé pour canaliser stdout et stderr flux dans un flux unique pour le traitement.

Certains exemples sont:

# 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 sera ne pas direct stderr à outfile2 - il le redirige vers quoi stdout était quand l'argument a été rencontré (outfile1) et puis redirections stdout à outfile2.

Cela permet une supercherie assez sophistiquée.


49
2018-05-03 23:54



J'ai trouvé ce brillant post sur la redirection: Tout sur les redirections

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

$ commande &> fichier

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

Voici à quoi ressemble la table des descripteurs de fichiers après que Bash a redirigé les deux flux:

Enter image description here

Comme vous pouvez le voir, stdout et stderr pointent maintenant vers file. Donc tout ce qui est écrit sur stdout et stderr est écrit file.

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> & 1

C'est un moyen beaucoup plus commun de rediriger les deux flux vers un fichier. La première sortie stdout est redirigée vers un fichier, puis stderr est dupliqué pour être identique à stdout. Donc, les deux flux finissent par pointer vers file.

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, la table des descripteurs de fichiers de Bash ressemble à ceci:

Enter image description here

Maintenant, Bash traite le premier fichier de redirection. Nous l'avons vu auparavant et cela fait stdout pointer vers le fichier:

Enter image description here

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

Enter image description here

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

Cependant faites attention ici! L'écriture

commande> fichier 2> & 1

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

$ command 2> & 1> fichier

L'ordre des redirections est important dans Bash! Cette commande redirige uniquement la sortie standard vers le fichier. Le stderr sera toujours imprimer sur le terminal. Pour comprendre pourquoi cela se produit, répétons les étapes. Donc, avant d'exécuter la commande, la table des descripteurs de fichiers ressemble à ceci:

Enter image description here

Maintenant Bash traite les redirections de gauche à droite. Il voit d'abord 2> & 1 donc il duplique stderr à stdout. La table des descripteurs de fichiers devient:

Enter image description here

Maintenant Bash voit la deuxième redirection, >file, et il redirige stdout vers le fichier:

Enter image description here

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

Notez aussi que dans Bash, écrire

$ commande &> fichier

est exactement le même que:

Commande $> & fichier


47
2017-10-29 13:04



2>&1 est une construction shell POSIX. Voici une répartition, jeton par jeton:


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

>&: Dupliquer un descripteur de fichier de sortie opérateur (une variante de Redirection de sortie opérateur >). Donné [x]>&[y], le descripteur de fichier désigné par x est fait pour être une copie du descripteur de fichier de sortie y.

1 "Sortie standard"descripteur de fichier de sortie.

L'expression 2>&1 copie le descripteur de fichier 1 à l'emplacement 2, donc toute sortie écrite à 2 ("erreur standard") dans l'environnement d'exécution va au même fichier décrit à l'origine par 1 ("sortie standard").


Plus d'explications:

Descripteur de fichier: "Un entier unique, non négatif par processus, utilisé pour identifier un fichier ouvert dans le but d'accéder au fichier."

Sortie standard / erreur: Reportez-vous à la note suivante dans le Redirection section de la documentation 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, inclusivement, pour une utilisation par l'application. Ces numéros sont appelés "descripteurs de fichiers". Les valeurs 0, 1 et 2 ont une signification spéciale et des utilisations conventionnelles et sont impliquées par certaines opérations de réacheminement; ils sont appelés entrée standard, sortie standard et erreur standard, respectivement. Les programmes prennent généralement leur entrée à partir de l'entrée standard et écrivent la sortie sur la sortie standard. Les messages d'erreur sont généralement écrits sur l'erreur standard. Les opérateurs de réacheminement peuvent être précédés d'un ou plusieurs chiffres (sans caractères intermédiaires autorisés) pour désigner le numéro de descripteur de fichier.


13
2017-12-25 06:43



Pour répondre à votre question: Il prend n'importe quelle 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 aiment imprimer les informations d'utilisation dans 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> & 1" pointe simplement tout ce qui est envoyé à stderr, à stdout à la place.

Je recommande également de lire ce post sur la redirection d'erreur où ce sujet est couvert en détail.


12
2018-05-03 23:24



2 est l'erreur standard de la console.

1 est la sortie standard de la console.

C'est le standard Unix, et Windows suit également le POSIX.

Par exemple. quand tu cours

perl test.pl 2>&1

l'erreur standard est redirigée vers la sortie standard, de sorte que vous pouvez 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 est ensuite envoyée à out.log et l'erreur standard à err.log.

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


12
2017-07-19 03:23



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

dup2(1, 2);

Voir le page de manuel.

Comprendre que 2>&1 est un copie explique aussi pourquoi ...

command >file 2>&1

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

command 2>&1 >file

Le premier enverra les deux flux à file, alors que le second enverra des erreurs à stdout, et la sortie ordinaire en file.


10
2017-12-03 10:20