Que sont stdin, stdout et stderr sous Linux ?


Points clés à retenir

  • Les commandes Linux créent trois flux de données (stdin, stdout et stderr) qui peuvent être utilisés pour transférer des données sur une commande.
  • stdin est le flux d’entrée, stdout est le flux de sortie et stderr est le flux d’erreurs sous Linux.
  • La redirection vous permet de rediriger la sortie ou les erreurs vers différentes destinations, telles que des fichiers ou des canaux.


stdin, stdoutet stderr sont trois flux de données créés lorsque vous lancez une commande Linux. Vous pouvez les utiliser pour savoir si vos scripts sont redirigés ou redirigés. Nous vous montrons comment.


Les flux rejoignent deux points

Dès que vous commencerez à vous renseigner sur les systèmes d’exploitation Linux et de type Unix, vous rencontrerez les termes stdin, stdoutet stederr . Ceux-ci sont trois flux standards qui sont établis lorsqu’une commande Linux est exécutée. En informatique, un flux est quelque chose qui peut transférer des données. Dans le cas de ces flux, ces données sont du texte.

Les flux de données, comme les flux d’eau, ont deux extrémités. Ils ont une source et une sortie. Quelle que soit la commande Linux que vous utilisez, elle fournit une extrémité de chaque flux. L’autre extrémité est déterminée par le shell qui a lancé la commande. Cette extrémité sera connectée à la fenêtre du terminal, connectée à un tube ou redirigée vers un fichier ou une autre commande, selon la ligne de commande qui a lancé la commande.

Les flux standard Linux : stdin, stdout, stderr

Sous Linux, stdin est le flux d’entrée standard. Cela accepte le texte comme entrée. La sortie texte de la commande vers le shell est transmise via le stdout (sortie standard). Les messages d’erreur de la commande sont envoyés via le stderr (erreur standard).

Vous pouvez donc voir qu’il y a deux flux de sortie, stdout et stderret un flux d’entrée, stdin. Étant donné que les messages d’erreur et les sorties normales ont chacun leur propre canal pour les acheminer vers la fenêtre du terminal, ils peuvent être traités indépendamment les uns des autres.

Les flux sont traités comme des fichiers

Les flux sous Linux — comme presque tout le reste — sont traités comme s’il s’agissait de fichiers. Vous pouvez lire du texte à partir d’un fichier et écrire du texte dans un fichier. Ces deux actions impliquent un flux de données. Ainsi, le concept de gestion d’un flux de données sous forme de fichier n’est pas si exagéré.

Chaque fichier associé à un processus se voit attribuer un numéro unique pour l’identifier. C’est ce qu’on appelle le descripteur de fichier. Chaque fois qu’une action doit être effectuée sur un fichier, le descripteur de fichier est utilisé pour identifier le fichier.

Ces valeurs sont toujours utilisées pour stdin, stdout, et stderr:

  • 0 : entrée standard
  • 1 : sortie standard
  • 2 : stderr

Réagir aux tuyaux et aux redirections

Pour faciliter l’introduction d’un sujet à quelqu’un, une technique courante consiste à enseigner une version simplifiée du sujet. Par exemple, en grammaire, on nous dit que la règle est « I avant E, sauf après C ». Mais en fait, là sont d’autres exceptions à cette règle qu’il y a des cas qui y obéissent.

Dans le même ordre d’idées, lorsqu’on parle de stdin, stdoutet stderr il est commode de répéter l’axiome accepté selon lequel un processus ne sait pas et ne se soucie pas de l’endroit où se terminent ses trois flux standards. Un processus doit-il se soucier de savoir si sa sortie va au terminal ou est redirigée vers un fichier ? Peut-il même savoir si sa saisie provient du clavier ou si elle y est transmise depuis un autre processus ?

En fait, un processus sait – ou du moins il peut le découvrir s’il choisit de vérifier – et il peut modifier son comportement en conséquence si l’auteur du logiciel décide d’ajouter cette fonctionnalité.

Nous pouvons constater ce changement de comportement très facilement. Essayez ces deux commandes :

ls

ls dans une fenêtre de terminal

ls | cat

ls sortie dans une fenêtre de terminal

Le ls la commande se comporte différemment si sa sortie (stdout) est redirigé vers une autre commande. C’est ls qui passe à une sortie à une seule colonne, ce n’est pas une conversion effectuée par cat. Et ls fait la même chose si sa sortie est redirigée :

ls > capture.txt

ls > capture.txt dans une fenêtre de terminal » style= »display:block;height:auto;max-width:100%; » data-img-url= »https://static1.howtogeekimages.com/wordpress/wp-content/uploads/2019/08/41.png »/> </picture> </figure>
</p></div>
</p></div>
<p><!-- Repeatable debug data:

cat capture.txt

cat capture.txt dans une fenêtre de terminal

Redirection de stdout et stderr

