web-dev-qa-db-fra.com

Confus à propos de stdin, stdout et stderr?

Je suis plutôt confus avec le but de ces trois fichiers. Si ma compréhension est correcte, stdin est le fichier dans lequel un programme écrit dans ses demandes d'exécution d'une tâche dans le processus, stdout est le fichier dans lequel le noyau écrit sa sortie et le processus qui la demande. accède aux informations depuis, et stderr est le fichier dans lequel toutes les exceptions sont entrées. En ouvrant ces fichiers pour vérifier s'ils se produisaient, je n'ai rien trouvé qui puisse le suggérer!

Ce que je voudrais savoir, c’est quel est exactement le but de ces fichiers, répondons avec une réponse absolument stupide avec très peu de jargon technologique!

186
Shouvik

Entrée standard - il s'agit du descripteur de fichier que votre processus lit pour obtenir des informations de votre part.

Sortie standard - votre processus écrit des informations normales dans ce descripteur de fichier.

Erreur standard - votre processus écrit les informations d'erreur dans ce descripteur de fichier.

C'est à peu près aussi bête que je peux le faire :-)

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

Lorsque votre processus démarre, ces poignées doivent déjà être ouvertes et il ne peut que lire et/ou écrire dessus.

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

Un exemple étant:

my_prog <inputfile 2>errorfile | grep XYZ

qui va:

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

Re votre commentaire:

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

C'est parce qu'ils ne sont pas des fichiers normaux. Bien que UNIX présente tout comme un fichier quelque part dans un système de fichiers, cela ne le rend pas aussi bas. La plupart des fichiers de la hiérarchie /dev sont des périphériques de type caractère ou bloc, ce qui 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. Ce dernier 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 de fichiers Linux /proc. Ce ne sont pas de vrais fichiers, juste des passerelles étroitement contrôlées vers les informations du noyau.

209
paxdiablo

Il serait plus correct de dire que stdin, stdout et stderr sont des "flux d'E/S" plutôt que des fichiers. Comme vous l'avez remarqué, ces entités ne résident pas dans le système de fichiers. Mais la philosophie 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 et interfaces de la bibliothèque (printf, scanf, read, write, select, etc.) sans vous soucier de savoir si le flux d'E/S est connecté à un clavier, à un fichier de disque, à un socket, à un tuyau ou à une autre abstraction d'E/S.

La plupart des programmes ont besoin de lire les entrées, d'écrire les sorties et de consigner les erreurs. Ainsi, stdin, stdout et stderr sont prédéfinis pour votre commodité de programmation. Ceci est seulement une convention et n'est pas appliqué par le système d'exploitation.

49
Jim Lewis

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

EDIT: Ce graphique n’est pas tout à fait correct mais je ne sais pas pourquoi ...

Le graphique indique 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 &>
34
Leopold Gault

Je crains que votre compréhension soit complètement en arrière. :)

Pensez à "standard in", "standard out" et "erreur standard" du point de vue du programme, pas du point de vue du noyau.

Lorsqu'un programme doit imprimer une sortie, il imprime normalement vers "sortie standard". Un programme imprime généralement la sortie sur la sortie standard avec printf, qui imprime UNIQUEMENT sur la sortie standard.

Lorsqu'un programme doit imprimer des informations d'erreur (pas nécessairement des exceptions, il s'agit d'une construction en langage de programmation imposée à un niveau beaucoup plus élevé), il affiche normalement "l'erreur standard". Il le fait normalement avec fprintf, qui accepte un flux de fichiers à utiliser lors de l'impression. Le flux de fichier peut être n’importe quel fichier ouvert en écriture: sortie standard, erreur standard ou tout autre fichier ouvert avec fopen ou fdopen.

"standard in" est utilisé lorsque le fichier doit lire une entrée, en utilisant fread ou fgets, ou getchar.

N'importe lequel de ces fichiers peut être facilement redirigé depuis le shell, 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, "standard in", "standard out" et "erreur standard" ne sont qu'une convention. Il s’agit d’une convention très forte, mais c’est simplement un accord selon lequel il est très agréable de pouvoir exécuter des programmes comme celui-ci: grep echo /etc/services | awk '{print $2;}' | sort et d’avoir les sorties standard de chaque programme reliées à la entrée standard du prochain programme en cours.

Deuxièmement, j'ai donné les fonctions ISO C standard pour travailler avec des flux de fichiers (objets FILE *) - au niveau du noyau, ce sont tous les descripteurs de fichier (int références à la table des fichiers) et beaucoup les opérations de niveau inférieur telles que read et write, qui ne font pas la mise en mémoire tampon des fonctions ISO C. Je pensais rester simple et utiliser les fonctions les plus simples, mais je pensais tout de même que vous devriez connaître les alternatives. :)

22
sarnold

