Que fait “2> & 1” en ligne de commande?

59

Je sais que le >signe est utilisé pour la redirection de sortie dans la ligne de commande, mais je ne parviens pas à trouver quelque chose qui explique l'utilisation de 2>&1dans la ligne de commande. Par exemple:

curl http://www.google.com > /dev/null 2>&1 &
Matt Huggins
la source

Réponses:

78

Le 1désigne la sortie standard (stdout). Le 2indique l'erreur standard (stderr).

Ainsi, il est 2>&1recommandé d’envoyer une erreur standard là où la sortie standard est redirigée. Comme cela a été envoyé, cela /dev/nullrevient à ignorer toute sortie.

Chealion
la source
2
Y at-il une raison pour laquelle une esperluette apparaît avant le 1, mais pas avant le 2? Je pensais que le caractère & était un caractère réservé pour l'exécution d'un travail en arrière-plan, mais je suppose que ce n'est que si l'esperluette apparaît sous la forme d'un caractère long à la fin d'une commande ...?
Matt Huggins
8
Étant donné que 0(stdin), 1(stdout) et 2(stderr) sont en fait des descripteurs de fichier, le shell requiert une esperluette et une mise en avant pour la redirection. Dans ce cas, il duplique le descripteur de fichier en fusionnant efficacement les deux flux d’informations.
Chealion
12
Pensez-y de cette façon: si vous venez juste d'avoir "1" sans aucune esperluette, le shell créerait un fichier nommé "1" et y redirigerait la sortie stderr.
CarlF
1
Ok, est-ce que cela seul serait valide alors? curl http://www.google.com 2>/dev/nullComment la ligne de commande sait-elle que le "2" désigne ici stderr et qu'il ne s'agit pas du deuxième paramètre que je passe à la commande curl?
Matt Huggins
1
@ Matt Huggins: Oui. Cela enverrait toute la sortie de stderrdirectement à la /dev/nullplace. Vous pouvez le voir dans la pratique en essayant curl, curl 1>/dev/nullet curl 2>/dev/nulljuste pour voir le changement de sortie. Encore une fois, l'esperluette n'est nécessaire que pour le descripteur de fichier redirigé.
Chealion
23

tl; dr

Chercher http://www.google.comen arrière - plan et jeter le stdoutet stderr.

curl http://www.google.com > /dev/null 2>&1 &

est le même que

curl http://www.google.com > /dev/null 2>/dev/null &

Les bases

0, 1et 2représentent les descripteurs de fichier standard dans les systèmes d’exploitation POSIX . Un descripteur de fichier est une référence système à (fondamentalement) un fichier ou un socket .

La création d'un nouveau descripteur de fichier en C peut ressembler à ceci:

fd = open("data.dat", O_RDONLY)

La plupart des commandes système Unix prennent certaines entrées et transmettent le résultat au terminal. curlva chercher ce qui se trouve à l'URL spécifiée ( google dot com ) et afficher le résultat stdout.

résultat curl

La redirection

Comme vous l' avez dit <et l' >habitude de rediriger la sortie d'une commande à un autre endroit, comme un fichier.

Par exemple, dans ls > myfiles.txt, lsrécupère le contenu du répertoire en cours et >redirige sa sortie myfiles.txt(si le fichier n'existe pas, il est créé, sinon écrasé, mais vous pouvez utiliser >>plutôt que d' >ajouter au fichier). Si vous exécutez la commande ci-dessus, vous remarquerez que rien n’est affiché sur le terminal. Cela signifie généralement le succès sur les systèmes Unix. Cochez cette case cat myfiles.txtpour afficher le contenu du fichier à l'écran.

> / dev / null 2> & 1

La première partie > /dev/nullredirige la stdout, sa curlsortie vers /dev/null(plus à ce sujet à l’avance) et 2>&1redirige le stderrvers le stdout(qui a été redirigé vers /dev/nullafin que tout soit envoyé à /dev/null).

Le côté gauche de 2>&1vous indique ce qui va être redirigé et le côté droit vous indique aller. Le &est utilisé à droite pour distinguer stdout (1)ou stderr (2)des fichiers nommés 1ou 2. Donc, 2>1créerait un nouveau fichier (s’il n’existait pas déjà) 1et nommait le stderrrésultat.

/ dev / null

/dev/nullest un fichier vide, un mécanisme utilisé pour supprimer tout ce qui y est écrit. Donc, curl http://www.google.com > /dev/nullsupprime efficacement curlla sortie.

> / dev / null

Mais pourquoi y a- t -il encore des éléments sur le terminal? Ce ne sont pascurl des sorties régulières, mais des données envoyées à la stderr, utilisées ici pour afficher des informations de progression et de diagnostic et pas seulement des erreurs .

curl http://www.google.com > /dev/null 2>&1ignore les informations curlde sortie et de curlprogression. Le résultat est que rien n'est affiché sur le terminal.

finalement

À &la fin, vous indiquez au shell d'exécuter la commande en tant que tâche en arrière - plan . Cela provoque le retour immédiat de l' invite lorsque la commande est exécutée de manière asynchrone en coulisse. Pour voir les emplois en cours tapez jobsdans votre terminal. Notez que cela diffère des processus en cours d'exécution sur votre système. Pour voir ces types topdans le terminal.

Références

Jorge Bucaran
la source
1
C'est l'une des meilleures réponses sur l'ensemble du site Web du point de vue de la mise en page, bravo!
OmarOthman
Une chose que je ne comprends pas, c'est pourquoi vous voudriez tout envoyer /dev/null? Ne voulez-vous pas que les résultats d' curlau moins quelque part soient utiles?
skube
@ skube Droite. Dans ce cas, la raison pour laquelle l'utilisateur souhaite ignorer stdout et stderr n'est pas claire. OP voulait probablement juste comprendre ce que la syntaxe voulait dire.
Jorge Bucaran
5

2fait référence à STDERR. 2>&1enverra STDERR au même endroit que 1(STDOUT).

John T
la source
0

Je comprends comme suit:

Si vous souhaitez uniquement lire les informations de sortie et d'erreur de la commande à l'écran, écrivez simplement: curl http://www.google.com

Et parfois, si vous souhaitez enregistrer les informations de sortie dans un fichier au lieu de l’écran du terminal pour une vérification ultérieure, vous pouvez écrire: curl http://www.google.com > logfile

Mais de cette façon, les informations StdErr seront omises, puisque >seulement rediriger le StdOut vers logfile.

Donc, si vous vous souciez des informations d'erreur de la commande une fois son exécution échouée, vous devez combiner StdOut avec StdErr en utilisant 2>&1(ce qui signifie replier StdErr en StdOut), afin que la ligne de commande suivante puisse être écrite: curl http://www.google.com > logfile2> & 1

YaOzI
la source