Hier, j'ai lu ce commentaire SO qui dit que dans le shell (au moins bash
) >&-
"a le même résultat que" >/dev/null
.
Ce commentaire fait en réalité référence au guide ABS comme source d'informations. Mais cette source dit que la >&-
syntaxe "ferme les descripteurs de fichier".
Il n’est pas clair pour moi si les deux actions de fermeture d’un descripteur de fichier et de sa redirection vers le périphérique null sont totalement équivalentes. Donc ma question est: sont-ils?
En apparence, fermer un descripteur revient à fermer une porte, mais le rediriger vers un périphérique nul ouvre la porte aux limbes! Les deux ne me semblent pas exactement pareils parce que si je vois une porte fermée, je ne tenterai rien, mais si je vois une porte ouverte, je supposerai que je peux le faire.
En d’autres termes, je me suis toujours demandé si cela >/dev/null
signifiait cat mybigfile >/dev/null
traiter tous les octets du fichier et l’écrire dans /dev/null
lequel l’oublie. D'un autre côté, si le shell rencontre un descripteur de fichier fermé, j'ai tendance à penser (mais je ne suis pas sûr) qu'il n'écrira simplement rien, bien que la question de savoir s'il litcat
toujours chaque octet reste posée .
Ce commentaire dit >&-
et >/dev/null
" devrait " être le même, mais ce n'est pas une réponse si retentissante pour moi. J'aimerais avoir une réponse plus autoritaire avec une référence au standard ou à la source ou pas ...
la source
Réponses:
Non, vous ne voulez certainement pas fermer les descripteurs de fichier 0, 1 et 2.
Si vous le faites, la première fois que l'application ouvre un fichier, il deviendra stdin / stdout / stderr ...
Par exemple, si vous le faites:
Lorsque
tee
(du moins certaines implémentations, comme busybox ') ouvrent le fichier en écriture, celui-ci sera ouvert dans le descripteur de fichier 1 (stdout). Alorstee
va écriretext
deux fois dansfile
:Cela a été connu pour causer des failles de sécurité. Par exemple:
Et
chsh
(une application setuid) peut finir par écrire des messages d'erreur dans/etc/passwd
.Certains outils et même certaines bibliothèques tentent de se protéger de cela. Par exemple, GNU
tee
déplacera le descripteur de fichier au-dessus de 2 si les fichiers ouverts en écriture se voient attribuer les valeurs 0, 1 et 2, alors que cetee
n'est pas le cas pour busybox .La plupart des outils, s'ils ne peuvent pas écrire sur stdout (parce que, par exemple, ce n'est pas ouvert), enverront un message d'erreur sur stderr (dans la langue de l'utilisateur, ce qui signifie un traitement supplémentaire pour ouvrir et analyser les fichiers de localisation ...), donc ce sera nettement moins efficace et peut entraîner l'échec du programme.
En tout cas, ça ne sera pas plus efficace. Le programme fera toujours un
write()
appel système. Cela ne peut être plus efficace que si le programme abandonne l'écriture sur stdout / stderr après le premierwrite()
appel système ayant échoué , mais les programmes ne le font généralement pas. Ils finissent généralement avec une erreur ou continuent d'essayer.la source
Ce n'est pas une réponse complète à votre question, mais oui, voici comment cela fonctionne.
cat
lit le (s) fichier (s) nommé (s) ou l'entrée standard si aucun fichier n'est nommé, et envoie à sa sortie standard le contenu de ceux-ci jusqu'à ce qu'il rencontre un EOF (incluant l'entrée standard) avec le dernier fichier nommé. C'est son travail.En ajoutant,
>/dev/null
vous redirigez la sortie standard vers / dev / null. C'est un fichier spécial (un nœud de périphérique) qui jette tout ce qui y est écrit (et renvoie immédiatement EOF en lecture). Notez que la redirection d'E / S est une fonctionnalité fournie par le shell, et non par chaque application, et que le nom / dev / null n'a rien de magique , mais seulement ce qui existe dans la plupart des systèmes de type Unix .Il est également important de noter que les mécanismes spécifiques des nœuds de périphériques varient d’un système d’exploitation à l’autre, mais cat (qui, dans un système GNU, signifie coreutils) est multiplate-forme (le même code source doit être exécuté au moins sous Linux et Hurd) et ne peuvent donc pas dépendre de dépendances de noyaux de système d’exploitation spécifiques. En outre, cela fonctionne toujours si vous créez un alias / dev / null (sous Linux, cela signifie un nœud de périphérique avec le même numéro de périphérique majeur / mineur) avec un autre nom. Et il y a toujours le cas d'écrire ailleurs qui se comporte effectivement de la même manière (par exemple, / dev / zero).
Il s’ensuit qu’il
cat
n’est pas au courant des propriétés spéciales de / dev / null et qu’il n’est probablement pas au courant de la redirection au départ, mais il doit toujours effectuer exactement le même travail: il lit les fichiers nommés et affiche le contenu du fichier. le / ces fichier (s) à sa sortie standard. Le fait que la sortie standard decat
va dans un vide ne concerne pas encat
soi.la source
cat mybigfile > /dev/null
feracat
lire chaque octet de labigfile
mémoire. Et, pour chaquen
octet, il appellerawrite(1, buffer, n)
. À l'insu ducat
programme,write
ils ne feront absolument rien (à l'exception peut-être d'une comptabilité triviale). Ecrire à/dev/null
ne nécessite pas de traiter chaque octet.cat
ou de l'autrecp
qui fonctionneraient enmmap
mettant en mémoire de gros morceaux du fichier source, puis en appelantwrite()
la région mappée. Si vous écrivez sur/dev/null
, l'write()
appel sera immédiatement renvoyé sans erreur dans les pages du fichier source, de sorte qu'il ne sera jamais réellement lu à partir du disque.cat
fonctionne sur de nombreuses plates-formes, mais un coup d'œil sur le code source montrera de nombreux#ifdef
s: il ne s'agit pas littéralement du même code que celui qui s'exécute sur toutes les plates-formes et de nombreuses sections dépendant du système.