Je suis nouveau sur Linux et j'essaie de comprendre comment fonctionnent les redirections.
J'ai testé diverses syntaxes pour rediriger stdout
et stderr
au même fichier, qui ne produisent pas tous les mêmes résultats.
Par exemple, si j'essaie de lister 2 fichiers qui n'existent pas (file1
et file2
) et 2 qui le font (foo
et fz
):
Syntaxe #1 (sans redirection) :
$ ls file1 foo fz file2
Voici la sortie que j'obtiens dans le terminal :
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo fz
Syntaxe #2 :
Maintenant, avec la redirection :
$ ls file1 foo fz file2 > redirect 2>&1
La redirect
le fichier contient la même chose que le résultat pour la syntaxe #1 :
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz
Donc, avec les deux syntaxes ci-dessus, il semble que le shell imprime stderr
d'abord, puis stdout
.
Syntaxe #3 :
Maintenant, si j'essaie avec l'une des syntaxes suivantes :
$ ls file1 foo fz file2 > redirect 2> redirect
ou
$ ls file1 foo fz file2 2> redirect > redirect
Puis la redirect
le fichier contiendra ceci :
foo
fz
nnot access file1: No such file or directory
ls: cannot access file2: No such file or directory
Ici, cela ressemble à stdout
est imprimé avant stderr
, mais ensuite nous voyons que le début de stderr
est "tronqué" du même nombre de caractères que stdout
.
La stdout
est long de 6 caractères (foo fz
, retour chariot inclus), donc les 6 premiers caractères du stderr
(ls: ca
) ont été écrasés par stdout
.
Cela ressemble donc en fait à stderr
a été imprimé en premier, et que stdout
a ensuite été imprimé sur stderr
au lieu d'y être ajouté.
Cependant, cela aurait eu plus de sens pour moi si stderr
avait été complètement effacé et remplacé par stdout
, plutôt que partiellement écrasé.
Syntaxe #4 :
Le seul moyen que j'ai trouvé pour corriger la syntaxe n ° 3 consiste à ajouter l'opérateur d'ajout au stdout
:
$ ls file1 foo fz file2 >> redirect 2> redirect
ou
$ ls file1 foo fz file2 2> redirect >> redirect
Ce qui produit la même chose que la syntaxe #2 :
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz
Cet article ici explique que la syntaxe #3 est fausse (vraisemblablement, la syntaxe #4 aussi). Mais pour l'amour de l'argument :pourquoi la syntaxe #3 est-elle fausse ? Que dit-il exactement (ou pas dire) le shell à faire par opposition à la syntaxe #2 ?
Connexe :Quelle est la différence entre $(…) et `…` dans Bash ?
Aussi, y a-t-il une raison pour laquelle la sortie affiche toujours stderr
avant stdout
?
Merci !
Réponse acceptée :
C'est comme exécuter deux processus pour écrire dans le même fichier en même temps... mauvaise idée. Vous vous retrouvez avec deux descripteurs de fichiers ouverts différents et vos données peuvent être tronquées (comme c'est le cas au point 3 ci-dessus). L'utilisation de la syntaxe #2 est correcte; ça fait un handle de fichier et pointe à la fois stderr et stdout au même endroit.
Quant au fait que stderr soit toujours imprimé en premier, il n'y a aucune règle à ce sujet. Je soupçonne avec ls
c'est parce que ls
doit vérifier chaque entrée du répertoire avant de pouvoir déclarer qu'un fichier particulier n'existe pas. Ainsi, plutôt que de faire N passages sur la table de répertoires, il fait un seul passage, vérifiant tous les arguments de ligne de commande donnés, signale les erreurs et imprime les fichiers qu'il a trouvés. D'autres commandes peuvent imprimer sur stderr après stdout, ou même alterner entre elles.