17 votes

Que fait "2>&1" lorsqu'il est affiché AVANT 1>x ?

Je sais ce que fait cette commande :

command 1>/dev/null 2>&1

Mais que fait ce qui suit, le cas échéant ?

command 2>&1 1>/dev/null

Je vois toujours la sortie d'erreur standard avec la deuxième commande, donc elle ne fait pas ce que j'attendais d'elle au moins...

Ceci est reproduit à la fois sous Windows/cmd.exe et sous Linux/Bash (j'étais sur le point de poser cette question sur Unix et Linux au lieu de Super User, mais j'ai remarqué qu'il peut être reproduit sur Windows cmd.exe aussi, donc je suppose qu'il s'adapte mieux à Super User qu'à Unix & Linux alors ?)

10 votes

Je décris 2>&1 comme "redirigé fd2 vers ce que fd1 utilise actuellement " -- par la suite, rediriger fd1 n'affecte pas ce que fd2 utilise.

0 votes

Excellente question.

26voto

Abbas Points 3737

Un autre exemple pourrait être utile : redirigeons fd1 vers un fichier, redirigeons fd2 vers fd1, puis redirigeons fd1 vers un autre fichier :

$ ( echo "this is stdout"; echo "this is stderr" >&2 ) 1>foo 2>&1 1>bar
$ cat foo
this is stderr
$ cat bar
this is stdout

Nous pouvons voir que 2>&1 envoie stderr vers le fichier "foo" vers lequel stdout a été redirigé, mais lorsque nous redirigeons stdout vers "bar", nous ne modifions pas la destination de stderr.

De même, 2>&1 1>/dev/null redirige stderr vers ce vers quoi stdout pointe (voir /proc/$$/fd ), et lorsque stdout est écarté, stderr n'est pas modifié (toujours visible).

C'est la technique utilisée pour capturer la sortie d'erreur d'une commande, en ignorant la sortie normale :

error_output=$( some_command  2>&1 1>/dev/null )

12voto

Rachel Blackman Points 81

De man bash :

" Notez que l'ordre des redirections est significatif. Par exemple, la commande

ls > dirlist 2>&1

dirige la sortie standard et l'erreur standard vers le fichier dirlist, tandis que la commande

ls 2>&1 > dirlist

dirige uniquement la sortie standard vers le fichier dirlist, parce que l'erreur standard a été dupliquée de la sortie standard avant que la sortie standard ne soit redirigée vers dirlist".

7voto

Ana cleto Points 11

C'est un problème d'ordre des opérations. Vous attendez 2>&1 pour rediriger vers 1 mais au lieu de cela, il redirige vers l'adresse actuelle de l'utilisateur. valeur de 1 à la place. Cela ressemble un peu à une "condition de course", mais ce n'en est pas vraiment une. Vous vous attendez à ce que les deux opérations se produisent en même temps, mais elles sont évaluées l'une après l'autre et c'est la valeur à ce moment précis qui compte, pas la valeur finale.

Par défaut 1 pointe vers la sortie de votre console par défaut stdout donc faire 2>&1 à ce moment-là redirige stderr à la sortie standard de votre console stdout .

En faisant 2>&1 après rediriger 1 vers un autre fichier, vous le redirigez vers le fichier nouveau pointeur de fichier que 1 pointe vers. ( /dev/null )

Essentiellement l'opérateur de redirection copies le pointeur de l'endroit vers lequel vous redirigez plutôt que de pointer vers l'autre descripteur. L'ordre des redirections est donc important.

0 votes

Moi aussi, je n'appellerais pas cela une condition de course, mais je ne sais pas si j'aurais un meilleur mot pour décrire ce que Mokubai décrit. Votre nom me donne envie d'un petit déjeuner hawaïen "Je voudrais le Mokubai Locobai s'il vous plaît ! avec un supplément de sauce !

0 votes

@DanielB, j'espère que cela a été clarifié.

2 votes

Conditions de course se produisent lorsque deux (ou plus) simultanée Les threads ou les processus (ou autre) essaient de faire des choses en même temps, sans synchronisation, de sorte que le résultat dépende suffisamment de facteurs externes pour être essentiellement aléatoire. Ce n'est absolument pas le cas ici : le traitement des redirections est très bien défini et se déroule exactement dans l'ordre, de gauche à droite.

5voto

ikegami Points 225

1>/dev/null 2>&1 :
1 (stdout) : /dev/null
2 (stderr) : /dev/null

2>&1 1>/dev/null :
1 (stdout) : /dev/null
2 (stderr) : destination originale de 1 (stdout)


L'ordre est important car ils sont traités de gauche à droite, en utilisant les valeurs actuelles des descripteurs à ce moment-là.

Regardons 1>/dev/null 2>&1 avec deux conditions de départ différentes :

            Original           After 1>/dev/null  After 2>&1
            -----------------  -----------------  -----------------
1 (stdout): /dev/tty           /dev/null          /dev/null
2 (stderr): /dev/tty           /dev/tty           /dev/null

            Original           After 1>/dev/null  After 2>&1
            -----------------  -----------------  -----------------
1 (stdout): /tmp/stdout        /dev/null          /dev/null
2 (stderr): /tmp/stderr        /tmp/stderr        /dev/null

Maintenant, regardons 2>&1 1>/dev/null avec les mêmes conditions de départ.

            Original           After 2>&1         After 1>/dev/null
            -----------------  -----------------  -----------------
1 (stdout): /dev/tty           /dev/tty           /dev/null
2 (stderr): /dev/tty           /dev/tty           /dev/tty

            Original           After 2>&1         After 1>/dev/null
            -----------------  -----------------  -----------------
1 (stdout): /tmp/stdout        /tmp/stdout        /dev/null
2 (stderr): /tmp/stderr        /tmp/stdout        /tmp/stdout

Démo

a :

#!/usr/bin/perl
print STDOUT "Sent to STDOUT\n";
print STDERR "Sent to STDERR\n";

$ ( exec 1>/tmp/stdout 2>/tmp/stderr; ./a )

$ cat /tmp/stdout; echo .
Sent to STDOUT
.

$ cat /tmp/stderr; echo .
Sent to STDERR
.

$ ( exec 1>/tmp/stdout 2>/tmp/stderr; ./a 2>&1 1>/dev/null )

$ cat /tmp/stdout; echo .
Sent to STDERR
.

$ cat /tmp/stderr; echo .
.

$ ( exec 1>/tmp/stdout 2>/tmp/stderr; ./a 1>/dev/null 2>&1 )

$ cat /tmp/stdout; echo .
.

$ cat /tmp/stderr; echo .
.

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