Je commence dans un répertoire vide.
$ touch aFile
$ ls
aFile
Ensuite, je ls
deux arguments, dont l'un n'est pas dans ce répertoire. Je redirige les deux flux de sortie vers un fichier nommé output
. J'utilise >>
afin d'éviter d'écrire simultanément.
$ ls aFile not_exist >>output 2>>output
$ cat output
ls: cannot access 'not_exist': No such file or directory
aFile
Ce qui semble fonctionner. Y a-t-il des dangers à cette approche?
Non, ce n'est pas aussi sûr que le standard >>bar 2>&1
.
Quand tu écris
foo >>bar 2>>bar
vous ouvrez le fichier bar
deux fois avec O_APPEND
, créant deux objets fichier complètement indépendants [1], chacun avec son propre état (pointeur, modes ouverts, etc.).
Ceci est très différent de 2>&1
Qui appelle simplement l'appel système dup(2)
et crée les alias interchangeables stderr et stdout pour le même objet fichier.
Maintenant, il y a un problème avec ça:
O_APPEND
Peut entraîner des fichiers corrompus sur les systèmes de fichiers NFS si plusieurs processus ajoutent des données à un fichier à la fois. Cela est dû au fait que NFS ne prend pas en charge l'ajout à un fichier, le noyau client doit donc le simuler, ce qui ne peut pas être fait sans condition de concurrence critique.
Vous pouvez généralement compter sur la probabilité que le fichier comme bar
dans foo >>bar 2>&1
Soit écrit en même temps à partir de deux endroits distincts étant assez faible. Mais par votre >>bar 2>>bar
Vous venez de l'augmenter d'une douzaine d'ordres de grandeur, sans aucune raison.
[1] "Open File Descriptions" dans le jargon POSIX.
Que se passe-t-il lorsque vous le faites
some_command >>file 2>>file
est que file
sera ouvert pour être ajouté deux fois. Ceci est sûr à faire sur un système de fichiers POSIX. Toute écriture qui arrive au fichier lorsqu'il est ouvert pour l'ajout se produira à la fin du fichier, que les données proviennent du flux de sortie standard ou du flux d'erreur standard.
Cela repose sur la prise en charge des opérations d'écriture d'ajout atomique dans le système de fichiers sous-jacent. Certains systèmes de fichiers, tels que NFS, ne prennent pas en charge l'ajout atomique. Voir par exemple la question "Le fichier est-il atomique sous UNIX?" sur StackOverflow.
En utilisant
some_command >>file 2>&1
fonctionnerait même sur NFS cependant.
Cependant, en utilisant
some_command >file 2>file
n'est pas sûr, car le shell tronquera le fichier de sortie (deux fois) et toute écriture qui se produira sur l'un ou l'autre flux ( écrasera les données déjà écrites par l'autre courant.
Exemple:
$ { echo hello; echo abc >&2; } >file 2>file
$ cat file
abc
o
La chaîne hello
est écrite en premier (avec une nouvelle ligne de fin), puis la chaîne abc
suivie d'une nouvelle ligne est écrite à partir de l'erreur standard, écrasant la hell
. Le résultat est la chaîne abc
avec une nouvelle ligne, suivie de ce qui reste de la première sortie echo
, une o
et une nouvelle ligne.
L'échange des deux echo
autour de la plaie ne produit que hello
dans le fichier de sortie car cette chaîne est écrite en dernier et est plus longue que la chaîne abc
. L'ordre dans lequel les redirections se produisent n'a pas d'importance.
Il serait préférable et plus sûr d'utiliser le plus idiomatique
some_command >file 2>&1
Cela dépend de ce que vous voulez réaliser. C'est à vous de décider si vous pouvez avoir des erreurs dans le même fichier que la sortie. Il s'agit simplement d'enregistrer du texte dans un fichier avec les fonctionnalités du Shell qui vous permettent de rediriger comme vous le souhaitez. Il n'y a pas de oui ou de non absolu. Comme tout sous Linux, cela peut se faire de plusieurs manières, c'est ma façon ls notExistingFile existingFile >> output 2>&1
Pour répondre à la question: en termes de redirection elle-même, oui, c'est parfaitement sûr.