306 votes

Vous ne savez pas ce que sont stdin, stdout et stderr ?

Je suis assez confus quant à l'utilité de ces trois fichiers. Si ma compréhension est correcte, stdin est le fichier dans lequel un programme écrit dans ses requêtes pour exécuter une tâche dans le processus, stdout est le fichier dans lequel le noyau écrit sa sortie et le processus qui le demande accède à l'information, et stderr est le fichier dans lequel toutes les exceptions sont saisies. En ouvrant ces fichiers pour vérifier si celles-ci se produisent effectivement, je n'ai rien trouvé qui le suggère !

Ce que je voudrais savoir, c'est à quoi servent exactement ces fichiers, une réponse absolument simpliste avec très peu de jargon technique !

329voto

paxdiablo Points 341644

Entrée standard - c'est le poignée de fichier que votre processus lit pour obtenir des informations de vous.

Sortie standard - votre processus écrit la sortie conventionnelle dans ce fichier.

Erreur standard - votre processus écrit la sortie de diagnostic dans ce fichier.

C'est le plus simple que je puisse faire :-)

Bien sûr, c'est surtout par convention. Rien ne vous empêche d'écrire vos informations de diagnostic sur la sortie standard si vous le souhaitez. Vous pouvez même fermer totalement les trois poignées de fichiers et ouvrir vos propres fichiers pour les E/S.

Lorsque votre processus démarre, il devrait déjà avoir ces handles ouverts et il peut simplement lire et/ou écrire dessus.

Par défaut, ils sont probablement connectés à votre terminal (par ex, /dev/tty ) mais les shells vous permettront d'établir des connexions entre ces handles et des fichiers et/ou périphériques spécifiques (ou même des pipelines vers d'autres processus) avant le démarrage de votre processus (certaines des manipulations possibles sont plutôt astucieuses).

Un exemple étant :

my_prog <inputfile 2>errorfile | grep XYZ

qui sera :

  • créer un processus pour my_prog .
  • ouvrir inputfile comme entrée standard (poignée de fichier 0).
  • ouvrir errorfile comme erreur standard (poignée de fichier 2).
  • créer un autre processus de grep .
  • joindre la sortie standard de my_prog à l'entrée standard de grep .

Re votre commentaire :

Lorsque j'ouvre ces fichiers dans le dossier /dev, comment se fait-il que je ne vois jamais la sortie d'un processus en cours d'exécution ?

C'est parce que ce ne sont pas des fichiers normaux. Alors qu'UNIX présente tout comme un fichier dans un système de fichiers quelque part, cela ne l'est pas pour autant aux niveaux les plus bas. La plupart des fichiers dans le /dev Les hiérarchies sont des périphériques à caractères ou à blocs, en fait un pilote de périphérique. Ils n'ont pas de taille, mais ils ont un numéro de périphérique majeur et mineur.

Lorsque vous les ouvrez, vous êtes connecté au pilote de périphérique plutôt qu'à un fichier physique, et le pilote de périphérique est suffisamment intelligent pour savoir que des processus distincts doivent être traités séparément.

Il en va de même pour le système Linux /proc système de fichiers. Ce ne sont pas de vrais fichiers, juste des passerelles étroitement contrôlées vers les informations du noyau.

3 votes

C'est pour votre réponse. Bien que je puisse comprendre l'objectif des fichiers à partir de ce que vous décrivez, je voudrais passer à un niveau supérieur. Lorsque j'ouvre ces fichiers dans le dossier /dev, comment se fait-il que je ne puisse jamais voir la sortie d'un processus en cours d'exécution. Disons que j'exécute top sur le terminal, n'est-il pas supposé sortir ses résultats sur le fichier stdout périodiquement, donc quand il est mis à jour, je devrais être capable de voir une instance de la sortie imprimée sur ce fichier. Mais ce n'est pas le cas. Ces fichiers ne sont donc pas les mêmes (ceux du répertoire /dev).

9 votes

