Τι είναι τα stdin, stdout και stderr στο Linux;

stdin, stdoutκαι stderrδημιουργούνται τρεις ροές δεδομένων κατά την εκκίνηση μιας εντολής Linux. Μπορείτε να τα χρησιμοποιήσετε για να δείτε εάν τα σενάρια σας διοχετεύονται σωστά ή ανακατευθύνονται. Σας δείχνουμε πώς.

Οι ροές ενώνουν δύο πόντους

Μόλις αρχίσετε να μάθετε για το Linux και Unix-όπως λειτουργικά συστήματα, θα συναντήσετε τους όρους stdin, stdoutκαι stederr. Αυτές είναι τρεις τυπικές ροές που δημιουργούνται όταν εκτελείται μια εντολή Linux. Στον υπολογιστή, μια ροή είναι κάτι που μπορεί να μεταφέρει δεδομένα. Στην περίπτωση αυτών των ροών, αυτά τα δεδομένα είναι κείμενο.

Οι ροές δεδομένων, όπως οι ροές νερού, έχουν δύο άκρα. Έχουν πηγή και εκροή. Όποια εντολή Linux χρησιμοποιείτε και παρέχει ένα άκρο κάθε ροής. Το άλλο άκρο καθορίζεται από το κέλυφος που ξεκίνησε την εντολή. Αυτό το άκρο θα συνδεθεί στο παράθυρο του τερματικού, θα συνδεθεί σε ένα σωλήνα ή θα ανακατευθυνθεί σε ένα αρχείο ή άλλη εντολή, σύμφωνα με τη γραμμή εντολών που ξεκίνησε την εντολή.

Οι τυπικές ροές Linux

Στο Linux,  stdinείναι η τυπική ροή εισόδου. Αυτό δέχεται κείμενο ως εισαγωγή του. Η έξοδος κειμένου από την εντολή στο κέλυφος παραδίδεται μέσω της stdoutροής (τυπική έξοδος). Τα μηνύματα σφάλματος από την εντολή αποστέλλονται μέσω της stderrροής (τυπικό σφάλμα).

Έτσι μπορείτε να δείτε ότι υπάρχουν δύο ρεύματα εξόδου, stdoutκαι stderr, και ένα ρεύμα εισόδου, stdin. Επειδή τα μηνύματα σφάλματος και η κανονική έξοδος έχουν το καθένα τον δικό τους αγωγό για να τα μεταφέρουν στο παράθυρο του τερματικού, μπορούν να αντιμετωπιστούν ανεξάρτητα το ένα από το άλλο.

Οι ροές αντιμετωπίζονται σαν αρχεία

Οι ροές στο Linux - όπως σχεδόν όλα τα υπόλοιπα - αντιμετωπίζονται σαν να ήταν αρχεία. Μπορείτε να διαβάσετε κείμενο από ένα αρχείο και να γράψετε κείμενο σε ένα αρχείο. Και οι δύο αυτές ενέργειες περιλαμβάνουν ροή δεδομένων. Επομένως, η έννοια του χειρισμού μιας ροής δεδομένων ως αρχείου δεν είναι τόσο μεγάλη.

Σε κάθε αρχείο που σχετίζεται με μια διαδικασία εκχωρείται ένας μοναδικός αριθμός για την αναγνώρισή του. Αυτό είναι γνωστό ως περιγραφή του αρχείου. Όποτε απαιτείται μια ενέργεια για να εκτελεστεί σε ένα αρχείο, ο περιγραφέας αρχείων χρησιμοποιείται για την αναγνώριση του αρχείου.

Οι τιμές αυτές χρησιμοποιούνται πάντα για stdin, stdout,και stderr:

  • 0 : stdin
  • 1 : stdout
  • 2 : stderr

Αντίδραση σε σωλήνες και ανακατευθύνσεις

Για να διευκολυνθεί η εισαγωγή κάποιου σε ένα θέμα, μια κοινή τεχνική είναι να διδάξει μια απλοποιημένη έκδοση του θέματος. Για παράδειγμα, με τη γραμματική, μας λένε ότι ο κανόνας είναι "I πριν E, εκτός από το C." Στην πραγματικότητα, υπάρχουν περισσότερες εξαιρέσεις σε αυτόν τον κανόνα από ότι υπάρχουν περιπτώσεις που τον υπακούουν.

