Quand utiliser le flux d'erreur standard dans une application en ligne de commande?

9

Existe-t-il une indication quant à l'utilisation de l'erreur lors de l'écriture d'une application en ligne de commande? À ma grande surprise, je n'ai rien trouvé sur Google.

En particulier, la question qui m'inquiète en ce moment est de savoir s'il faut utiliser stdoutou stderrquand l'utilisateur a appelé le programme avec des arguments illégaux. Cependant, une réponse plus complète est très appréciée car ce ne sera sûrement pas le seul cas dans lequel une règle claire est nécessaire pour écrire un programme qui se comporte de la manière attendue par l'utilisateur.

UTF-8
la source
Est-il correct que ces messages d'erreur soient mélangés avec la sortie régulière? Par exemple, le programme est-il un filtre pour les données?
thrig
Ce n'est pas un filtre pour les données. Ce n'est pas non plus interactif. L'utilisateur l'appelle avec des arguments (parmi lesquels se trouvent des chemins de fichiers), le programme fonctionne, modifie ces fichiers, imprime quelques messages, n'imprime idéalement aucun message d'erreur et se termine.
UTF-8 du

Réponses:

15

Oui, affichez un message stderrlorsque les mauvais arguments sont utilisés. Et si cela entraîne également la fermeture de l'application, quittez avec un état de sortie différent de zéro.

Vous devez utiliser le flux d'erreurs standard pour les messages de diagnostic ou pour l'interaction avec l'utilisateur. Les messages de diagnostic incluent des messages d'erreur, des avertissements et d'autres messages qui ne font pas partie de la sortie de l'utilitaire lorsqu'il fonctionne correctement («correctement» signifiant qu'il ne se passe rien d'exceptionnel, comme les fichiers non trouvés ou quoi que ce soit).

De nombreux shells (tous?) Affichent des invites, les types d'utilisateurs, les menus, etc. stderrpour que la redirection stdoutne vous empêche pas d'interagir avec le shell de manière significative.

Voici un article de blog sur ce sujet:

Ceci est une citation de Doug McIllroy, inventeur des tuyaux Unix, expliquant comment stderrest né. 'v6' fait référence à une version d'une version spécifique du système d'exploitation Unix original qui a été publié en 1975.

Tous les programmes ont placé des diagnostics sur la sortie standard. Cela avait toujours causé des problèmes lorsque la sortie était redirigée vers un fichier, mais était devenu intolérable lorsque la sortie était envoyée à un processus sans méfiance. Néanmoins, ne voulant pas violer la simplicité du modèle d'entrée-standard-sortie-standard, les gens ont toléré cet état de fait via la v6. Peu de temps après, Dennis Ritchie a coupé le nœud gordien en introduisant le fichier d'erreur standard. Ce n'était pas tout à fait suffisant. Avec les pipelines, les diagnostics peuvent provenir de plusieurs programmes exécutés simultanément. Les diagnostics devaient s'identifier.
- Doug McIllroy, "Un lecteur de recherche UNIX: extraits annotés du manuel du programmeur, 1971-1986"

"S'identifier" signifie simplement dire "Hé! C'est moi qui parle! Cela a mal tourné: [...]":

$ ls nothere
ls: nothere: No such file or directory

Faire ceci stderrest préférable, car il pourrait autrement être lu par ce qui était en train de lire stdout(mais nous ne le faisons pas de lstoute façon , n'est-ce pas ?).

Kusalananda
la source
Donc, lorsque vous demandez quelque chose à l'utilisateur pendant que l'application est en cours d'exécution, vous devez imprimer la question sur stderr? Cela ne semble pas juste. Avez-vous une source pour cela? Est-ce que cela s'applique uniquement aux applications qui ont une sortie autre que de simples questions et réponses (sortie que l'utilisateur peut vouloir diriger quelque part)?
UTF-8 du
@ UTF-8 Le texte de la question doit-il être considéré comme faisant partie du résultat du programme? Qu'en est-il de ce que l'utilisateur tape? Je ne pense pas que cela devrait être (tout comme les obus ne pensent pas que cela devrait être). Mais cela dépend peut-être de l'application?
Kusalananda
1
Merci pour ton montage. En attendant, j'ai vérifié le comportement des applications standard et elles se comportent comme on pourrait s'attendre à ce qu'elles se comportent après avoir lu votre réponse.
UTF-8 du
@ UTF-8, vous trouverez peut-être ces questions / réponses pertinentes: unix.stackexchange.com/q/331611/22222
terdon
5

À partir des spécifications POSIX pour les flux standard:

Au démarrage du programme, trois flux doivent être prédéfinis et n'ont pas besoin d'être ouverts explicitement: entrée standard (pour lire l'entrée conventionnelle), sortie standard (pour écrire la sortie conventionnelle) et erreur standard (pour écrire la sortie de diagnostic ).

En d'autres termes, les erreurs, les informations de débogage et tout ce qui relève de la catégorie de diagnostic sont inclus stderr.

Voir la question connexe pour plus d'informations: les rapports de progression / informations de journalisation appartiennent-ils à stderr ou stdout?

Sergiy Kolodyazhnyy
la source