Il y a un avantage à ce que les messages d’erreur soient transmis par un flux dédié. Cela signifie que nous pouvons rediriger la sortie d’une commande (stdout) dans un fichier et je vois toujours les messages d’erreur (stderr) dans la fenêtre du terminal. Vous pouvez réagir aux erreurs si nécessaire, au fur et à mesure qu’elles se produisent. Cela empêche également les messages d’erreur de contaminer le fichier qui stdout a été redirigé vers.

Tapez le texte suivant dans un éditeur et enregistrez-le dans un fichier appelé error.sh.

 #!/bin/bash
echo "About to try to access a file that doesn't exist"
cat bad-filename.txt

Rendez le script exécutable avec cette commande :

chmod +x error.sh

La première ligne du script renvoie le texte dans la fenêtre du terminal, via le stdout flux. La deuxième ligne tente d’accéder à un fichier qui n’existe pas. Cela générera un message d’erreur qui sera envoyé via stderr.

Exécutez le script avec cette commande :

./error.sh

./error.sh dans une fenêtre de terminal

Nous pouvons voir que les deux flux de sortie, stdout et stderront été affichés dans les fenêtres du terminal.

sortie du script error.sh dans une fenêtre de terminal

Essayons de rediriger la sortie vers un fichier :

./error.sh > capture.txt

./error.sh > capture.txt dans une fenêtre de terminal » style= »display:block;height:auto;max-width:100%; » data-img-url= »https://static1.howtogeekimages.com/wordpress/wp-content/uploads/2019/08/3.png »/> </picture> </figure>
</p></div>
</p></div>
<p><!-- Repeatable debug data:

Le message d’erreur envoyé via stderr est toujours envoyé à la fenêtre du terminal. Nous pouvons vérifier le contenu du fichier pour voir si le stdout la sortie est allée dans le fichier.

cat capture.txt

cat capture.txt dans une fenêtre de terminal

La sortie de stdin a été redirigé vers le fichier comme prévu.

contenu de capture.txt dans une fenêtre de terminal

Le > le symbole de redirection fonctionne avec stdout par défaut. Vous pouvez utiliser l’un des descripteurs de fichier numériques pour indiquer le flux de sortie standard que vous souhaitez rediriger.

Pour rediriger explicitement stdoututilisez cette instruction de redirection :

1>

Pour rediriger explicitement stderrutilisez cette instruction de redirection :

2>

Essayons à nouveau notre test, et cette fois nous utiliserons 2>:

./error.sh 2> capture.txt

La sortie Error.sh n’existe pas.

Le message d’erreur est redirigé et le stdout echo Le message est envoyé à la fenêtre du terminal :

stdout est envoyé au terminal.

Voyons ce qu’il y a dans le fichier capture.txt.

cat capture.txt

cat capture.txt dans une fenêtre de terminal

Le stderr le message est dans capture.txt comme prévu.

Capture.txt a le contenu auquel nous nous attendons.

Redirection à la fois stdout et stderr

Sûrement, si nous pouvons rediriger l’un ou l’autre stdout ou stderr vers un fichier indépendamment l’un de l’autre, on devrait pouvoir les rediriger tous les deux en même temps, vers deux fichiers différents ?

Oui nous pouvons. Cette commande dirigera stdout vers un fichier appelé capture.txt et stderr dans un fichier appelé error.txt.

./error.sh 1> capture.txt 2> error.txt

Envoi de stderr et stdout vers deux fichiers distincts.

Étant donné que les deux flux de sortie (sortie standard et erreur standard) sont redirigés vers des fichiers, aucune sortie n’est visible dans la fenêtre du terminal. Nous revenons à l’invite de ligne de commande comme si de rien n’était.

Le terminal n'affichera rien puisque la sortie est redirigée.

Vérifions le contenu de chaque fichier :

cat capture.txt

cat error.txt

Nos deux fichiers texte, error.txt et capture.txt, contiennent les informations correctes.

Redirection de stdout et stderr vers le même fichier

C’est bien, chacun des flux de sortie standard est dirigé vers son propre fichier dédié. La seule autre combinaison que nous pouvons faire est d’envoyer les deux stdout et stderr au même fichier.

Nous pouvons y parvenir avec la commande suivante :

./error.sh > capture.txt 2>&1

Décomposons cela.

  • ./error.sh : lance le fichier de script error.sh.
  • > capture.txt : redirige le stdout flux vers le fichier capture.txt. > est un raccourci pour 1>.
  • 2>&1 : cela utilise l’instruction de redirection &>. Cette instruction vous permet d’indiquer au shell de faire en sorte qu’un flux arrive à la même destination qu’un autre flux. Dans ce cas, nous disons « redirection du flux 2, stderrvers la même destination que le flux 1, stdoutest redirigé vers. »

Une manière concise de rediriger les deux sorties vers un seul fichier.

Il n’y a aucune sortie visible. C’est encourageant.

Encore une fois, aucune sortie dans le Terminal.