Στο ίδιο πνεύμα, όταν μιλάμε για stdin, stdoutκαι stderr είναι βολικό να ανασύρουμε από το αποδεκτό αξίωμα ότι η διαδικασία δεν ξέρει ούτε νοιάζεται όταν τερματίστηκε τρεις τυπικές ροές της. Πρέπει μια διαδικασία να φροντίζει εάν η έξοδος της πηγαίνει στο τερματικό ή ανακατευθύνεται σε ένα αρχείο; Μπορεί ακόμη να πει εάν η είσοδος του προέρχεται από το πληκτρολόγιο ή έχει διοχετευτεί σε άλλη διαδικασία;

Στην πραγματικότητα, μια διαδικασία γνωρίζει - ή τουλάχιστον μπορεί να μάθει, εάν επιλέξει να ελέγξει - και μπορεί να αλλάξει τη συμπεριφορά της ανάλογα, εάν ο συγγραφέας λογισμικού αποφάσισε να προσθέσει αυτήν τη λειτουργικότητα.

Μπορούμε να δούμε αυτήν την αλλαγή συμπεριφοράς πολύ εύκολα. Δοκιμάστε αυτές τις δύο εντολές:

είναι

είναι | Γάτα

Η lsεντολή συμπεριφέρεται διαφορετικά εάν η έξοδος της ( stdout) διοχετεύεται σε άλλη εντολή. Είναι  lsπου αλλάζει σε έξοδο μίας στήλης, δεν είναι μετατροπή που εκτελείται από cat. Και lsκάνει το ίδιο πράγμα εάν ανακατευθύνεται η έξοδος του:

ls> capture.txt

cat capture.txt

Ανακατεύθυνση stdout και stderr

Υπάρχει ένα πλεονέκτημα ότι τα μηνύματα σφάλματος παραδίδονται από μια ειδική ροή. Σημαίνει ότι μπορούμε να ανακατευθύνουμε την έξοδο μιας εντολής ( stdout) σε ένα αρχείο και να εξακολουθούμε να βλέπουμε τυχόν μηνύματα σφάλματος ( stderr) στο παράθυρο του τερματικού. Αν χρειαστεί, μπορείτε να αντιδράσετε στα λάθη, όπως συμβαίνουν. Επίσης, σταματά τα μηνύματα σφάλματος να μολύνουν το αρχείο στο οποίο stdoutέχει ανακατευθυνθεί.

Πληκτρολογήστε το ακόλουθο κείμενο σε πρόγραμμα επεξεργασίας και αποθηκεύστε το σε ένα αρχείο που ονομάζεται error.sh.

#! / bin / bash echo "Σχετικά με την προσπάθεια πρόσβασης σε ένα αρχείο που δεν υπάρχει" cat bad-filename.txt

Κάντε το σενάριο εκτελέσιμο με αυτήν την εντολή:

chmod + x error.sh

Η πρώτη γραμμή του σεναρίου αντικατοπτρίζει το κείμενο στο παράθυρο του τερματικού, μέσω της  stdoutροής. Η δεύτερη γραμμή προσπαθεί να αποκτήσει πρόσβαση σε ένα αρχείο που δεν υπάρχει. Αυτό θα δημιουργήσει ένα μήνυμα σφάλματος που παραδίδεται μέσω stderr.

Εκτελέστε το σενάριο με αυτήν την εντολή:

./error.sh

Μπορούμε να δούμε ότι και οι δύο ροές εξόδου stdoutκαι stderr, έχουν εμφανιστεί στα παράθυρα του τερματικού.

Ας προσπαθήσουμε να ανακατευθύνουμε την έξοδο σε ένα αρχείο:

./error.sh> capture.txt

Το μήνυμα σφάλματος που παραδίδεται stderrαποστέλλεται στο παράθυρο του τερματικού. Μπορούμε να ελέγξουμε τα περιεχόμενα του αρχείου για να δούμε αν η stdout έξοδος πήγε στο αρχείο.

cat capture.txt

Η έξοδος από stdinανακατευθύνθηκε στο αρχείο όπως αναμενόταν.

Το >σύμβολο ανακατεύθυνσης λειτουργεί stdoutαπό προεπιλογή. Μπορείτε να χρησιμοποιήσετε έναν από τους αριθμητικούς περιγραφείς αρχείων για να υποδείξετε ποια τυπική ροή εξόδου θέλετε να ανακατευθύνετε.

Για να ανακατευθύνετε ρητά  stdout, χρησιμοποιήστε αυτήν την οδηγία ανακατεύθυνσης:

1>

Για να ανακατευθύνετε ρητά  stderr, χρησιμοποιήστε αυτήν την οδηγία ανακατεύθυνσης:

2>

Ας δοκιμάσουμε ξανά τη δοκιμή μας και αυτή τη φορά θα χρησιμοποιήσουμε 2>:

./error.sh 2> capture.txt

