Στον κόσμο της διεπαφής γραμμής εντολών, τα προγράμματα αλληλεπιδρούν συχνά με τρεις τυπικές ροές δεδομένων:
stdin): Όπου ένα πρόγραμμα δέχεται την είσοδό του (συνήθως από το πληκτρολόγιο).stdout): Όπου ένα πρόγραμμα στέλνει την κανονική έξοδό του (συνήθως στην οθόνη του τερματικού).stderr): Όπου ένα πρόγραμμα στέλνει μηνύματα σφάλματος (συνήθως στην οθόνη του τερματικού).Θυμήσου ότι τα παρουσιάσαμε στο κεφάλαιο Σωληνώσεις και λίστες εντολών.
Οι σωληνώσεις μπορούν να θεωρηθούν μια μορφή ανακατεύθυνσης: η τυπική έξοδος ενός προγράμματος στέλνεται απευθείας στην τυπική είσοδο ενός άλλου. Έχουμε ήδη καλύψει τις σωληνώσεις. Αυτή η έννοια θα καλύψει την ανακατεύθυνση από και προς αρχεία.
Η ανακατεύθυνση στο κέλυφος είναι ένας ισχυρός μηχανισμός που σου επιτρέπει να αλλάξεις τον προορισμό αυτών των ροών. Αντί ένα πρόγραμμα να διαβάζει από το πληκτρολόγιο ή να γράφει στην οθόνη, μπορείς να ανακατευθύνεις την είσοδο από ένα αρχείο ή να στέλνεις την έξοδο σε ένα αρχείο. Αυτό σου δίνει σημαντική ευελιξία και έλεγχο στον τρόπο που τα προγράμματα αλληλεπιδρούν με τα δεδομένα.
Ακολουθούν οι πιο συνηθισμένοι τελεστές ανακατεύθυνσης και το τι κάνουν:
> (Ανακατεύθυνση εξόδου)Σκοπός: Να ανακατευθύνεις την τυπική έξοδο (stdout) μιας εντολής σε ένα αρχείο.
Συμπεριφορά:
Παράδειγμα:
# Sends the output of 'ls -l' to 'file_listing.txt'
ls -l > file_listing.txt
Η ανακατεύθυνση γίνεται πριν εκτελεστεί η εντολή. Αυτό σημαίνει ότι δεν μπορείς να ανακατευθύνεις στο ίδιο αρχείο από το οποίο πρέπει να διαβάσεις.
date > date.txt # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!
Στη δεύτερη εντολή του παραπάνω παραδείγματος,
>> (Ανακατεύθυνση εξόδου με προσάρτηση)Σκοπός: Να προσαρτήσεις την τυπική έξοδο (stdout) μιας εντολής σε ένα αρχείο.
Συμπεριφορά:
Παράδειγμα:
# Adds "Another line" to the end of the file
echo "Another line" >> file_listing.txt
< (Ανακατεύθυνση εισόδου)Σκοπός: Να ανακατευθύνεις την τυπική είσοδο (stdin) μιας εντολής από ένα αρχείο.
Συμπεριφορά: Η εντολή διαβάζει την είσοδό της από το συγκεκριμένο αρχείο αντί από το πληκτρολόγιο.
Παράδειγμα:
# 'tr' reads from 'lowercase.txt' and
# output is redirected to 'uppercase.txt'
tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
2> (Ανακατεύθυνση σφάλματος):stderr) μιας εντολής σε ένα αρχείο.# Error message from 'rm' is sent to 'error_log.txt'
rm non_existent_file 2> error_log.txt
Μπορείς να προσαρτήσεις το τυπικό σφάλμα σε ένα αρχείο με το 2>>.
Υπάρχουν επίσης ανακατευθύνσεις που μπορούν να συγχωνεύσουν και το stdin και το stderr.
Δες το εγχειρίδιο για λεπτομέρειες.
/dev/nullΤο /dev/null είναι ένα ειδικό αρχείο που
Μερικές φορές αναφέρεται ως "ο κάδος bits". Είναι χρήσιμο για να καταστέλλεις έξοδο ή σφάλματα.
some_command > /dev/null # Discards stdout
some_command 2> /dev/null # Discards stderr
# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null
Μπορούν να δοθούν πολλαπλές ανακατευθύνσεις ταυτόχρονα.
some_command < input.txt > output.txt 2> error.txt
Μια ανακατεύθυνση μπορεί να αντιγραφεί.
# send stderr to the same destination as stdout
some_command > output.txt 2>&1
Όταν βλέπεις 2>&1, διάβασέ το ως "ανακατεύθυνε το stderr σε ό,τι δείχνει αυτή τη στιγμή το stdout".
Το Bash επεξεργάζεται τις οδηγίες ανακατεύθυνσης αυστηρά από αριστερά προς τα δεξιά, που σημαίνει ότι μπορείς να κάνεις:
# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
Στο πλαίσιο του προγραμματισμού κελύφους και λειτουργικών συστημάτων όπως το Linux/Unix, ο περιγραφέας αρχείου (FD, file descriptor) είναι ένας μη αρνητικός ακέραιος που λειτουργεί ως αναγνωριστικό ή λαβή για ένα ανοιχτό αρχείο ή έναν πόρο I/O (είσοδος/έξοδος). Σκέψου το σαν μια ετικέτα ή έναν αριθμό αναφοράς που χρησιμοποιεί το λειτουργικό σύστημα για να παρακολουθεί ανοιχτά αρχεία και ροές δεδομένων.
Οι αριθμοί που βλέπεις στην αριστερή πλευρά των ανακατευθύνσεων είναι περιγραφείς αρχείων.
Στις τυπικές ροές I/O δίνονται οι πρώτοι 3 περιγραφείς αρχείων:
Νέοι περιγραφείς αρχείων μπορούν να οριστούν ή να δημιουργηθούν με την εντολή exec και τους τελεστές ανακατεύθυνσης.
# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt
# then redirect both stdout and file descriptor 3
echo "some debug message" >&3 # displayed in the terminal
some_command 2>&1 # stdout and stderr send to 'log.txt'
Αυτή η τεχνική φαίνεται αρκετά μπερδεμένη, αλλά μπορεί να είναι πολύ χρήσιμη σε περιπτώσεις όπου το σενάριό σου εκτελείται από κάποιο άλλο πακέτο λογισμικού και η τυπική έξοδος συλλαμβάνεται αυτόματα από το λογισμικό.
Η εντολή bats που χρησιμοποιείται για να τρέξει τα unit tests αυτού του track λειτουργεί έτσι: το bats συλλαμβάνει το stdout και το stderr ενός τεστ, αλλά τα μηνύματα αποσφαλμάτωσης που στέλνονται στον FD 3 εμφανίζονται στο τερματικό.
Γιατί είναι χρήσιμη η ανακατεύθυνση;
Οι ανακατευθύνσεις του κελύφους σου δίνουν λεπτομερή έλεγχο στο πώς τα προγράμματα αλληλεπιδρούν με τα δεδομένα, επιτρέποντάς σου να χτίζεις σύνθετες ροές εργασίας και να διαχειρίζεσαι αποτελεσματικά τις πληροφορίες.