Dans la coquille, que signifie "2>&1"?
dans un shell Unix, si je veux combiner stderr
et stdout
dans le flux stdout
pour d'autres manipulations, 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
donc je ne vois que les premières erreurs.
j'ai toujours du mal à m'en souvenir, et je constamment avoir à aller le chercher, et c'est principalement parce que je ne comprends pas tout la syntaxe de cette astuce particulière.
Quelqu'un peut-il briser ceci et expliquer le caractère par caractère ce que 2>&1
signifie?
15 réponses
le descripteur de fichier 1 est la sortie standard ( stdout
).
Le descripteur de fichier 2 est l'erreur type ( stderr
).
Voici une façon de se souvenir de cette construction (bien qu'elle ne soit pas entièrement exacte): au début, 2>1
peut sembler un bon moyen de rediriger stderr
à stdout
. Cependant, il sera en fait interprété comme "rediriger stderr
vers un fichier nommé 1
". &
indique que ce qui suit est un descripteur de fichier et non pas un nom de fichier. Ainsi la construction devient: 2>&1
.
echo test > afile.txt
redirige stdout vers afile.txt
. C'est la même chose que 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 résumé... 2>
redirige stderr vers un fichier (non spécifié), en ajoutant &1
redirige stderr vers stdout.
Quelques trucs à propos de la redirection
certaines particularités syntaxiques à ce sujet peuvent avoir des comportements importants. Il y a quelques petits exemples de redirections, STDERR
, STDOUT
, et des arguments ordonnant .
1 - l'Écrasement ou l'ajout d'?
symbole >
signifie redirection .
-
>
moyenne Envoyer à l'ensemble du fichier complété , remplacer cible s'il existe (voirnoclobber
Bash caractéristique à #3 plus tard). -
>>
signifie envoyer serait ajouter à la cible, si elle existe.
Dans tous les cas, le fichier est créé s'ils n'existent pas.
2 - La ligne de commande shell est l'ordre dépendant de la!!
pour tester ceci, 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
(en espérant que vous n'ayez pas de répertoire nommé /tnt
, bien sûr ;). Eh bien, nous l'avons!!
alors, voyons voir:
$ 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 renvoie STDERR
à la console, et cela ne semble pas être le comportement attendu... Mais...
Si vous voulez faire quelques filtrage sur une sortie, l'autre ou 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 dans ce paragraphe est exactement la même que dans le paragraphe précédent, où j'ai écrit ne semblent pas être le comportement attendu (donc, cela pourrait même être un comportement attendu).
Eh bien, il y a quelques trucs 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
Note: &9
descripteur se produirait spontanément en raison de ) 9>&2
.
Addendum: nota! avec la nouvelle version de bash ( >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 une telle production en cascade mise en forme:
$ ((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
où STDOUT
passe 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 au sujet de noclobber
option et >|
syntaxe
c'est à propos de overwriting :
alors que set -o noclobber
instruit bash à pas écraser tout fichier existant, la syntaxe >|
vous laisser passer par 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 par >|
:
$ 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ésactivant cette option et/ou demandant si elle est déjà activée.
$ 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 - le Dernier pli et plus...
Pour rediriger les deux sortie à partir d'une commande donnée, nous voyons qu'un droit de la syntaxe pourrait être:
$ ls -ld /tmp /tnt >/dev/null 2>&1
pour ce cas spécial , il y a une syntaxe de raccourci: &>
... ou >&
$ ls -ld /tmp /tnt &>/dev/null
$ ls -ld /tmp /tnt >&/dev/null
Nota: Si 2>&1
existent, 1>&2
est un bonne syntaxe aussi:
$ ls -ld /tmp /tnt 2>/dev/null 1>&2
4b-maintenant, je vous laisse 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 informations
vous pouvez lire le manuel en tapant:
man -Len -Pless\ +/^REDIRECTION bash
dans un bash de la console ;-)
les numéros renvoient aux descripteurs de fichier (fd).
- Zéro
stdin
- l'Un est
stdout
- Deux, c'est
stderr
2>&1
redirige fd 2 vers 1.
Cela fonctionne pour n'importe quel nombre de descripteurs de fichier si le programme 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. */
qui dit que 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 que vous ne le redirigiez vers un fichier ou quelque chose.
j'ai trouvé ce post brillant sur la redirection: tout sur les redirections
rediriger la sortie standard et l'erreur standard vers un fichier
commande $ &>fichier
cette doublure utilise l'opérateur &>
pour rediriger les flux de sortie-stdout et stderr - de la commande au fichier. C'est du Bash raccourci 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:
comme vous pouvez le voir, stdout et stderr pointent maintenant vers file
. Donc tout ce qui est écrit à stdout et stderr est écrit à file
.
Il y a plusieurs façons de rediriger les deux flux vers la même destination. Vous pouvez rediriger chaque flux, l'un après l'autre:
$ commande >fichier 2>&1
c'est une façon beaucoup plus courante de rediriger les deux flux vers un fichier. D'abord stdout est redirigé vers file, puis stderr est dupliqué pour être le même que stdout. Donc les deux flux finissent par pointer vers file
.
quand Bash voit plusieurs redirections il les traite de gauche à droite. Passons en revue les étapes et voyons comment cela se produit. Avant d'exécuter une commande, la table de descripteur de fichier de Bash ressemble à ceci:
traite maintenant Bash le premier fichier de redirection>. Nous avons déjà vu cela et cela fait de stdout point un fichier:
prochain Bash voit le deuxième redirection 2>&1. Nous n'avons jamais vu cette redirection auparavant. Celui-ci duplique le descripteur de fichier 2 pour être une copie du descripteur de fichier 1 et nous obtenons:
les deux flux ont été redirigés vers file.
cependant faites attention ici! Ecriture
commande > Fichier 2> & 1
n'est pas la même que écriture:
$ commande 2>&1 >fichier
L'ordre des redirections questions dans le coup! Cette commande redirige uniquement la sortie standard vers le fichier. Le stderr imprimera toujours au terminal. Pour comprendre pourquoi cela se produit, revoyons les étapes. Ainsi, avant d'exécuter la commande, la table de descripteur de fichier ressemble à ceci:
maintenant Bash traite des redirections de gauche à droite. Il voit d'abord 2>&1 ainsi il duplique stderr à stdout. La table des descripteurs de fichier devient:
maintenant Bash voit la deuxième redirection, >file
, et il redirige stdout au fichier:
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 à stderr est imprimé à l'écran! Soyez donc très, très prudent avec l'ordre des redirections!
notez aussi Qu'en Bash, en écrivant
commande $ &>fichier
est exactement le même que:
$ command >&fichier
cette construction envoie le flux d'erreur standard ( stderr
) au courant 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 quelle poignée de sortie à une autre en utilisant cette méthode, mais il est le plus souvent utilisé pour canaliser stdout
et stderr
flux dans un seul flux pour le 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 le dernier, pas direct stderr
à outfile2
- il redirige vers ce stdout
a été lors de l'argument a été rencontrée ( outfile1
) et puis redirige stdout
à outfile2
.
cela permet quelques ruses assez sophistiquées.
2>&1
est un shell POSIX construire. Voici une répartition, jeton par jeton:
2
: " erreur Standard sortie " du descripteur de fichier.
>&
: dupliquer un descripteur de fichier de sortie opérateur (une variante de Redirection de sortie opérateur >
). Étant donné [x]>&[y]
, le descripteur de fichier indiqué 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
, de sorte que 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").
autre explication:
descripteur de fichier : "un entier unique par processus, non négatif, utilisé pour identifier un fichier ouvert aux fins de l'accès au fichier."
sortie/erreur Standard : se référer à la note suivante dans la section Redirection de la documentation shell:
les fichiers ouverts sont représentés par des nombres décimaux commençant par zéro. La valeur la plus élevée possible est définie par la mise en œuvre; toutefois, toutes les mises en œuvre doivent supporter au moins 0 à 9, inclusivement, pour utilisation par l'application. Ces numéros sont appelés "descripteurs de fichiers". Les valeurs 0, 1 et 2 ont un sens particulier et des utilisations conventionnelles et sont impliquées par certaines opérations de redirection; elles sont appelées entrées standard, la sortie, et l'erreur standard, Respectivement. Les programmes prennent généralement leur entrée standard, et écrire la sortie sur la sortie standard. Les messages d'erreur sont généralement écrits sur l'erreur standard. Les opérateurs de redirection peuvent être précédés d'un ou plusieurs chiffres (sans caractères intermédiaires autorisés) pour désigner le numéro du descripteur de fichier.
pour répondre à votre question: il prend n'importe quelle sortie d'erreur (normalement envoyé à stderr) et l'écrit à la sortie standard (stdout).
c'est utile avec, par exemple 'plus' quand vous avez besoin de pagination pour toutes les sorties. Certains programmes comme l'impression des informations d'utilisation dans stderr.
pour vous aider à vous souvenir
- 1 = sortie standard (où les programmes impriment la sortie normale)
- 2 = Erreur type (où programmes erreurs d'impression)
"2>&1" Il suffit de pointer tout ce qui est envoyé à stderr, à stdout à la place.
je recommande aussi la lecture ce post sur la redirection d'erreur où ce sujet est couvert en détail.
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.
E. G. quand vous courez
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 débogage.journal.
perl test.pl 1>out.log 2>err.log
puis sortie standard.journal, et la marge d'erreur err.journal.
je vous suggère d'essayer de comprendre ces.
du point de vue d'un programmeur, cela signifie précisément ceci:
dup2(1, 2);
Voir la l'homme page .
comprendre que 2>&1
est une copie explique aussi pourquoi ...
command >file 2>&1
... n'est pas le même que ...
command 2>&1 >file
le premier enverra les deux flux à file
, tandis que le second enverra des erreurs à stdout
, et Sortie ordinaire dans file
.
les Gens, rappelez-vous toujours paxdiablo , allusion à propos de la actuel emplacement de la cible de redirection... est important.
mon mnémonique personnel pour l'opérateur 2>&1
est ceci:
- pensez à
&
comme signifiant'and'
ou'add'
(le caractère est un ampères - et , n'est-ce pas?) - ainsi il devient: 'redirect
2
(stderr) à l'endroit où1
(stdout) est déjà/actuellement et ajouter les deux flux" .
les mêmes œuvres mnémoniques pour l'autre redirection fréquemment utilisé aussi, 1>&2
:
- pensez à
&
qui signifieand
ouadd
... (vous avez l' idée à propos de l'esperluette, oui?) - ainsi il devient: 'redirect
1
(stdout) à l'endroit où2
(stderr) est déjà/actuellement et ajouter les deux flux" .
et rappelez-vous toujours: vous devez lire les chaînes de redirections 'du bout', de droite à gauche ( pas de gauche à droite).
pourvu que /foo
n'existe pas sur votre système et /tmp
n'existe pas ...
$ ls -l /tmp /foo
affichera le contenu de /tmp
et affichera un message d'erreur pour /foo
$ ls -l /tmp /foo > /dev/null
enverra le contenu de /tmp
à /dev/null
et imprimera un message d'erreur pour /foo
$ ls -l /tmp /foo 1> /dev/null
fera exactement la même chose (notez la 1 )
$ ls -l /tmp /foo 2> /dev/null
imprime le contenu de /tmp
et envoie le message d'erreur /dev/null
$ ls -l /tmp /foo 1> /dev/null 2> /dev/null
enverra à la fois l'inscription ainsi que le message d'erreur /dev/null
$ ls -l /tmp /foo > /dev/null 2> &1
est une abréviation de
c'est comme passer l'erreur au stdout ou au terminal.
C'est-à-dire, cmd
n'est pas une commande:
$cmd 2>filename
cat filename
command not found
l'erreur est envoyée au fichier comme ceci:
2>&1
L'erreur Type est envoyée au terminal.
Redirection D'Entrée
Redirection de l'entrée provoque le fichier dont le nom résultats de l'extension de word à ouvrir pour la lecture sur Fichier descripteur n, ou l'entrée standard (descripteur de fichier 0) si n est n'est pas spécifié.
le format général pour rediriger l'entrée est:
[n]<word
Redirection De La Sortie
Redirection de la sortie provoque le fichier dont nom résulte de l'expansion de word à ouvrir pour l'écriture 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éé; s'il n'existe pas, il est tronqué à la taille zéro.
le format général pour rediriger la sortie est:
[n]>word
Déplacement Des Descripteurs De Fichier
l'opérateur de redirection,
[n]<&digit-
déplace le chiffre du descripteur de fichier vers le descripteur de fichier n, ou le l'entrée standard (descripteur de fichier 0) si n n'est pas spécifié. le chiffre est fermé après avoir été dupliqué à 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 le la sortie standard (descripteur de fichier 1) si n n'est pas spécifié.
Ref:
man bash
Tapez /^REDIRECT
pour localiser la section redirection
, et en savoir plus...
une version en ligne est ici: 3.6 Redirections
PS:
beaucoup de fois, man
était l'outil puissant pour apprendre Linux.
0 pour input, 1 pour stdout et 2 pour stderr.
Une Astuce :
somecmd >1.txt 2>&1
est correct, tandis que somecmd 2>&1 >1.txt
est totalement faux sans effet!