Parce que ce ne sont pas techniquement des fichiers. Ce sont des nœuds de périphériques, indiquant un périphérique spécifique sur lequel écrire. UNIX peut présent tout ce qui vous est présenté comme une abstraction de fichier, mais ce n'est pas le cas aux niveaux les plus profonds.

0 votes

Oh ok, ça a beaucoup plus de sens maintenant ! Donc, si je veux accéder au flux de données qu'un processus écrit sur ces "fichiers" auxquels je ne peux pas accéder. Comment serait-il possible pour moi de l'intercepter et de le sortir dans un fichier à moi ? Est-il théoriquement possible d'enregistrer tout ce qui se passe sur chacun de ces fichiers dans un seul fichier pour un processus donné ?

87voto

Jim Lewis Points 18753

Il serait plus correct de dire que stdin , stdout et stderr sont des "flux d'E/S" plutôt que des plutôt que des fichiers. Comme vous l'avez remarqué, ces entités ne vivent pas dans le système de fichiers. Mais la philosophie philosophie d'Unix, en ce qui concerne les E/S, est "tout est un fichier". En pratique, cela signifie réellement que vous pouvez utiliser les mêmes fonctions de bibliothèque et interfaces ( printf , scanf , read , write , select etc.) sans se préoccuper de savoir si le flux d'E/S est connecté à un clavier, un fichier disque, un socket, un pipe, ou toute autre abstraction d'E/S.

La plupart des programmes doivent lire les entrées, écrire les sorties et enregistrer les erreurs, donc stdin , stdout , et stderr sont prédéfinis pour vous, comme une commodité de programmation. Il s'agit uniquement convention, et n'est pas appliquée par le système d'exploitation.

0 votes

Merci pour vos contributions. Sauriez-vous par hasard comment je pourrais intercepter le flux de données de sortie d'un processus et le sortir dans un fichier qui m'est propre ?

80voto

suanik Points 81

En complément des réponses ci-dessus, voici un résumé sur les redirections : Redirections cheatsheet

EDIT : Ce graphique n'est pas tout à fait correct.

Le premier exemple n'utilise pas du tout stdin, il passe "hello" comme argument à la commande echo.

Le graphique indique aussi que 2>&1 a le même effet que &> ; cependant

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>

C'est parce que &> nécessite un fichier vers lequel rediriger, et 2>&1 envoie simplement stderr dans stdout

7 votes

Votre commentaire combiné à la réponse acceptée est parfaitement logique et explique clairement les choses ! Merci !

4 votes

Une image vaut mille mots !

1 votes

&> nécessite un fichier vers lequel rediriger l'entrée, mais 2>&1 ne le fait pas &> sert à la journalisation, mais 2>&1 peut être utilisé pour la journalisation et la visualisation de STDOUT STDERR du terminal en même temps 2>&1 peut être utilisé simplement pour visualiser le STDOUT et le STDERR (dans l'invite de commande du terminal) de votre programme (selon la capacité de votre programme à gérer les erreurs)

30voto

sarnold Points 62720

Je crains que votre compréhension soit complètement à l'envers. :)

Pensez aux termes "entrée standard", "sortie standard" et "erreur standard" du point de vue de l'environnement. du programme et non du point de vue du noyau.

Lorsqu'un programme doit imprimer des données de sortie, il les imprime normalement sur la "sortie standard". Un programme imprime généralement la sortie sur la sortie standard avec printf qui n'imprime QUE sur la sortie standard.

Lorsqu'un programme a besoin d'imprimer des informations sur les erreurs (pas nécessairement les exceptions, qui sont une construction du langage de programmation, imposée à un niveau beaucoup plus élevé), il imprime normalement sur "l'erreur standard". Il le fait normalement avec fprintf qui accepte un flux de fichiers à utiliser lors de l'impression. Le flux de fichiers peut être n'importe quel fichier ouvert pour l'écriture : sortie standard, erreur standard, ou tout autre fichier qui a été ouvert avec la commande fopen o fdopen .

"standard in" est utilisé lorsque le fichier doit lire les données d'entrée, à l'aide de fread o fgets ou getchar .