Vérifions le fichier capture.txt et voyons ce qu’il contient.

cat capture.txt

Capture.txt contient correctement la sortie de stderr et stdout.

Les deux stdout et stderr les flux ont été redirigés vers un seul fichier de destination.

Pour que la sortie d’un flux soit redirigée et supprimée silencieusement, dirigez la sortie vers /dev/null.

Détection de la redirection dans un script

Nous avons expliqué comment une commande peut détecter si l’un des flux est redirigé et peut choisir de modifier son comportement en conséquence. Pouvons-nous accomplir cela dans nos propres scripts ? Oui nous pouvons. Et c’est une technique très simple à comprendre et à utiliser.

Tapez le texte suivant dans un éditeur et enregistrez-le sous input.sh.

 #!/bin/bash
if [ -t 0 ]; then
echo stdin coming from keyboard
else echo stdin coming from a pipe or a file
fi

Utilisez la commande suivante pour le rendre exécutable :

chmod +x input.sh

La partie intelligente est la tester entre crochets. Le -t L’option (terminal) renvoie vrai (0) si le fichier associé au descripteur de fichier se termine dans la fenêtre du terminal. Nous avons utilisé le descripteur de fichier 0 comme argument du test, qui représente stdin.

Si stdin est connecté à une fenêtre de terminal, le test s’avérera vrai. Si stdin est connecté à un fichier ou à un tube, le test échouera.

Nous pouvons utiliser n’importe quel fichier texte pratique pour générer une entrée dans le script. Ici, nous en utilisons un appelé dummy.txt.

./input.sh < dummy.txt

Diriger l’entrée d’un script.

La sortie montre que le script reconnaît que l’entrée ne provient pas d’un clavier, mais d’un fichier. Si vous le souhaitez, vous pouvez modifier le comportement de votre script en conséquence.

Reconnaît correctement qu'il provient d'un tube ou d'un fichier.

C’était avec une redirection de fichier, essayons avec un tube.

cat dummy.txt | ./input.sh

28-1

Le script reconnaît que son entrée y est redirigée. Ou plus précisément, il reconnaît une fois de plus que stdin Le flux n’est pas connecté à une fenêtre de terminal.

Reconnaît correctement qu'il provient d'un tube ou d'un fichier.

Exécutons le script sans tuyaux ni redirections.

./input.sh

Exécution du script d'entrée.

Le stdin stream est connecté à la fenêtre du terminal et le script le signale en conséquence.

Pour vérifier la même chose avec le flux de sortie, nous avons besoin d’un nouveau script. Tapez ce qui suit dans un éditeur et enregistrez-le sous output.sh.

 #!/bin/bash
if [ -t 1 ]; then
echo stdout is going to the terminal window
else
echo stdout is being redirected or piped
fi

Utilisez la commande suivante pour le rendre exécutable :

chmod +x input.sh

Le seul changement significatif apporté à ce script réside dans le test entre crochets. Nous utilisons le chiffre 1 pour représenter le descripteur de fichier pour stdout.

Essayons-le. Nous acheminerons la sortie via cat.

./output | cat

32-1

Le script reconnaît que sa sortie ne va pas directement vers une fenêtre de terminal.

La sortie est acheminée hors de la fenêtre du terminal.

Nous pouvons également tester le script en redirigeant la sortie vers un fichier.

./output.sh > capture.txt

Sortie vers capture.txt

Il n’y a aucune sortie dans la fenêtre du terminal, nous revenons silencieusement à l’invite de commande. Comme on pouvait s’y attendre.

Une autre fenêtre de terminal vide résultant de l'envoi de la sortie vers un fichier texte.

Nous pouvons regarder à l’intérieur du fichier capture.txt pour voir ce qui a été capturé. Utilisez la commande suivante pour ce faire.

cat capture.sh

Capture.txt contient le rapport indiquant que la commande a été transmise.

Encore une fois, le simple test de notre script détecte que le stdout le flux n’est pas envoyé directement à une fenêtre de terminal.

Si nous exécutons le script sans aucun canal ni redirection, il devrait détecter cela stdout est livré directement à la fenêtre du terminal.

./output.sh

Exécution de output.sh sans arguments.

Et c’est exactement ce que nous voyons.

stdout va au terminal.

Flux de conscience

Savoir comment savoir si vos scripts sont connectés à la fenêtre du terminal, ou à un tube, ou s’ils sont redirigés, vous permet d’ajuster leur comportement en conséquence.

Les résultats de journalisation et de diagnostic peuvent être plus ou moins détaillés, selon qu’ils sont dirigés vers l’écran ou vers un fichier. Les messages d’erreur peuvent être enregistrés dans un fichier différent de celui de la sortie normale du programme.

Comme c’est généralement le cas, plus de connaissances apportent plus d’options.



Vous pouvez lire l’article original (en Angais) sur le blogwww.howtogeek.com