Dois-je utiliser des crochets simples ou doubles pour rediriger vers / dev / null?

18

La plupart des réponses ici [ 1 ] [ 2 ] [ 3 ] utilisent une parenthèse angulaire simple pour rediriger vers / dev / null, comme ceci:

command > /dev/null

Mais l'ajout à / dev / null fonctionne aussi:

command >> /dev/null

À part le caractère supplémentaire, y a-t-il une raison de ne pas le faire? Est-ce que l'une ou l'autre de ces options est "plus agréable" pour l'implémentation sous-jacente de / dev / null?

Edit:
L' open (2) manpage dit lseek est appelée avant chaque écriture dans un fichier en mode append:

O_APPEND
Le fichier est ouvert en mode ajout. Avant chaque écriture (2), le décalage de fichier est positionné à la fin du fichier, comme avec lseek (2). La modification de l'offset de fichier et l'opération d'écriture sont effectuées en une seule étape atomique.

ce qui me fait penser qu'il pourrait y avoir une minuscule pénalité de performance pour l'utilisation >>. Mais d'un autre côté, tronquer / dev / null semble être une opération non définie selon ce document:

O_TRUNC
Si le fichier existe déjà et est un fichier normal et que le mode d'accès permet l'écriture (c'est-à-dire O_RDWR ou O_WRONLY), il sera tronqué à la longueur 0. Si le fichier est un fichier FIFO ou de périphérique terminal, l'indicateur O_TRUNC est ignoré. Sinon, l'effet de O_TRUNC n'est pas spécifié.

et la spécification POSIX dit >doit tronquer un fichier existant , mais O_TRUNC est défini par l'implémentation pour les fichiers de périphérique et il n'y a pas de mot sur la façon dont / dev / null devrait répondre à la tronquage .

Donc, tronquer / dev / null n'est-il pas réellement spécifié? Et les appels lseek ont-ils un impact sur les performances d'écriture?

Morgan
la source

Réponses:

27

Par définition /dev/nullcoule tout ce qui y est écrit , donc peu importe que vous écriviez en mode ajout ou non, tout est rejeté. Comme il ne stocke pas les données, il n'y a vraiment rien à ajouter.

Donc au final, c'est juste plus court pour écrire > /dev/nullavec un seul >signe.

Quant à l'ajout édité:

La page de manuel open (2) indique que lseek est appelé avant chaque écriture dans un fichier en mode ajout.

Si vous lisez attentivement, vous verrez qu'il est dit (soulignement le mien):

le décalage du fichier est positionné à la fin du fichier, comme avec lseek (2)

Cela signifie qu'il n'a pas (besoin) d'appeler réellement l'appel lseeksystème, et l'effet n'est pas non plus strictement le même: appeler lseek(fd, SEEK_END, 0); write(fd, buf, size);sans O_APPENDn'est pas la même chose qu'une écriture en mode ajout, car avec des appels séparés, un autre processus pourrait écrire dans le fichier entre les appels système, en supprimant les données ajoutées. En mode ajout, cela ne se produit pas (sauf sur NFS, qui ne prend pas en charge le mode ajout réel ).

Le texte dans la norme ne mentionne pas lseekà ce stade, seulement que les écritures iront à la fin du fichier.

Donc, tronquer / dev / null n'est-il pas réellement spécifié?

À en juger par l'Écriture à laquelle vous vous référez, elle est apparemment définie par l'implémentation. Cela signifie que toute mise en œuvre sensée fera la même chose qu'avec les tuyaux et les ATS, à savoir rien. Une implémentation insensée pourrait faire autre chose, et peut-être que la troncature pourrait signifier quelque chose de sensé dans le cas d'un autre fichier de périphérique.

Et les appels lseek ont-ils un impact sur les performances d'écriture?

Essaye-le. C'est la seule façon de savoir avec certitude sur un système donné. Ou lisez la source pour voir où le mode d'ajout change le comportement, le cas échéant.

ilkkachu
la source
-3

Si c'est l'efficacité que vous voulez, utilisez command >&-plutôt. Cela ferme le descripteur de fichier plutôt que de le rediriger, donc vous ne perdez pas de temps à lui écrire des choses.

db48x
la source
3
Ne fermez pas les flux à moins de 3. Cela alias les descripteurs std * avec des descripteurs de fichiers aléatoires; potentiellement avec des résultats catastrophiques.
Joshua
7
Si vous fermez simplement le descripteur de fichier, le programme recevra des erreurs à chaque appel d'écriture, ce qui entraînera probablement des messages d'erreur gênants et éventuellement le programme se terminera avant de terminer sa tâche.
ilkkachu