stdin

Lit les entrées via la console (par exemple, une entrée au clavier). Utilisé en C avec scanf

scanf(<formatstring>,<pointer to storage> ...);

stdout

Produit une sortie vers la console. Utilisé en C avec printf

printf(<string>, <values to print> ...);

stderr

Génère une sortie "erreur" sur la console. Utilisé en C avec fprintf

fprintf(stderr, <string>, <values to print> ...);

La redirection

Le source de stdin peut être redirigé. Par exemple, au lieu de provenir d'une entrée au clavier, cela peut provenir d'un fichier (echo < file.txt) ou d'un autre programme (ps | grep <userid>).

Les destinations pour stdout, stderr peuvent également être redirigées. Par exemple, stdout peut être redirigé vers un fichier: ls . > ls-output.txt, dans ce cas, le résultat est écrit dans le fichier ls-output.txt. Stderr peut être redirigé avec 2>.

7
mikek3332002

Je pense que les gens qui disent stderr ne devraient être utilisés que pour les messages d'erreur est trompeur.

Il doit également être utilisé pour les messages informatifs destinés à l'utilisateur qui exécute la commande et non pour les utilisateurs potentiels en aval des données (c'est-à-dire que si vous exécutez un canal Shell chaînant plusieurs commandes, vous ne souhaitez pas recevoir de messages informatifs tels que "obtenir le point 30 de 42424 "pour apparaître sur stdout car ils dérangeront le consommateur, mais vous voudrez peut-être que l'utilisateur les voie.

Voir this pour justification historique:

"Tous les programmes plaçaient des diagnostics sur la sortie standard. Cela posait toujours des problèmes lorsque la sortie était redirigée dans un fichier, mais devenait intolérable lorsque la sortie était envoyée à un processus sans méfiance. Néanmoins, le fait de ne pas vouloir violer la simplicité de l'entrée standard modèle de sortie standard, les gens ont toléré cet état de fait jusqu'à la version 6. Peu de temps après, Dennis Ritchie a coupé le nœud gordien en introduisant le fichier d'erreur standard. Cela ne suffisait pas. Avec les pipelines, les diagnostics pouvaient provenir de plusieurs programmes exécutés simultanément. s'identifier. "

5
dee

Utiliser ps -aux révèle les processus en cours, qui sont tous répertoriés dans/proc/as/proc/(pid) /, en appelant cat/proc/(pid)/fd/0, tout ce qui se trouve dans la sortie standard de ce processus je pense. Alors peut être,

/ proc/(pid)/fd/0 - Fichier de sortie standard
/proc/(pid)/fd/1 - Fichier d'entrée standard
/proc/(pid)/fd/2 - Fichier d'erreur standard

par exemplemy terminal window

Mais cela n’a fonctionné que pour/bin/bash, d’autres processus n’ayant généralement rien en 0, beaucoup d’entre eux avaient des erreurs écrites en 2

3
Sam

Pour obtenir des informations faisant autorité sur ces fichiers, consultez les pages de manuel, exécutez la commande sur votre terminal.

$ man stdout 

Mais pour une réponse simple, chaque fichier est pour:

stdout pour un flux sortant

stdin pour une entrée de flux

stderr pour les erreurs d'impression ou les messages du journal.

Chaque programme unix a chacun de ces flux.

2
Margach Chris

stderr ne fera pas IO La mise en mémoire cache, donc si notre application doit imprimer les informations critiques du message (quelques erreurs, exceptions) sur la console ou dans un fichier, utilisez-les où utilisez stdout pour imprimer les informations générales du journal ainsi que IO La mise en mémoire cache, il est possible qu'avant d'écrire nos messages dans l'application de fichier se ferme, le débogage reste complexe

2
geekanil

Un fichier associé à la mise en mémoire tampon est appelé flux et est déclaré pointeur sur un type défini FILE. La fonction fopen () crée certaines données descriptives pour un flux et renvoie un pointeur pour désigner le flux dans toutes les transactions ultérieures. Normalement, il existe trois flux ouverts avec des pointeurs constants déclarés dans l'en-tête et associés aux fichiers ouverts standard. Au démarrage du programme, trois flux sont prédéfinis et n'ont pas besoin d'être explicitement ouverts: entrée standard (pour lire une entrée conventionnelle), sortie standard (pour écriture d'une sortie conventionnelle) et erreur standard (pour l'écriture d'une sortie de diagnostic). Lorsqu'il est ouvert, le flux d'erreur standard n'est pas entièrement mis en mémoire tampon; les flux d'entrée et de sortie standard sont entièrement mis en mémoire tampon si et seulement si le flux peut être déterminé de ne pas faire référence à un périphérique interactif

https://www.mkssoftware.com/docs/man5/stdio.5.asp

0
Bahruz Balabayov