Το μήνυμα σφάλματος ανακατευθύνεται και το stdoutechoμήνυμα αποστέλλεται στο παράθυρο του τερματικού:

Ας δούμε τι υπάρχει στο αρχείο capture.txt.

cat capture.txt

Το stderrμήνυμα βρίσκεται στο capture.txt όπως αναμενόταν.

Ανακατεύθυνση τόσο stdout όσο και stderr

Σίγουρα, αν μπορούμε να ανακατευθύνουμε ένα stdoutή stderrσε ένα αρχείο ανεξάρτητα το ένα από το άλλο, θα έπρεπε να είμαστε σε θέση να τα ανακατευθύνουμε και τα δύο ταυτόχρονα, σε δύο διαφορετικά αρχεία;

Ναι μπορούμε. Αυτή η εντολή θα κατευθύνει stdoutσε ένα αρχείο που ονομάζεται capture.txt και stderrσε ένα αρχείο που ονομάζεται error.txt.

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

Επειδή και οι δύο ροές εξόδου - τυπική έξοδος και τυπικό σφάλμα - ανακατευθύνονται σε αρχεία, δεν υπάρχει ορατή έξοδος στο παράθυρο του τερματικού. Επιστρέφουμε στη γραμμή εντολών σαν να μην έχει συμβεί τίποτα.

Ας δούμε τα περιεχόμενα κάθε αρχείου:

cat capture.txt
σφάλμα γάτας.txt

Ανακατεύθυνση stdout και stderr στο ίδιο αρχείο

Αυτό είναι τακτοποιημένο, έχουμε κάθε μία από τις τυπικές ροές εξόδου στο δικό του ειδικό αρχείο. Ο μόνος άλλος συνδυασμός που μπορούμε να κάνουμε είναι να στείλουμε stdoutκαι τα δύο και stderrστο ίδιο αρχείο.

Μπορούμε να το επιτύχουμε με την ακόλουθη εντολή:

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

Ας το σπάσουμε.

  • ./error.sh : Εκκινεί το αρχείο σεναρίου error.sh.
  • > capture.txt : Ανακατευθύνει τη stdoutροή στο αρχείο capture.txt. >είναι σύντομη για 1>.
  • 2> & 1 : Χρησιμοποιεί την εντολή &> ανακατεύθυνσης. Αυτή η οδηγία σάς επιτρέπει να πείτε στο κέλυφος να κάνει μια ροή στον ίδιο προορισμό με μια άλλη ροή. Σε αυτήν την περίπτωση, λέμε "ανακατεύθυνση ροής 2, stderrστον ίδιο προορισμό με τη ροή 1, stdoutσε ανακατεύθυνση."

Δεν υπάρχει ορατή έξοδος. Αυτό είναι ενθαρρυντικό.

Ας ελέγξουμε το αρχείο capture.txt και να δούμε τι περιέχει.

cat capture.txt

Και οι δύο stdoutκαι οι stderrροές ανακατευθύνθηκαν σε ένα αρχείο προορισμού.

Για να ανακατευθυνθεί η έξοδος μιας ροής και να απομακρυνθεί σιωπηλά, κατευθυνθείτε στην έξοδο /dev/null.

Εντοπισμός ανακατεύθυνσης σε ένα σενάριο

Συζητήσαμε πώς μια εντολή μπορεί να ανιχνεύσει εάν κάποια από τις ροές ανακατευθύνεται και μπορούμε να επιλέξουμε να αλλάξει τη συμπεριφορά της ανάλογα. Μπορούμε να το επιτύχουμε στα δικά μας σενάρια; Ναι μπορούμε. Και είναι μια πολύ εύκολη τεχνική για κατανόηση και χρήση.

Πληκτρολογήστε το ακόλουθο κείμενο σε πρόγραμμα επεξεργασίας και αποθηκεύστε το ως input.sh.

#! / bin / bash εάν [-t 0]; τότε echo stdin που προέρχεται από το πληκτρολόγιο αλλιώς echo stdin που προέρχεται από σωλήνα ή αρχείο fi

Χρησιμοποιήστε την ακόλουθη εντολή για να την εκτελέσετε:

chmod + x input.sh

Το έξυπνο μέρος είναι το τεστ εντός των αγκυλών. Η -tεπιλογή (τερματικό) επιστρέφει true (0) εάν το αρχείο που σχετίζεται με την περιγραφή αρχείου τερματίζεται στο παράθυρο τερματικού. Χρησιμοποιήσαμε τον περιγραφέα αρχείων 0 ως το όρισμα της δοκιμής, που αντιπροσωπεύει   stdin.