Chacun de ces fichiers peut être facilement redirigé à partir de l'enveloppe, comme ceci :

cat /etc/passwd > /tmp/out     # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err   # redirect cat's standard error to /tmp/error
cat < /etc/passwd              # redirect cat's standard input to /etc/passwd

Ou, toute l'enchilada :

cat < /etc/passwd > /tmp/out 2> /tmp/err

Il y a deux mises en garde importantes : Premièrement, "entrée standard", "sortie standard" et "erreur standard" ne sont qu'une convention. Il s'agit d'une très forte convention, mais il s'agit juste d'un accord sur le fait qu'il est très agréable de pouvoir exécuter des programmes comme celui-ci : grep echo /etc/services | awk '{print $2;}' | sort et que les sorties standard de chaque programme soient reliées à l'entrée standard du programme suivant dans le pipeline.

Deuxièmement, j'ai donné les fonctions ISO C standard pour travailler avec les flux de fichiers ( FILE * ) -- au niveau du noyau, ce sont tous les descripteurs de fichiers ( int références à la table des fichiers) et des opérations de niveau beaucoup plus bas comme read y write qui ne font pas l'heureuse mise en mémoire tampon des fonctions ISO C. Je me suis dit qu'il fallait rester simple et utiliser les fonctions les plus faciles, mais j'ai quand même pensé que vous deviez connaître les alternatives :)

0 votes

C'est donc lors de l'exécution du processus qu'il écrit les erreurs dans ce fichier stderr ou lorsque le programme est compilé à partir de sa source. De plus, lorsque nous parlons de ces fichiers du point de vue du compilateur, est-ce différent de celui d'un programme ?

1 votes

@Shouvik, le compilateur est juste un autre programme, avec son propre stdin, stdout, et stderr. Lorsque le compilateur a besoin d'écrire des avertissements ou des erreurs, il les écrira dans stderr. Lorsque le frontal du compilateur produit du code intermédiaire pour l'assembleur, il pourrait écrire le code intermédiaire sur stdout et l'assembleur pourrait accepter son entrée sur stdin, mais tout cela serait derrière les coulisses de votre perspective en tant qu'utilisateur). Une fois que vous avez un programme compilé, ce programme peut aussi écrire des erreurs sur son erreur standard, mais cela n'a rien à voir avec le fait d'être compilé.

0 votes

Merci pour ce témoignage d'information. Je suppose que c'est assez stupide de ma part de ne pas le voir sous cet angle de toute façon... :P

20voto

dee Points 456

Je pense que les gens qui disent stderr ne devrait être utilisée que pour les messages d'erreur est trompeuse.

Il doit également être utilisé pour les messages informatifs destinés à l'utilisateur qui exécute la commande et non aux consommateurs potentiels des données en aval (par exemple, si vous exécutez un tube shell enchaînant plusieurs commandes, vous ne souhaitez pas que des messages informatifs tels que "obtention de l'élément 30 sur 42424" apparaissent sur l'écran stdout car ils risquent d'embrouiller le consommateur, mais vous pourriez quand même vouloir que l'utilisateur les voie.

Voir este pour des raisons historiques :

"Tous les programmes plaçaient des diagnostics sur la sortie standard. Cela avait toujours causé des problèmes lorsque la sortie était redirigée vers une fuite, mais mais devenait intolérable lorsque la sortie était envoyée à un processus processus. Néanmoins, ne voulant pas violer la simplicité de la norme modèle entrée standard-sortie standard, les gens ont toléré cet état de fait. d'affaires jusqu'à la v6. Peu de temps après, Dennis Ritchie a tranché le nœud gordien en introduisant le critère d'erreur standard. nœud gordien en introduisant l'erreur standard. Ce n'était pas tout à fait suffisant. Avec les pipelines, les diagnostics pouvaient provenir de n'importe lequel de plusieurs programmes s'exécutant simultanément. Les diagnostics devaient s'identifier eux-mêmes."

0 votes

Le lien historique de justification est rompu - le domaine a disparu !

1 votes

Remplacé par un lien vers archive.org.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X