stdin, stdout et 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 envoyés ou redirigés. Nous vous montrons comment.
Table des matières
Les flux rejoignent deux points
Dès que vous commencez à en apprendre davantage sur les systèmes d’exploitation Linux et Unix, vous rencontrerez les termes stdin, stdout et stederr. Ceux-ci sont trois flux standard 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. La commande Linux que vous utilisez 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
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 fournie via le flux stdout (sortie standard). Les messages d’erreur de la commande sont envoyés via le flux stderr (erreur standard).
Vous pouvez donc voir qu’il existe deux flux de sortie, stdout et stderr, et un flux d’entrée, stdin. Étant donné que les messages d’erreur et la sortie normale ont chacun leur propre conduit pour les transporter 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. Le concept de gestion d’un flux de données sous forme de fichier n’est donc pas si compliqué.
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: stdin
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, avec la grammaire, on nous dit que la règle est « I avant E, sauf après C. » Mais en fait, là sont plus d’exceptions à cette règle qu’il y a des cas qui y obéissent.
Dans la même veine, quand on parle de stdin, stdout et stderr, il est pratique de trotter l’axiome accepté selon lequel un processus ne sait ni ne se soucie de l’endroit où ses trois flux standard se terminent. Un processus doit-il se soucier de savoir si sa sortie va au terminal ou est redirigée dans un fichier? Peut-il même dire si son entrée provient du clavier ou y est acheminée par un autre processus?
En fait, un processus le 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 a décidé d’ajouter cette fonctionnalité.
On voit très facilement ce changement de comportement. Essayez ces deux commandes:
ls
ls | cat
La commande ls se comporte différemment si sa sortie (stdout) est redirigée vers une autre commande. C’est ls qui bascule sur une sortie de colonne unique, 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
Redirection de stdout et stderr
Il y a un avantage à avoir des messages d’erreur envoyés par un flux dédié. Cela signifie que nous pouvons rediriger la sortie d’une commande (stdout) vers un fichier et toujours voir 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 vers lequel stdout a été redirigé.
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 fait écho au texte dans la fenêtre du terminal, via le flux stdout. La deuxième ligne tente d’accéder à un fichier qui n’existe pas. Cela générera un message d’erreur qui est livré via stderr.
Exécutez le script avec cette commande:
./error.sh
Nous pouvons voir que les deux flux de sortie, stdout et stderr, ont été affichés dans les fenêtres du terminal.
Essayons de rediriger la sortie vers un fichier:
./error.sh > capture.txt
La sortie de stdin a été redirigée vers le fichier comme prévu.
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 stdout, utilisez cette instruction de redirection:
1>
Pour rediriger explicitement stderr, utilisez cette instruction de redirection:
2>
Essayons à nouveau notre test, et cette fois nous utiliserons 2>:
./error.sh 2> capture.txt
Le message stderr est dans capture.txt comme prévu.
Redirection à la fois stdout et stderr
Sûrement, si nous pouvons rediriger stdout ou stderr vers un fichier indépendamment l’un de l’autre, nous devrions être en mesure de 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 vers un fichier appelé error.txt.
./error.sh 1> capture.txt 2> error.txt
Vérifions le contenu de chaque fichier:
cat capture.txt
cat error.txt
Redirection de stdout et stderr vers le même fichier
C’est bien, nous avons chacun des flux de sortie standard vers son propre fichier dédié. La seule autre combinaison que nous pouvons faire est d’envoyer à la fois stdout et stderr dans le 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 flux stdout vers le fichier capture.txt. > est un raccourci pour 1>.
2> & 1: Ceci utilise l’instruction de redirection &>. Cette instruction vous permet de dire au shell de faire en sorte qu’un flux arrive à la même destination qu’un autre flux. Dans ce cas, nous disons « rediriger le flux 2, stderr, vers la même destination vers laquelle le flux 1, stdout, est redirigé. »
Vérifions le fichier capture.txt et voyons ce qu’il contient.
cat capture.txt
Les flux stdout et stderr 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 facile à 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 test entre crochets. L’option -t (terminal) renvoie true (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.shThe output shows that the script recognizes that the input isn’t coming from a keyboard, it is coming from a file. If you chose to, you could vary your script’s behavior accordingly.
C'était avec une redirection de fichier, essayons-le avec un tube.
chat dummy.txt | ./input.shLe script reconnaît que son entrée y est envoyée. Ou plus précisément, il reconnaît une fois de plus que le flux stdin n'est pas connecté à une fenêtre de terminal.
Exécutons le script sans tubes ni redirections.
./input.shLe flux stdin 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 fiUtilisez la commande suivante pour le rendre exécutable:
chmod +x input.shLe seul changement significatif à ce script est dans le test entre crochets. Nous utilisons le chiffre 1 pour représenter le descripteur de fichier pour stdout.
Essayons-le. Nous allons diriger la sortie via cat.
./output | catLe script reconnaît que sa sortie ne va pas directement à une fenêtre de terminal.
Nous pouvons également tester le script en redirigeant la sortie vers un fichier.
./output.sh > capture.txtIl n'y a pas de sortie dans la fenêtre du terminal, nous retournons silencieusement à l'invite de commande. Comme on pouvait s'y attendre.
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.shEncore une fois, le simple test de notre script détecte que le flux stdout n'est pas envoyé directement à une fenêtre de terminal.
Si nous exécutons le script sans tubes ni redirections, il devrait détecter que stdout est livré directement dans la fenêtre du terminal.
./output.shEt c'est exactement ce que nous voyons.
Flux de conscience
Savoir savoir si vos scripts sont connectés à la fenêtre du terminal, ou à un tube, ou sont en cours de redirection, vous permet d'ajuster leur comportement en conséquence.
La journalisation et la sortie de diagnostic peuvent être plus ou moins détaillées, selon qu'elles vont à l'écran ou à un fichier. Les messages d'erreur peuvent être enregistrés dans un fichier différent de la sortie normale du programme.
Comme c'est généralement le cas, plus de connaissances apporte plus d'options.