Εάν stdinείναι συνδεδεμένο σε παράθυρο τερματικού, το τεστ θα αποδειχθεί αληθινό. Εάν stdinείναι συνδεδεμένο σε αρχείο ή σωλήνα, ο έλεγχος θα αποτύχει.

Μπορούμε να χρησιμοποιήσουμε οποιοδήποτε βολικό αρχείο κειμένου για τη δημιουργία εισόδου στο σενάριο. Εδώ χρησιμοποιούμε ένα που ονομάζεται dummy.txt.

./input.sh <dummy.txt

Η έξοδος δείχνει ότι το σενάριο αναγνωρίζει ότι η είσοδος δεν προέρχεται από πληκτρολόγιο, προέρχεται από αρχείο. Εάν το επιλέξατε, θα μπορούσατε να αλλάξετε τη συμπεριφορά του σεναρίου σας ανάλογα.

Αυτό ήταν με μια ανακατεύθυνση αρχείων, ας το δοκιμάσουμε με έναν σωλήνα.

cat dummy.txt | ./input.sh

Το σενάριο αναγνωρίζει ότι εισάγεται σε αυτό. Ή πιο συγκεκριμένα, αναγνωρίζει για άλλη μια φορά ότι η stdinροή δεν είναι συνδεδεμένη σε παράθυρο τερματικού.

Ας τρέξουμε το σενάριο με ούτε σωλήνες ούτε ανακατευθύνσεις.

./input.sh

Η stdinροή συνδέεται με το παράθυρο του τερματικού και το σενάριο το αναφέρει ανάλογα.

Για να ελέγξουμε το ίδιο με τη ροή εξόδου, χρειαζόμαστε ένα νέο σενάριο. Πληκτρολογήστε τα ακόλουθα σε έναν επεξεργαστή και αποθηκεύστε το ως output.sh.

#! / bin / bash εάν [-t 1]; τότε το echo stdout πηγαίνει στο παράθυρο τερματικού αλλιώς το echo stdout ανακατευθύνεται ή διοχετεύεται με σωλήνες fi

Χρησιμοποιήστε την ακόλουθη εντολή για να την εκτελέσετε:

chmod + x input.sh

Η μόνη σημαντική αλλαγή σε αυτό το σενάριο είναι η δοκιμή στα αγκύλες. Χρησιμοποιούμε το ψηφίο 1 για να αντιπροσωπεύσουμε την περιγραφή του αρχείου για stdout.

Ας το δοκιμάσουμε. Θα διοχετεύσουμε την έξοδο cat.

./ έξοδος | Γάτα

Το σενάριο αναγνωρίζει ότι η έξοδος του δεν πηγαίνει απευθείας σε ένα παράθυρο τερματικού.

Μπορούμε επίσης να δοκιμάσουμε το σενάριο ανακατευθύνοντας την έξοδο σε ένα αρχείο.

./output.sh> capture.txt

Δεν υπάρχει έξοδος στο παράθυρο του τερματικού, επιστρέφουμε σιωπηλά στη γραμμή εντολών. Όπως θα περιμέναμε

Μπορούμε να κοιτάξουμε μέσα στο αρχείο capture.txt για να δούμε τι καταγράφηκε. Χρησιμοποιήστε την ακόλουθη εντολή για να το κάνετε.

cat capture.sh

Και πάλι, η απλή δοκιμή στο σενάριό μας εντοπίζει ότι η stdoutροή δεν αποστέλλεται απευθείας σε παράθυρο τερματικού.

Εάν εκτελέσουμε το σενάριο χωρίς σωλήνες ή ανακατευθύνσεις, θα πρέπει να εντοπίσει ότι stdoutπαραδίδεται απευθείας στο παράθυρο του τερματικού.

./output.sh

Και αυτό ακριβώς βλέπουμε.

Ρεύματα συνείδησης

Γνωρίζοντας πώς να διαπιστώσετε εάν τα σενάρια σας είναι συνδεδεμένα στο παράθυρο του τερματικού ή σε έναν σωλήνα ή ανακατευθύνονται, σας επιτρέπει να προσαρμόσετε ανάλογα τη συμπεριφορά τους.

Η καταγραφή και η έξοδος διαγνωστικών μπορεί να είναι περισσότερο ή λιγότερο λεπτομερείς, ανάλογα με το αν πηγαίνει στην οθόνη ή σε ένα αρχείο. Τα μηνύματα σφάλματος μπορούν να καταγραφούν σε διαφορετικό αρχείο από το κανονικό αποτέλεσμα του προγράμματος.

Όπως συμβαίνει συνήθως, περισσότερες γνώσεις φέρνουν περισσότερες επιλογές.