Γλώσσες κελύφους εντολών Shell (sh, bash, ksh και άλλες). Κέλυφος εντολών ως γλώσσα προγραμματισμού

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

Τι είναι ένα κέλυφος;

κέλυφος εντολών ( κέλυφος) παρέχει αλληλεπίδραση μεταξύ του χρήστη και του περιβάλλοντος λειτουργικού συστήματος Linux. Είναι ένα εξειδικευμένο προϊόν λογισμικού που διασφαλίζει την εκτέλεση εντολών και τη λήψη των αποτελεσμάτων της εκτέλεσής τους ή, για να το θέσω πολύ απλά, ένα κέλυφος είναι ένα πρόγραμμα που έχει σχεδιαστεί για να διασφαλίζει την εκτέλεση άλλων προγραμμάτων κατόπιν αιτήματος του χρήστη. Ένα παράδειγμα κελύφους θα μπορούσε να είναι, για παράδειγμα, ένας διερμηνέας εντολών command.comλειτουργικό σύστημα MS DOS ή κέλυφος βίαιο χτύπημαΛειτουργικά συστήματα Unix/Linux.

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

Ερμηνεία γραμμή εντολών.

Πρόσβαση σε εντολές και τα αποτελέσματα της εκτέλεσής τους.

Υποστήριξη για μεταβλητές, ειδικούς χαρακτήρες και δεσμευμένες λέξεις.

Επεξεργασία αρχείων, τυπικές λειτουργίες εισόδου και εξόδου.

Εκτέλεση ειδική γλώσσαπρογραμματισμός κελύφους.

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

sh- κέλυφος Οριο, κλασικό κέλυφος για Unix OS

βίαιο χτύπημακέλυφος Bourne Ξανά(GNU Bourne-Again SHell). Ίσως το πιο κοινό αυτή τη στιγμή, ένα κέλυφος στο περιβάλλον λειτουργικού συστήματος Linux.

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

csh- κέλυφος ντο, χρησιμοποιώντας τη σύνταξη μιας δημοφιλής γλώσσας προγραμματισμού ντο

tcsh- έκδοση κελύφους ντομε διαδραστική επεξεργασία γραμμής εντολών.

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

    Κατά τη διαδικασία φόρτωσης των λειτουργικών συστημάτων της οικογένειας Linux, μετά τη φόρτωση του πυρήνα του συστήματος, το σύστημα μεταβαίνει σε διαδραστική λειτουργία - τον τρόπο αλληλεπίδρασης μεταξύ του χρήστη και του λειτουργικού συστήματος. Στο Linux, η πρώτη διαδικασία που ξεκινά κατά την εκκίνηση είναι το πρόγραμμα init. στην αρχή, το οποίο διαβάζει τα περιεχόμενα του αρχείου διαμόρφωσης /etc/inittab, καθορίζει τη λίστα και τα χαρακτηριστικά των τερματικών που είναι διαθέσιμα στο σύστημα και καλεί το διαδραστικό πρόγραμμα σύνδεσης getty, το οποίο σας ζητά να εισαγάγετε το όνομα χρήστη σας. Αφού εισαγάγετε το όνομα χρήστη και τον κωδικό πρόσβασης, το πρόγραμμα gettyκαλεί το πρόγραμμα σύνδεση, το οποίο ελέγχει την εγκυρότητα λογαριασμός, πλοηγείται στον αρχικό κατάλογο του χρήστη και μεταβιβάζει τον έλεγχο στο πρόγραμμα εκκίνησης περιόδου λειτουργίας, το οποίο είναι συνήθως το πρόγραμμα φλοιού του χρήστη, η συγκεκριμένη γεύση του οποίου καθορίζεται από τα περιεχόμενα του αρχείου /etc/passwdγια αυτόν τον λογαριασμό. Για παράδειγμα:

user1:x:508:511::/home/user1:/bin/sh
interbase:x:510:511::/home/interbase:/bin/csh
apb:x:511:513:apb:/home/apb:/bin/bash

Όπως φαίνεται από τα περιεχόμενα του αρχείου /etc/passwd, για τον χρήστη χρήστη 1το κέλυφος θα εκτοξευθεί sh(Bourne shell), για χρήστη μεσοβάση- κέλυφος csh(C shell) και για τον χρήστη απβ- κέλυφος βίαιο χτύπημα(Bourne Again) Μετά την εκκίνηση του κελύφους, εμφανίζεται μια γραμμή εντολών στην οθόνη (συνήθως με τη μορφή σύμβολο δολαρίου $ εάν η εργασία γίνεται στο πλαίσιο ενός λογαριασμού τακτικός χρήστης, ή λίρα # , εάν το κέλυφος χρησιμοποιείται σε λογαριασμό χρήστη root ( ρίζα).

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

Μέσω της ομάδας έξοδοςεκτελείται από τον χρήστη

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

Ερμηνεία γραμμής εντολών.

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

ls -l file01 file02

Περιέχει την εντολή ls, την επιλογή -l και δύο ονόματα αρχείων file01 file02.

Όταν χρησιμοποιείτε πολλές επιλογές, μπορούν να συνδυαστούν. Για παράδειγμα, οι ακόλουθες επιλογές εντολών είναι πανομοιότυπες:

Ls -l -d
ls -ld

Οι εντολές που αποτελούν μέρος του κελύφους καλούνται ενσωματωμένο. Τέτοιες εντολές περιλαμβάνουν, για παράδειγμα, cd, if, case, κ.λπ. Φυσικά, οι ενσωματωμένες εντολές μπορεί να διαφέρουν για διαφορετικές επιλογές φλοιού. Εκτός από τις ενσωματωμένες εντολές, είναι δυνατή η χρήση μονάδων προγράμματος, που είναι ξεχωριστά εκτελέσιμα αρχεία ή αρχεία σενάριαή σενάρια- συνηθισμένα αρχεία κειμένου που περιέχουν διαδοχικά εκτελούμενες γραμμές με εντολές φλοιού. Ορισμένα σενάρια (scripts) μπορούν να εκτελεστούν από διαδικασίες Linux, όπως ο προγραμματιστής εργασιών cron. Ο προγραμματιστής εργασιών είναι συνήθως σχεδιασμένος για να εκτελεί αυτόματα εργασίες διαχείρισης συστήματος σε ένα χρονοδιάγραμμα. Καθήκοντα cronείναι εντολές ή σενάρια και εκτελούνται αυτόματα, χωρίς ανθρώπινη παρέμβαση και μπορούν να εκτελεστούν στο πλαίσιο διαφορετικών λογαριασμών χρηστών. Στην περίπτωση που η εργασία χρονοπρογραμματιστή περιλαμβάνει την εκτέλεση ενός σεναρίου, προκύπτει το πρόβλημα της επιλογής ενός κελύφους που θα πρέπει να ξεκινήσει ως θυγατρική διαδικασία cronγια την επεξεργασία εντολών από ένα αρχείο σεναρίου - τελικά, το κέλυφος μπορεί να είναι οποιοδήποτε και η σύνταξη ενός σεναρίου, κατά κανόνα, απαιτεί τη χρήση του συγκεκριμένου φλοιού για το οποίο είναι γραμμένο. Για την εξάλειψη αυτού του προβλήματος, στα λειτουργικά συστήματα Linux είναι συνηθισμένο να υποδεικνύεται στην πρώτη γραμμή του σεναρίου ο τύπος του κελύφους που απαιτείται για την εκτέλεσή του, με τη μορφή:

#!/bin/bash- για κέλυφος βίαιο χτύπημα

#!/bin/sh- για κέλυφος sh

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

Κατά την εκτέλεση εντολών ή σεναρίων, χρησιμοποιήστε μεταβλητές περιβάλλοντος(στα αγγλικά - περιβάλλο, οι αξίες του οποίου χαρακτηρίζουν περιβάλλον λογισμικού, στο οποίο εκτελούνται εντολές. Τέτοιες μεταβλητές μπορεί να περιέχουν γενικές ρυθμίσεις συστήματος, παραμέτρους γραφικών ή κελύφους εντολών, διαδρομές εκτελέσιμων αρχείων κ.λπ. Οι τιμές των μεταβλητών περιβάλλοντος ορίζονται σε επίπεδο συστήματος (για όλους τους χρήστες) και σε επίπεδο συγκεκριμένου χρήστη. Για να ορίσετε μεταβλητές περιβάλλοντος σε επίπεδο συστήματος, χρησιμοποιούνται τα περιεχόμενα των αρχείων:

/etc/profile- ορίζει μεταβλητές μόνο για κελύφη εντολών. Μπορεί να εκτελέσει οποιοδήποτε σενάριο σε κελύφη συμβατό με το κέλυφος Bourne.

/etc/bash.bashrc- ορίζει μεταβλητές μόνο για διαδραστικά κελύφη. Εκτελεί επίσης σενάρια bash.

/etc/περιβάλλον- χρησιμοποιείται από τη μονάδα PAM-env. Μόνο ζεύγη μπορούν να καθοριστούν σε αυτό το αρχείο όνομα=τιμή.

Κάθε ένα από αυτά τα αρχεία έχει τη δική του εφαρμογή, επομένως θα πρέπει να επιλέξετε προσεκτικά αυτό που ταιριάζει στους σκοπούς σας. Για παράδειγμα, εάν πρέπει να προσθέσετε έναν προσαρμοσμένο κατάλογο ~/binσε μια μεταβλητή ΜΟΝΟΠΑΤΙγια όλους τους χρήστες, τοποθετήστε τον ακόλουθο κώδικα σε ένα από τα αρχεία προετοιμασίας περιβάλλοντος συστήματος (/etc/profile ή /etc/bash.bashrc):

# Εάν το αναγνωριστικό χρήστη είναι μεγαλύτερο ή ίσο με 1000 και υπάρχει ένας κατάλογος ~/bin και

#δεν έχει προστεθεί προηγουμένως στη μεταβλητή PATH,

# εξαγωγή ~/bin στο $PATH.

Αν [[ $UID -ge 1000 && -d $HOME/bin && -z $(echo $PATH | grep -o $HOME/bin)

Εξαγωγή PATH=$HOME/bin:$(PATH)

Συνήθως σε χειρουργεία Συστήματα Linux,Το User ID μικρότερο από 1000 ή μικρότερο από 500 χρησιμοποιείται για λογαριασμούς υπηρεσιών. ΣΕ σε αυτό το παράδειγμα, η μεταβλητή περιβάλλοντος θα οριστεί για όλους τοπικούς χρήστεςσυστήματα με αναγνωριστικό 1000 ή περισσότερο.

Εάν πρέπει να αλλάξετε το περιβάλλον για έναν συγκεκριμένο χρήστη, τροποποιήστε τα περιεχόμενα του περιβάλλοντος του χρήστη:

- ~/.bash_profile, ~/.bash_loginκαι τα λοιπά. - Αρχεία προετοιμασίας κελύφους από τον αρχικό κατάλογο του χρήστη.

- ~/.προφίλ- αρχείο προετοιμασίας προφίλ χρήστη. Χρησιμοποιείται από πολλά κελύφη για τον ορισμό μεταβλητών περιβάλλοντος.

~/.pam_environment- ένα προσαρμοσμένο ανάλογο του αρχείου /etc/environment, το οποίο χρησιμοποιείται από τη λειτουργική μονάδα PAM-env.

Για παράδειγμα, για να προσθέσετε τον κατάλογο χρήστη ~/bin στη διαδρομή αναζήτησης των εκτελέσιμων αρχείων που καθορίζονται από τη μεταβλητή ΜΟΝΟΠΑΤΙ, για παράδειγμα, σε ένα αρχείο ~/.προφίλβάλε τη γραμμή:

εξαγωγή PATH="$(PATH):/home/user/bin"

Για να ορίσετε μεταβλητές περιβάλλοντος για γραφικές εφαρμογές, χρησιμοποιούνται τα περιεχόμενα των αρχείων διαμόρφωσης γραφικό περιβάλλονχρήστες ~/.xinitrc

Συχνότερα, ορίζονται τιμές μεταβλητών περιβάλλοντος για την τρέχουσα περίοδο λειτουργίας χρήστη. Για παράδειγμα, για να προσθέσετε έναν προσαρμοσμένο κατάλογο ~/binστη διαδρομή αναζήτησης για εκτελέσιμα αρχεία:

εξαγωγή PATH=~/bin:$PATH

Νέα τιμή μεταβλητής ΜΟΝΟΠΑΤΙθα διαρκέσει μόνο μέχρι να τελειώσει η τρέχουσα συνεδρία χρήστη.

Για να δείτε την τιμή μιας μεταβλητής, μπορείτε να χρησιμοποιήσετε την εντολή echo $μεταβλητή, Για παράδειγμα:

ηχώ $PATH

Επί του παρόντος, το πιο κοινό κέλυφος, όπως αναφέρθηκε παραπάνω, είναι βίαιο χτύπημα. Αυτό προκαλείται κυρίως από το γεγονός ότι το κέλυφος βίαιο χτύπημαείναι sh- ένα συμβατό κέλυφος εντολών, το οποίο προσθέτει χρήσιμες λειτουργίες από το κέλυφος Korn ( ksh) και κέλυφος C ( csh). Κέλυφος βίαιο χτύπημαμπορεί να εκτελέσει τα περισσότερα σενάρια γραμμένα για μια γλώσσα προγραμματισμού φλοιού χωρίς καμία τροποποίηση shκαι προσπαθεί να πλησιάσει όσο το δυνατόν πιο κοντά στο πρότυπο POSIX, το οποίο οδήγησε σε πολλές βελτιώσεις, τόσο για τον προγραμματισμό όσο και για χρήση σε διαδραστική λειτουργία. Σε σύγχρονη εφαρμογή βίαιο χτύπημαυπάρχει μια λειτουργία επεξεργασίας γραμμής εντολών, απεριόριστο μέγεθος ιστορικού εντολών, εργαλεία διαχείρισης εργασιών, δυνατότητα χρήσης ψευδωνύμων, εκτενής λίστα ενσωματωμένων εντολών, λειτουργίες κελύφους εντολών κ.λπ. Γενικά, βίαιο χτύπηματαιριάζει καλύτερα στις ανάγκες του μέσου χρήστη, γεγονός που το έχει καταστήσει το πιο χρησιμοποιούμενο στο περιβάλλον Linux.

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

ΣΕ αυτό το τμήμαέχει παρασχεθεί τεκμηρίωση για να βοηθήσει τον προγραμματιστή σε γλώσσες κελύφους εντολών κελύφους (sh, bash, ksh και άλλες)

Διερμηνέας εντολών c-shell

0. Εισαγωγή

Ο διερμηνέας εντολών στο περιβάλλον UNIX εκτελεί δύο κύριες λειτουργίες:

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

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

Στο περιβάλλον UNIX (σε αντίθεση, ας πούμε, στο DOS) υπάρχουν πολλά διαφορετικά διερμηνείς εντολών. Ας αναφέρουμε τα πιο δημοφιλή:

/bin/sh - κέλυφος Bourne. Ιστορικά, είναι το πρώτο κέλυφος εντολών που αναπτύχθηκε για την πρώτη έκδοση του λειτουργικού συστήματος UNIX. Επί του παρόντος, αυτό το κέλυφος είναι το κύριο κέλυφος στις εκδόσεις του UNIX System V.
/bin/csh - C-shell. Ένα κέλυφος του οποίου η σύνταξη της γλώσσας εντολών είναι κοντά στη γλώσσα C Είναι το κύριο κέλυφος για την έκδοση Berkeley του λειτουργικού συστήματος UNIX.
/bin/ksh - k-shell.
/bin/rsh - Περιορισμένο κέλυφος. Είναι sh με περιορισμένες δυνατότητες (κυρίως για την προστασία του λειτουργικού συστήματος από μη εξουσιοδοτημένες ενέργειες χρήστη).

Το λειτουργικό σύστημα ConvexOS είναι μια γεύση 4.3 BSD UNIX()BSD - Berkeley Series Distribution και επομένως το βασικό κέλυφος είναι csh.

1. Κύρια χαρακτηριστικά

Εργασία με τη γραμμή εντολών

Ο διερμηνέας αντιλαμβάνεται τη συμβολοσειρά που πληκτρολογεί ο χρήστης ως εντολή (ή πολλές εντολές). Η σύνταξη του κελύφους σας επιτρέπει να πληκτρολογείτε

πολλές εντολές σε μία γραμμή, χωρισμένες με ερωτηματικά. Για παράδειγμα

ισοδυναμεί με δύο εντολές που εισάγονται διαδοχικά:

Αντίθετα, εάν το επιθυμεί, ο χρήστης μπορεί

συνεχίστε να πληκτρολογείτε την εντολή long στην επόμενη γραμμή, τελειώνοντας την τρέχουσα γραμμή με ένα \\. Μέχρι να ολοκληρώσετε την εντολή, θα λάβετε ένα «δευτερεύον προτροπή» > αντί για το κύριο (%). Για παράδειγμα,

% tar tv Makefile star.o star.c star.dat main.o main.c

ισοδύναμος

%tar tv Makefile star.o\

> star.c star.dat \

Οι ροές εισόδου/εξόδου ελέγχονται με παρόμοιο τρόπο με το DOS (Ακριβέστερα, το λειτουργικό σύστημα DOS υιοθέτησε τη σύνταξη ανακατεύθυνσης νήματος από το UNIX) χρησιμοποιώντας τα σύμβολα > , > > ,

Χρήσιμος ειδική περίπτωσηχρησιμοποιώντας τον μηχανισμό ανακατεύθυνσης νήματος - ανακατεύθυνση στο /dev/null, που σας επιτρέπει να απαλλαγείτε από περιττά μηνύματα στην οθόνη. Χρησιμοποιώντας τον ίδιο μηχανισμό, μπορείτε να δημιουργήσετε κενά αρχεία:

θα δημιουργήσει ένα κενό αρχείο myfile στον τρέχοντα κατάλογο.

Επιπλέον, το C-shell σάς επιτρέπει να ομαδοποιείτε εντολές χρησιμοποιώντας παρενθέσεις. Σε αυτήν την περίπτωση, ολόκληρη η κατασκευή μέσα στις αγκύλες θεωρείται από τον διερμηνέα ως μία εντολή. Αυτό είναι χρήσιμο, για παράδειγμα, σε τέτοιες κατασκευές:

% (εντολή1 | εντολή2)

Εάν παραλείψετε τις παρενθέσεις, το κέλυφος δεν θα μπορεί να προσδιορίσει ποια εντολή θέλετε να εισαγάγετε το αρχείο myfile.

Υπάρχουν οι ακόλουθες «ευκολίες» σε αυτήν την υλοποίηση του C-shell:

Μπορείτε να αποφύγετε να πληκτρολογήσετε μια μεγάλη εντολή μέχρι το τέλος, αλλά δοκιμάστε να πατήσετε το πλήκτρο tab αφού πληκτρολογήσετε εν μέρει την εντολή (ή το όνομα αρχείου). Το C-shell θα προσπαθήσει να ολοκληρώσει το ίδιο τους χαρακτήρες που λείπουν ή θα απαντήσει με ένα τρίξιμο εάν η επιλογή είναι διφορούμενη.
Εάν πληκτρολογήσατε μια εντολή αλλά ξεχάσατε τις επιλογές της, πληκτρολογήστε την ακολουθία H. Το C-shell θα παρέχει σύντομη βοήθεια. Για παράδειγμα,

Δακτυλογραφία ονοματεπώνυμοαρχείο, χρησιμοποιήστε τον συνδυασμό πλήκτρων ^D. Θα μπορείτε να λάβετε μια λίστα με τον κατάλογο που πληκτρολογείτε με τη μορφή της εντολής lf.
Το buffer εντολών θυμάται τις τελευταίες 20 εντολές. Αντί να πληκτρολογήσετε μια εντολή, μπορείτε να την καλέσετε από το buffer χρησιμοποιώντας το πληκτρολόγιο με βέλη (φυσικά, μόνο εάν αυτή η εντολή βρίσκεται στην προσωρινή μνήμη).

Ανάλυση γραμμής εντολών

Ο διερμηνέας, έχοντας λάβει τη γραμμή εντολών, εκτελεί έναν αριθμό μετασχηματισμών σε αυτήν, και συγκεκριμένα:

Επεκτείνει τα ψευδώνυμα
Επεκτείνει τους μεταχαρακτήρες (*, ?, [, ], ~, (, ))
Αντικαθιστά μεταβλητές φλοιού
Εκτελεί την εντολή εάν είναι μια ενσωματωμένη εντολή διερμηνέα ή ξεκινά μια διαδικασία εάν η εντολή είναι εξωτερική.

Ας δούμε αυτά τα βήματα βήμα προς βήμα.

Ψευδώνυμο. Η εντολή ενσωματωμένο ψευδώνυμο σάς επιτρέπει να ορίσετε ψευδώνυμα εντολών. Παράδειγμα:

% ψευδώνυμο mycat "cat | περισσότερα"

ορίζει το mycat ως ψευδώνυμο για το string cat | περισσότερο. Επομένως, περαιτέρω έχετε το δικαίωμα να χρησιμοποιήσετε την εντολή mycat, η οποία θα επεκταθεί από τον διερμηνέα όπου κι αν τη χρησιμοποιήσετε. Αυτός είναι ένας τρόπος ορισμού σύντομων ονομάτων για μεγάλες σύνθετες εντολές.

Η ενσωματωμένη εντολή unalias mycat καταστρέφει το ψευδώνυμο mycat που είχε εισαχθεί προηγουμένως.

Μεταχαρακτήρες. Οι μεταχαρακτήρες σάς επιτρέπουν να συντομεύετε ολόκληρες λίστες λέξεων (κυρίως ονόματα αρχείων). Το Shell αντιμετωπίζει μια λέξη που περιέχει μεταχαρακτήρες ως πρότυπο για τη δημιουργία μιας λίστας ονομάτων αρχείων:

* στο πρότυπο αντικαθιστά οποιαδήποτε ακολουθία χαρακτήρων. Για παράδειγμα, το m* θα επεκταθεί σε μια λίστα με όλα τα αρχεία που ξεκινούν με το γράμμα m. Υπάρχει μια μικρή εξαίρεση σε αυτόν τον κανόνα: απλά * παραλείπει από τη λίστα εκείνα τα αρχεία των οποίων τα ονόματα αρχίζουν με μια τελεία.
? αντικαθιστά έναν χαρακτήρα. Για παράδειγμα m; θα επεκταθεί σε μια λίστα με όλα τα ονόματα αρχείων που ξεκινούν με το γράμμα m και αποτελούνται ακριβώς από δύο γράμματα.
Το [.-.] σας επιτρέπει να καθορίσετε το διάστημα για τον αντικατεστημένο χαρακτήρα. Για παράδειγμα το m θα επεκταθεί σε ma mb mc me.
(...,...) σας επιτρέπει να παραθέσετε λέξεις για αντικατάσταση. Έτσι, για παράδειγμα, το m(κόκκινο, μπλε, πράσινο) θα επεκταθεί σε mred mblue mgreen.

Τέλος, το tilde σάς επιτρέπει να καθορίσετε τον αρχικό κατάλογο του χρήστη:

Το ~name/ ισοδυναμεί με τον καθορισμό της πλήρους διαδρομής προς τον αρχικό κατάλογο του ονόματος χρήστη (Πείτε /usr1/name/)
Το ~/ ισοδυναμεί με τον καθορισμό της πλήρους διαδρομής προς τον οικιακό σας κατάλογο.

Μεταβλητές Shell. Οι λέξεις που ξεκινούν με το σύμβολο $ ερμηνεύονται από τον διερμηνέα εντολών ως ονόματα μεταβλητών. Οι μεταβλητές χωρίζονται σε μεταβλητές περιβάλλοντος (θα είναι γνωστές σε όλους όσους καλούνται από αυτό προγράμματα κελύφουςκαι είναι υπό αυτή την έννοια καθολικές) και απλές μεταβλητές.

Η ενσωματωμένη εντολή set name=value σάς επιτρέπει να ορίσετε μια απλή μεταβλητή που ονομάζεται όνομα και να της δώσετε την τιμή τιμής. Όταν ο διερμηνέας συναντήσει την έκφραση $name στη γραμμή εντολών, θα την αντικαταστήσει με τιμή. Για παράδειγμα,

%set color=μπλε

θα εμφανίσει τη μπλε γραμμή στο τερματικό. ΕΝΑ

%set color=μπλε

% echo new$color

θα δώσει newblue. Τέλος, μπαίνοντας

%set color=μπλε

% echo $(color)new

παίρνουμε νέο χρώμα. Το τελευταίο παράδειγμα δείχνει πώς να το χρησιμοποιήσετε τιράντεςγια να εξαγάγετε ένα όνομα μεταβλητής από μια λέξη (για να επαναλάβετε το $colornew, ο διερμηνέας θα απαντούσε ότι η μεταβλητή colornew δεν έχει οριστεί.

Η εντολή unset καταστρέφει προηγουμένως καθορισμένες μεταβλητές.

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

% set color="μπλε ή κόκκινο ή πράσινο"

Οι απλές μεταβλητές μπορεί να είναι πίνακες λέξεων (που πρέπει να διακρίνονται από την περίπτωση που μόλις συζητήθηκε, όταν η μεταβλητή περιέχει μια σειρά από πολλές λέξεις. Για να δηλώσετε έναν πίνακα, πρέπει να χρησιμοποιήσετε παρενθέσεις:

% σύνολο χρωμάτων=(μπλε κόκκινο πράσινο)

Τώρα το echo $colors θα παράγει μια σειρά τριών χρωμάτων (δοκιμάστε το!). Ωστόσο, μπορείτε επίσης να εργαστείτε σε ξεχωριστά στοιχείαπίνακας (τα στοιχεία αριθμούνται ξεκινώντας από το μηδέν), για παράδειγμα ως εξής:

(πρασινίζουμε). Ο αριθμός των στοιχείων στον πίνακα περιέχεται στη μεταβλητή $#colors.

θα δώσει τον αριθμό 3 στο τερματικό.

Είναι δυνατοί αρκετά περίπλοκοι συνδυασμοί χρησιμοποιώντας πρότυπα, για παράδειγμα:

% σύνολο αρχείων=(m*)

θα επιστρέψει τον αριθμό των αρχείων στον τρέχοντα κατάλογο που ξεκινά με το γράμμα m.

Οι μεταβλητές περιβάλλοντος καλούνται με τον ίδιο τρόπο όπως οι απλές μεταβλητές. Η διαφορά έγκειται στον τρόπο που ορίζονται:

Η εντολή % setenv name value ορίζει μια μεταβλητή περιβάλλοντος με όνομα όνομα. Σημειώστε την ενοχλητική διαφορά στη σύνταξη: όταν ορίζετε μια μεταβλητή περιβάλλοντος, δεν χρειάζεται να χρησιμοποιείτε το σύμβολο =.

Μια λίστα με όλες τις μεταβλητές περιβάλλοντος μπορεί να ληφθεί χρησιμοποιώντας την ενσωματωμένη εντολή printenv.

Μπορείτε να καταργήσετε τον ορισμό μιας μεταβλητής περιβάλλοντος χρησιμοποιώντας το unsetenv.

Τέλος, για να ορίσετε έναν πίνακα μεταβλητών περιβάλλοντος, ΔΕΝ χρησιμοποιείτε παρενθέσεις, αλλά χρησιμοποιείτε άνω και κάτω τελείες ως οριοθέτες στοιχείων πίνακα:

% setenv MANPATH /usr/man/:/usr/local/man:/usr/man/X11:~/man

Ενσωματωμένες εντολές και μεταβλητές

Λίστα με τις πιο σημαντικές ενσωματωμένες εντολές C-shell με σύντομες επεξηγήσεις:

Το ψευδώνυμο ορίζει ένα ψευδώνυμο

Το bg μεταφέρει την εργασία στη λειτουργία εκτέλεσης παρασκηνίου

εντολή διαδρομής chdir για να μεταβείτε στον κατάλογο διαδρομής.

Το echo εκτυπώνει όλα τα ορίσματά του σε τυπική έξοδο

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

έξοδος τελειώνει το κέλυφος.

fg μεταφράζεται διαδικασία φόντουσε σύγχρονο.

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

Το goto label μεταβαίνει άνευ όρων στη γραμμή του αρχείου δέσμης που επισημαίνεται με ετικέτα. Δεν χρησιμοποιείται διαδραστικά.

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

Το όνομα αρχείου πηγής διαβάζει και εκτελεί εντολές από το όνομα αρχείου.

set, setenv ρύθμιση εσωτερικών και περιβαλλοντικών μεταβλητών.

Το shift var μετατοπίζει τα στοιχεία του πίνακα var προς τα αριστερά. Σε αυτήν την περίπτωση, το μέγεθος του πίνακα μειώνεται κατά ένα και το μηδενικό στοιχείο του πίνακα χάνεται. Η μεταβλητή var πρέπει να είναι πίνακας.

Η εντολή time εκτελεί την εντολή και εμφανίζει το χρόνο που χρειάστηκε για να εκτελεστεί στο τερματικό.

Το unset καταστρέφει τη μεταβλητή φλοιού.

Το unalias καταστρέφει ένα ψευδώνυμο εντολής που ορίστηκε προηγουμένως.

Το @name=expr αποθηκεύει το αποτέλεσμα της αριθμητικής έκφρασης expr στη μεταβλητή name.

Λίστα με τις πιο σημαντικές ενσωματωμένες μεταβλητές C-shell με σύντομες επεξηγήσεις:

argv πίνακας παραμέτρων γραμμής εντολών (χρησιμοποιείται στη λειτουργία εντολών)

Το cdpath είναι ο κατάλογος όπου πηγαίνει το κέλυφος όταν δίνεται η εντολή chdir χωρίς όρισμα.

μέγεθος buffer ιστορικού για την αποθήκευση εντολών.

τον οικιακό κατάλογο του οικιακού χρήστη

θέση αλληλογραφίας σε σύστημα αρχείων γραμματοκιβώτιομεταχειριζόμενος.

διαδρομή για αναζήτηση εξωτερικών εντολών.

Το prompt είναι το κύριο μήνυμα του κελύφους.

prompt1 δευτερεύουσα προτροπή.

πλήρης διαδρομή κελύφους του τρέχοντος εκτελέσιμου αρχείου φλοιού (/bin/csh)

Δηλώσεις ελέγχου και δηλώσεις βρόχου

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

Εκτέλεση υπό όρους

Η σύνταξη της εντολής if υπό όρους στο C-shell είναι:

if (expr) εντολή

Το expr μπορεί να είναι είτε μια αριθμητική έκφραση είτε ένας έλεγχος των χαρακτηριστικών του αρχείου. Παράδειγμα:

αν (-f /etc/hosts) cat /etc/hosts

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

Το R είναι αναγνώσιμο

Το W είναι διαθέσιμο για εγγραφή

Το X είναι διαθέσιμο για εκτέλεση

Έλεγχος ύπαρξης αρχείου

Βεβαιωθείτε ότι είστε ο ιδιοκτήτης αυτό το αρχείο

Το αρχείο Z έχει μηδενικό μέγεθος

Το αρχείο F είναι ένα κανονικό αρχείο

Το αρχείο P είναι ένας σωλήνας με όνομα

Το αρχείο D είναι ένας κατάλογος

ενώ βρόχος

Ο βρόχος εκτελείται όσο η συνθήκη είναι αληθής. Παράδειγμα:

ενώ ($#files > 0)

για κάθε βρόχο

Αυτός είναι ένας εξαιρετικά χρήσιμος τελεστής που σας επιτρέπει να κάνετε βρόχο μέσω των στοιχείων ενός πίνακα λέξεων.

foreach varname (λίστα)

Το σώμα του βρόχου εκτελείται όσες φορές υπάρχουν στοιχεία στον πίνακα λίστας. Σε αυτήν την περίπτωση, η μεταβλητή varname περιέχει την επόμενη τιμή του στοιχείου πίνακα. Παράδειγμα

χρώμα foreach (μπλε κόκκινο πράσινο)

echo Το χρώμα είναι $color

foreach αρχείο (*.for)

echo Μετονομασία αρχείου $

mv $αρχείο `όνομα βάσης $αρχείο .for`.f

Αυτό χρησιμοποιεί την εντολή τυπικού ονόματος βάσης, η οποία «κόβει» το επίθημα που δίνεται από το δεύτερο όρισμα από τη λέξη που δίνεται στο πρώτο όρισμα και εκτυπώνει τη λέξη που προκύπτει στην τυπική έξοδο. Η χρήση των backquotes στη γλώσσα C-shell θα συζητηθεί λίγο αργότερα.

Πολυμεταβλητός υπό όρους τελεστής

Η σύνταξη μιας δήλωσης μεταγωγής υπό όρους στο C-shell είναι:

case pattern1: ... breaksw case (\it pattern2) :

Ο χειριστής επιτρέπει τη μεταφορά του ελέγχου ανάλογα με το εάν το χορδή χορδήςοποιοδήποτε μοτίβο από το σύνολο μοτίβο1, μοτίβο2, ... (σε αυτήν την περίπτωση, ο έλεγχος μεταφέρεται στο μπλοκ που οριοθετείται από την περίπτωση ... breaksw) ή όχι (στην περίπτωση αυτή, ο έλεγχος μεταφέρεται στον προεπιλεγμένο κλάδο:... endsw Γενικά, ο διακόπτης χειριστή είναι πολύ παρόμοιος με μια παρόμοια δήλωση στο C. Τέτοιες δομές χρησιμοποιούνται συχνά σε αρχεία δέσμης για την ανάλυση της απάντησης του χρήστη σε μια δεδομένη ερώτηση ().

2. Εκτέλεση του κελύφους σε λειτουργία εντολών

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

Ταυτοποίηση διερμηνέα

Ο ευκολότερος τρόπος εκκίνησης του φλοιού στη λειτουργία εκτέλεσης ενός συγκεκριμένου αρχείου mycommand είναι να δώσετε σε αυτό το αρχείο το εκτελέσιμο χαρακτηριστικό με την εντολή chmod:

% chmod +x mycommand

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

που θα επιτρέψει στο ΛΣ να κάνει το σωστό. Εάν δεν προσδιορίσετε αυτές τις πληροφορίες, το λειτουργικό σύστημα θα υποθέσει (για ιστορικούς λόγους) ότι το αρχείο είναι γραμμένο στη γλώσσα κελύφους Bourne και πιθανότατα θα λάβετε πολλά μηνύματα συντακτικού σφάλματος.

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

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

# Αυτό το αρχείο απλώς εξάγει τα ορίσματά του

# και τον συνολικό αριθμό ορισμάτων

echo Επιχειρήματα: $argv

echo Αριθμός ορισμάτων: $#argv

Ρητή εκτόξευση

Μπορείτε να κάνετε πιο άμεση αίτηση, αλλά λιγότερο βολικό τρόποεκκινήστε ένα αρχείο δέσμης - καλώντας το κέλυφος με το διακόπτη ονόματος αρχείου -c. Παράδειγμα:

% /bin/csh -c mycommand arg1 arg2 arg3...

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

Εισαγωγικά

Τα εισαγωγικά παίζουν σημαντικό ρόλο στη σύνταξη του κελύφους. Υπάρχουν τρεις τύποι εισαγωγικών: μονά ("), διπλά (") και backticks (`).

Χρησιμοποιούνται μεμονωμένα εισαγωγικά για να επισημανθεί το κείμενο που το κέλυφος πρέπει να ερμηνεύει κυριολεκτικά. Με άλλα λόγια, το κείμενο μέσα σε απλά εισαγωγικά δεν υπόκειται σε επέκταση και ερμηνεία. Παράδειγμα:

echo "Το δολάριο είναι $καλό"

κυριολεκτικά παίρνουμε το δολάριο είναι $καλό, παρόλο που το σύμβολο του δολαρίου είναι ένας μεταχαρακτήρας του κελύφους.

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

set Colors="πράσινο μπλε κόκκινο"; echo $#colors

θα επιστρέψει τον αριθμό 1, που σημαίνει ότι η μεταβλητή των χρωμάτων είναι μια απλή μεταβλητή και όχι ένας πίνακας. Οτιδήποτε μέσα σε διπλά εισαγωγικά υπόκειται σε ερμηνεία από το κέλυφος.

Τα πίσω εισαγωγικά σάς επιτρέπουν να αναπαραστήσετε μια συμβολοσειρά που αποτελείται από το αποτέλεσμα μιας εντολής. Έτσι, η έκφραση στα backticks αντιμετωπίζεται ως εντολή που εκτελεί το κέλυφος και αυτό που εκτυπώνει αυτή η εντολή σε τυπική έξοδο αντικαθίσταται ως συμβολοσειρά στο σημείο όπου εμφανίζονται αυτά τα backtick. Παράδειγμα:

θα βάλει στη μεταβλητή mytty τη συμβολοσειρά που παράγει η εντολή tty (δηλαδή το όνομα και τον αριθμό του τρέχοντος τερματικού).

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

5.8.1 Χειριστές ανΚαι δοκιμή )

Η κατασκευή του τελεστή υπό όρους σε ελαφρώς απλοποιημένη μορφή μοιάζει με αυτό:

αν list1 τότε list2 other list3 fi

Οπου λίστα 1, λίστα 2 και λίστα 3είναι ακολουθίες εντολών που χωρίζονται με κόμμα και τελειώνουν με ερωτηματικό ή χαρακτήρα νέας γραμμής. Επιπλέον, αυτές οι ακολουθίες μπορούν να περικλείονται σε σγουρά σιδεράκια: (λίστα).

Χειριστής ανελέγχει την τιμή που επιστρέφεται από εντολές από λίστα 1. Εάν υπάρχουν πολλές εντολές σε αυτή τη λίστα, τότε ελέγχεται η τιμή που επιστρέφεται από την τελευταία εντολή στη λίστα. Εάν αυτή η τιμή είναι 0, τότε εντολές από λίστα 2; αν αυτή η τιμή δεν είναι μηδέν, οι εντολές από λίστα 3. Η τιμή που επιστρέφεται από έναν τέτοιο σύνθετο τελεστή αν, είναι ίδια με την τιμή που παράγεται από την τελευταία εντολή της ακολουθίας που εκτελείται.

Πλήρης μορφή εντολής ανέχει τη μορφή:

αν λίστα τότε λίστα [ elif list then list ] ... [ else list ] fi

(εδώ οι αγκύλες σημαίνουν μόνο ότι αυτό που περιέχεται σε αυτές δεν υπάρχει απαραίτητα στον τελεστή).

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

δοκιμαστική έκφραση,

Μπορείτε να περικλείσετε την έκφραση σε αγκύλες:

[έκφραση].

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

Συμπερασματικά, δίνουμε ένα παράδειγμα χρήσης του τελεστή αν:

αν [ -e textmode2.htm ] ; τότε

ls λειτουργία κειμένου*

αλλού

pwd

Σχετικά με τον χειριστή δοκιμή(ή […]) πρέπει να κάνουμε μια ειδική συζήτηση.

5.8.2 Χειριστής δοκιμήκαι υπό όρους

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

    Ένα αρχείο

Σωστό εάν υπάρχει ένα αρχείο με όνομα αρχείο.

    Β αρχείο

Αλήθεια αν αρχείουπάρχει και είναι ένα ειδικό αρχείο συσκευής μπλοκ.

    αρχείο C

Αλήθεια αν αρχείουπάρχει και είναι ένα αρχείο συσκευής ειδικών χαρακτήρων.

    αρχείο D

Αλήθεια αν αρχείουπάρχει και είναι ένας κατάλογος.

    αρχείο Ε

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει.

    αρχείο F

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και είναι κανονικό αρχείο.

    αρχείο G

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και έχει οριστεί το bit αλλαγής ομάδας του.

    Αρχείο H ή αρχείο -L

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και αποτελεί συμβολικό σύνδεσμο.

    αρχείο Κ

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και έχει οριστεί το "κολλώδες" bit του.

    αρχείο P

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και είναι με όνομα σωλήνας(FIFO).

    αρχείο R

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και έχει οριστεί δικαιώματα ανάγνωσης

    αρχείο S

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

    Tfd

Σωστό εάν ο περιγραφέας αρχείου fdείναι ανοιχτό και δείχνει προς το τερματικό.

    αρχείο U

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και έχει οριστεί το bit αλλαγής χρήστη.

    αρχείο W

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και έχει σύνολο αδειών εγγραφής.

    αρχείο X

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και είναι εκτελέσιμο.

    O αρχείο

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και ανήκει στον χρήστη στον οποίο υποδεικνύεται το πραγματικό αναγνωριστικό χρήστη.

    αρχείο G

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και ανήκει στην ομάδα που προσδιορίζεται από το ενεργό αναγνωριστικό ομάδας.

    αρχείο S

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και είναι πρίζα.

    N αρχείο

Σωστό αν το αρχείο έχει το όνομα αρχείουπάρχει και έχει αλλάξει από την τελευταία ανάγνωση.

    file1 -nt file2

Σωστό αν το αρχείο αρχείο 1έχει μεταγενέστερο χρόνο τροποποίησης από αρχείο 2.

    file1 -ot file2

Σωστό αν το αρχείο αρχείο 1μεγαλύτερο από αρχείο 2.

    file1 -ef file2

Σωστό αν τα αρχεία αρχείο 1Και αρχείο 2έχουν τους ίδιους αριθμούς συσκευής και inode(ινώδης).

    O optname

Σωστό εάν είναι ενεργοποιημένη η επιλογή κελύφους optname. Για μια εξήγηση, ανατρέξτε στη σελίδα του bash man.

    Ζ χορδή

Σωστό αν το μήκος της συμβολοσειράς είναι μηδέν.

    Ν συμβολοσειρά

Σωστό αν το μήκος της συμβολοσειράς δεν είναι μηδέν.

    string1 == string2

Σωστό αν οι χορδές ταιριάζουν. Αντί για == μπορεί να χρησιμοποιηθεί = .

    string1 !== string2

Σωστό αν οι χορδές δεν ταιριάζουν.

    συμβολοσειρά 1< string2

Σωστό αν η γραμμή συμβολοσειρά 1λεξικογραφικά προηγείται της χορδής συμβολοσειρά 2(για την τρέχουσα τοπική ρύθμιση).

    string1 > string2

Σωστό αν η γραμμή συμβολοσειρά 1λεξικογραφικά έρχεται μετά τη γραμμή συμβολοσειρά 2(για την τρέχουσα τοπική ρύθμιση).

    arg1 OP arg2

Εδώ ΕΠ- ε τότε μια από τις πράξεις αριθμητικής σύγκρισης: -εξ(ίσον), -νε(όχι ίσο) - λ(λιγότερο από) -le(λιγότερο ή ίσο με) -gt(περισσότερο), -ge(μεγαλύτερο ή ίσο με). Ως ορίσματα μπορούν να χρησιμοποιηθούν θετικοί ή αρνητικοί ακέραιοι.

Από αυτές τις στοιχειώδεις εκφράσεις υπό όρους μπορείτε να δημιουργήσετε όσο περίπλοκες θέλετε χρησιμοποιώντας τις συνήθεις λογικές πράξεις των ΑΡΝΗΣΗ, ΚΑΙ και Ή:

    !(έκφραση)

Τελεστή άρνησης Boole.

    έκφραση1 -α έκφραση2

Boolean τελεστής ΚΑΙ(ΚΑΙ). Σωστό αν και οι δύο εκφράσεις είναι αληθείς.

    έκφραση1 -ο έκφραση2

Boolean τελεστής Ή(Ή). Σωστό αν οποιαδήποτε από τις δύο εκφράσεις είναι αληθής.

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

5.8.3 Χειριστής περίπτωση

Μορφή χειριστή περίπτωσηείναι:

περίπτωση λέξης στη λίστα [ [(] pattern [ | pattern ] ...) ;; ]...esac

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

Το ακόλουθο παράδειγμα χρήσης της δήλωσης case λαμβάνεται από τη δέσμη ενεργειών συστήματος /etc/rc.d/rc.sysinit.

περίπτωση "$UTC" σε

ναι|αλήθεια)

CLOCKFLAGS="$CLOCKFLAGS -u";

CLOCKDEF="$CLOCKDEF (utc)";

όχι|ψευδές)

CLOCKFLAGS="$CLOCKFLAGS --localtime";

CLOCKDEF="$CLOCKDEF (τοπική ώρα)";

esac

Εάν η μεταβλητή αξιολογηθεί σε ναι ή true, τότε θα εκτελεστεί το πρώτο ζεύγος εντολών και αν η τιμή του είναι no ή false, θα εκτελεστεί το δεύτερο ζεύγος.

5.8.4 Χειριστής επιλέγω

Χειριστής επιλέγωσας επιτρέπει να οργανώσετε τη διαδραστική αλληλεπίδραση με τον χρήστη. Έχει την εξής μορφή:

επιλέξτε όνομα [σε λέξη; ] do list ; γινώμενος

Πρώτα από το πρότυπο λέξηδημιουργείται μια λίστα λέξεων που ταιριάζουν με το μοτίβο. Αυτό το σύνολο λέξεων εξάγεται στην τυπική ροή σφαλμάτων, με κάθε λέξη να συνοδεύεται από έναν αριθμό σειράς. Αν το μοτίβο λέξηπαραλείπονται, οι παράμετροι θέσης προέρχονται με τον ίδιο τρόπο. Στη συνέχεια εκδίδεται η τυπική προτροπή PS3 και το κέλυφος περιμένει να εισαχθεί μια γραμμή στην τυπική είσοδο. Εάν η συμβολοσειρά που εισάγατε περιέχει έναν αριθμό που αντιστοιχεί σε μία από τις εμφανιζόμενες λέξεις, τότε η μεταβλητή όνομααποδίδεται μια τιμή ίση με αυτή τη λέξη. Εάν εισαχθεί μια κενή γραμμή, εμφανίζονται ξανά οι αριθμοί και οι αντίστοιχες λέξεις. Εάν εισαχθεί οποιαδήποτε άλλη τιμή, η μεταβλητή όνομααποδίδεται τιμή μηδέν. Η συμβολοσειρά που εισάγεται από τον χρήστη αποθηκεύεται σε μια μεταβλητή ΑΠΑΝΤΗΣΗ. Λίστα εντολών λίσταεκτελείται με την επιλεγμένη τιμή μεταβλητής όνομα.

Εδώ είναι ένα μικρό σενάριο:

#!/bin/sh

echo "Ποιο λειτουργικό σύστημα προτιμάς;"

επιλέξτε var στο "Linux" "Gnu Hurd" "Free BSD" "Other"; κάνω

διακοπή

γινώμενος

echo "Θα επιλέγατε $var"

Ποιο λειτουργικό σύστημα προτιμάτε;
1) Linux
2) Gnu Hurd
3) Δωρεάν BSD
4) Άλλο
#?

Πατήστε οποιονδήποτε από τους 4 προτεινόμενους αριθμούς (1,2,3,4). Εάν πληκτρολογήσετε 1, για παράδειγμα, θα δείτε το μήνυμα:

"Θα επιλέγατε το Linux"

5.8.5 Χειριστής για

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

για το όνομα με τις λέξεις θα γίνει λίστα.

Κανόνες για την κατασκευή λιστών εντολών ( λίστα) είναι ίδια όπως στον τελεστή αν.

Παράδειγμα. Το ακόλουθο σενάριο δημιουργεί τα αρχεία foo_1, foo_2 και foo_3:

για ένα σε 1 2 3 ; κάνω

αγγίξτε foo_$a

γινώμενος

Σε γενικές γραμμές για δήλωσηέχει τη μορφή:

για όνομα [σε λέξη? ] do list ; γινώμενος

Πρώτα, αποκαλύπτεται η λέξη λέξησύμφωνα με τους κανόνες αποκάλυψης έκφρασης που δίνονται παραπάνω. Στη συνέχεια η μεταβλητή όνομαΟι τιμές που προκύπτουν εκχωρούνται μία προς μία και εκτελείται μια λίστα εντολών κάθε φορά ist. αν " στο word" λείπει, τότε η λίστα των εντολών λίσταεκτελείται μία φορά για κάθε παράμετρο θέσης που καθορίζεται.

Το Linux έχει ένα πρόγραμμα επ, το οποίο παίρνει δύο αριθμούς ως ορίσματα και παράγει μια ακολουθία όλων των αριθμών που βρίσκονται μεταξύ των δεδομένων. Με αυτήν την εντολή μπορείτε να αναγκάσετε για V βίαιο χτύπημαλειτουργούν ακριβώς με τον ίδιο τρόπο που λειτουργεί ένας παρόμοιος χειριστής σε συμβατικές γλώσσες προγραμματισμού. Για να το κάνετε αυτό, απλώς γράψτε τον κύκλο γιαως εξής:

για ένα σε $(ακολουθία 1 10) ; κάνω

cat file_$a

γινώμενος

Αυτή η εντολή εμφανίζει τα περιεχόμενα 10 αρχείων: " file_1", ..., "file_10".

5.8.6 Χειριστές ενώΚαι μέχρι

Χειριστής ενώλειτουργεί όπως αν, εκτελούν μόνο τελεστές από τη λίστα λίστα 2Ο βρόχος συνεχίζεται όσο η συνθήκη είναι αληθής και ματαιώνεται εάν η συνθήκη δεν είναι αληθής. Το σχέδιο μοιάζει με αυτό:

ενώ το list1 do list2 έχει ολοκληρωθεί.

ενώ [-d mydirectory] ; κάνω

ls -l mydirectory >> αρχείο καταγραφής

echo -- SEPARATOR -- >> αρχείο καταγραφής

ύπνος 60

γινώμενος

Ένα τέτοιο πρόγραμμα θα καταγράφει τα περιεχόμενα του καταλόγου "mydirectory" κάθε λεπτό όσο υπάρχει ο κατάλογος.

Χειριστής μέχριπαρόμοιο με τον χειριστή ενώ:

μέχρι να ολοκληρωθεί η λίστα1 έως τη λίστα2.

Η διαφορά είναι ότι το αποτέλεσμα επιστρέφεται κατά την εκτέλεση μιας λίστας εντολών λίστα 1, λαμβάνονται με άρνηση: λίστα 2εκτελείται εάν η τελευταία εντολή στη λίστα λίστα 1επιστρέφει μια μη μηδενική κατάσταση εξόδου.

5.8.7 Λειτουργίες

Σύνταξη

Κέλυφος βίαιο χτύπημαεπιτρέπει στον χρήστη να δημιουργήσει τις δικές του λειτουργίες. Οι συναρτήσεις συμπεριφέρονται και χρησιμοποιούνται ακριβώς όπως οι κανονικές εντολές φλοιού, που σημαίνει ότι μπορούμε να δημιουργήσουμε νέες εντολές μόνοι μας. Οι συναρτήσεις είναι κατασκευασμένες ως εξής:

όνομα συνάρτησης() (λίστα)

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

Οι συναρτήσεις εκτελούνται στο πλαίσιο του τρέχοντος φλοιού: δεν ξεκινά μια νέα διαδικασία για την ερμηνεία της συνάρτησης (σε αντίθεση με την εκτέλεση σεναρίων φλοιού).

Επιχειρήματα

Όταν μια συνάρτηση καλείται για εκτέλεση, τα ορίσματα της συνάρτησης γίνονται παραμέτρους θέσης(παράμετροι θέσης)για τη διάρκεια της λειτουργίας. Αναφέρονται ως $n, Πού n— ο αριθμός του ορίσματος στο οποίο θέλουμε να έχουμε πρόσβαση. Η αρίθμηση επιχειρημάτων ξεκινά από το 1, άρα $1 - αυτό είναι το πρώτο επιχείρημα. Μπορούμε επίσης να λάβουμε όλα τα επιχειρήματα ταυτόχρονα με $* και τον αριθμό των ορισμάτων που χρησιμοποιούνται $# . Παράμετρος θέσης 0 δεν αλλάζει.

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

Τοπικές μεταβλητές (τοπικές)

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

Ακολουθεί ένα παράδειγμα καθορισμού μιας συνάρτησης που υλοποιεί την εντολή που αναφέρεται παραπάνω επ:

seq()

τοπικό I=$1;

ενώ [ $2 != $I ]; κάνω

echo -n "$I ";

I=$(($I + 1))

γινώμενος;

ηχώ $2

Σημειώστε την επιλογή -nχειριστής ηχώ, ακυρώνει τη νέα γραμμή. Αν και αυτό δεν είναι απαραίτητο για τους σκοπούς που έχουμε κατά νου εδώ, μπορεί να είναι χρήσιμο για τη χρήση της συνάρτησης για άλλους σκοπούς.

Συνάρτηση παραγοντικού υπολογισμού γεγονός

Άλλο παράδειγμα:

γεγονός()

εάν [ $1 = 0 ]; τότε

ηχώ 1;

αλλού

echo $(($1 * $(γεγονός $(($1 - 1)))))

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

V. Kostromin (kos at rus-linux dot net) - 5,8. Το Shell ως γλώσσα προγραμματισμού

Τα κελύφη εντολών εμφανίστηκαν στην αρχή της ανάπτυξης του Unix, ήταν απαραίτητα γιατί ήταν ο μόνος τρόπος αλληλεπίδρασης με το σύστημα. Σε αυτό το διάστημα πέρασαν πολλά μεγάλης απόστασηςανάπτυξη και έλαβε πολλές νέες λειτουργίες. Δεν είναι εύκολο να εκτιμήσεις την εξέλιξη των κελύφους Linux. Μπορείτε να γράψετε για αυτό για πολύ καιρό και ένα άρθρο σίγουρα δεν είναι αρκετό. Θα προσπαθήσουμε να καλύψουμε μόνο τα βασικά χωρίς να εμβαθύνουμε. Ας δούμε πρώτα τι είναι το κέλυφος εντολών Linux και τι κελύφη υπάρχουν.

Τι είναι ένα κέλυφος Linux/Unix

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

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

Thompson Shell

Για να γίνει πιστευτή η ιστορία και πολλές πηγές του Διαδικτύου, το πρώτο κέλυφος ήταν το Thompson Shell, γραμμένο από τον Ken Thomson στα Bell Labs. Υπήρχαν 6 εκδόσεις συνολικά και διανεμήθηκε από το 1971 έως το 1975. Υποστηρίχθηκαν δυνατότητες όπως η ανακατεύθυνση I/O και οι απλές κατασκευές ελέγχου - if, goto. Αυτές οι λειτουργίες υποστηρίζουν όλα τα σύγχρονα κελύφη εντολών Linux.

Κέλυφος PWB

Το κέλυφος PWB είναι μια τροποποίηση του κελύφους Thomson που αναπτύχθηκε από τον John Masheu. Γράφτηκε για να αυξήσει την ευκολία του προγραμματισμού Shell. Έχουν εμφανιστεί ενδιαφέρουσες δομές όπως οι βρόχοι if-then-else-endif, switch και while.

Bourne Shell

Το Unix ξεκίνησε την άνοδό του με το κέλυφος Bourne. Γράφτηκε από τον Stefan Born στα Bell Labs και χρησιμοποιήθηκε ως το προεπιλεγμένο κέλυφος στην έκδοση 7 του Unix από το 1979. Ένας μεγάλος αριθμός δυνατοτήτων που είναι διαθέσιμες στα σύγχρονα κελύφη έχουν ήδη εφαρμοστεί εδώ - συμπλήρωση ονόματος αρχείου, ολοκλήρωση εντολών, τυπικές μεταβλητές περιβάλλοντος και ενσωματωμένες δομές ελέγχου. Το Bourne Shell ονομαζόταν sh και βρισκόταν στο σύστημα αρχείων Unix στο /bin/sh.

Σε πολλά συστήματα, ένα πρόγραμμα φλοιού Bourne (sh) είναι ένας συμβολικός ή σκληρός σύνδεσμος σε μία από τις εναλλακτικές του:

  • Κοχύλι Almquist (στάχτη)
  • Κέλυφος Bourne-Again (bash)
  • Κέλυφος Korn (ksh)
  • κέλυφος Z (zsh)

Παράδειγμα σεναρίου για το Bourne Shell:

!/bin/sh
ηχώ" Γεια σου Κόσμο 1!"
echo "Hello World 2!"

Κοχύλι Almquist (στάχτη)

Κοχύλι Almquist, γνωστό και ως A Shell. Είναι ένα ελαφρύ κέλυφος Unix που γράφτηκε αρχικά από τον Kenneth Almquist. Αναπτύχθηκε στα τέλη της δεκαετίας του 1980. Αυτή είναι μια τροποποίηση του κελύφους Bourne και αντικατέστησε το πρωτότυπο στο BSD Unix που κυκλοφόρησε το 1990. Μπορεί πλέον να χρησιμοποιηθεί σε διανομές όπως το Debian και το Ubuntu ως έκδοση στάχτης που ονομάζεται παύλα (Debian Almquist shell) Αυτό το κέλυφος είναι επίσης δημοφιλές σε ενσωματωμένες διανομές Unix.

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

Bourne-Again Shell (Bash)

Γράφτηκε από τον Brian Fox ως μέρος του έργου GNU ως δωρεάν και ανοιχτού κώδικα αντικατάσταση του κελύφους Bourne. Το Bash είναι το πιο δημοφιλές και ευρέως χρησιμοποιούμενο από όλα τα κοχύλια. Ολοι Διανομές Linuxέρχονται από προεπιλογή με αυτό το κέλυφος. Επεκτείνει το σύνολο δυνατοτήτων Bourne Shell. Στα περισσότερα συστήματα Unix/Linux, αυτό το κέλυφος μπορεί να βρεθεί στο σύστημα αρχείων στο /bin/bash. Κυκλοφόρησε το 1989.

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

Υποστηρίζει αυτόματη συμπλήρωση, ανακατεύθυνση I/O, ολοκλήρωση εντολών, μεταβλητές και δομές ελέγχου για τη λήψη αποφάσεων (if-then-elese if) και βρόχους.

Τα σενάρια Bash ξεκινούν με αυτή τη γραμμή:

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

Παράδειγμα κώδικα στο Bash:

!/bin/sh
εάν [ $days -gt 365 ]
τότε
echo Αυτό είναι πάνω από ένα χρόνο.
fi

Κέλυφος Korn (ksh)

Γράφτηκε από τον David Kron και βασίζεται στον πηγαίο κώδικα του κελύφους Bourne. Το KornShell (ksh) είναι ένα κέλυφος που αναπτύχθηκε στα εργαστήρια Bell το 1980. Είναι συμβατό προς τα πίσω με το κέλυφος Bourne και περιλαμβάνει επίσης πολλά από τα χαρακτηριστικά του κελύφους C.

Φάω επόμενες εκδόσειςκαι τροποποιήσεις:

  • Dtksh
  • MKS Korn κέλυφος

Παράδειγμα σεναρίου:

!/bin/ksh
Εκτύπωση χρήσης χώρου στο δίσκο
du-k
έξοδος 0

κέλυφος Z (zsh)

Ο Paul Falstad έγραψε την πρώτη έκδοση με την εντολή zsh shell το 1990. Είναι ένα κέλυφος εντολών Linux που μπορεί να χρησιμοποιηθεί ως διαδραστικό κέλυφος σύνδεσης, ένας πολύ ισχυρός διερμηνέας εντολών. Το Zsh είναι στην πραγματικότητα ένα βελτιωμένο κέλυφος Bourne με πολλές βελτιώσεις που περιλαμβάνει ορισμένες δυνατότητες από το Bash, το KSH και το Tcsh.

Το όνομα Zsh προέρχεται από τον καθηγητή του Yale Zhong Shao, καθώς ο Paul ήταν φοιτητής στο Πανεπιστήμιο του Πρίνστον.

Υποστηρίζονται τα ακόλουθα ενδιαφέροντα χαρακτηριστικά:

  • Ολοκλήρωση γραμμής
  • Κοινό ιστορικό εντολών για όλες τις περιόδους λειτουργίας φλοιού
  • Βελτιωμένη εργασία με μεταβλητές και πίνακες
  • Επεξεργασία πολλών γραμμών σε ένα buffer
  • Διόρθωση ορθογραφίας και πολλά άλλα.

C κέλυφος

Το κέλυφος C είναι επίσης γνωστό ως Csh. Αναπτύχθηκε από τον Bill Joy όταν ήταν φοιτητής στο Πανεπιστήμιο της Καλιφόρνια. Αυτό το κέλυφος είναι πολύ κοινό σε συστήματα BSD Linux. Υπάρχουν πολλά ενδιαφέροντα χαρακτηριστικά εδώ, συμπεριλαμβανομένων των δομών ελέγχου και των γραμματικών εκφράσεων. Αυτό το φλοιό εισήγαγε επίσης για πρώτη φορά μεγάλο αριθμό ενδιαφέροντων χαρακτηριστικών, όπως μηχανισμοί ιστορικού και επεξεργασίας, ψευδώνυμα, CDPATH, διαχείριση εργασιών και κατακερματισμός, ανακατεύθυνση εξόδου, προσάρτηση, αντικατάσταση μεταβλητών, εκτέλεση παρασκηνίου κ.λπ.

Όπως και άλλοι τύποι κελύφους Linux, υποστηρίζει αρχεία σεναρίων, ανακατεύθυνση και δομές ελέγχου. Το Csh χρησιμοποιείται πλέον ως tcsh σε πολλά συστήματα, όπως το MacOS X και Κόκκινο καπέλο Linux. Στο Debian μπορείτε να χρησιμοποιήσετε και CSH και Tcsh.

Δείγμα κώδικα στο C Shell:

!/bin/csh
εάν ($days > 365) τότε
echo Αυτό είναι πάνω από ένα χρόνο.
endif

Ψάρι

Το Fish or Friendly Interactive Shell είναι ένα κέλυφος εντολών Linux νέογενιές. Έχει σχεδιαστεί για να διευκολύνει τον χρήστη να εκτελεί εντολές, υπάρχει επισήμανση σύνταξης, επισήμανση σωστών διευθύνσεων αρχείων, γρήγορη αναζήτηση ιστορικού, διαμορφωτής ιστού, καθώς και ειδική σύνταξη σεναρίου.

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

Ένα παράδειγμα δημιουργίας συνάρτησης σε ψάρια:

!/usr/bin/fish
funced su
συνάρτηση su
/bin/su --shell=/usr/bin/fish $argv
τέλος
funcsave su

Περισσότερο λεπτομερής σύγκρισηκελύφη εντολών στο Linux μπορείτε να δείτε τον σύνδεσμο.

Αυτό είναι όλο για σήμερα. Ελπίζω να το βρήκατε ενδιαφέρον.

Πολλοί πιστεύουν ότι είναι πολύ δύσκολο να φτιάξεις ένα πρόγραμμα που θα χρησιμοποιηθεί από εκατομμύρια. Ωστόσο, πίσω από οποιοδήποτε, ακόμη και το πιο περίπλοκο, προϊόν υπάρχει πάντα μια απλή ιδέα. Ένα από αυτά είναι το κέλυφος εντολών ή κέλυφος. Σε αυτό το άρθρο θα σας δείξουμε πώς να γράψετε μια απλοποιημένη γραμμή εντολών Κέλυφος Unixστο Γ.

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

Κύκλος ζωής του κελύφους

Το κέλυφος εκτελεί τρεις κύριες λειτουργίες κατά τη διάρκεια της ζωής του:

  1. Αρχικοποίηση: Σε αυτό το στάδιο, διαβάζει και εκτελεί τα αρχεία διαμόρφωσής του. Της αλλάζουν συμπεριφορά.
  2. Ερμηνεία: Στη συνέχεια, το φλοιό διαβάζει τις εντολές από το stdin και τις εκτελεί.
  3. Τερματισμός: Μετά την εκτέλεση βασικών εντολών, εκτελεί εντολές τερματισμού λειτουργίας, ελευθερώνει τη μνήμη και εξέρχεται.

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

Int main(int argc, char **argv) ( // Φόρτωση αρχείων διαμόρφωσης εάν είναι διαθέσιμα. // Εκκίνηση βρόχου εντολών. lsh_loop(); // Τερματισμός / εκκαθάριση μνήμης. επιστροφή EXIT_SUCCESS; )

Στο παραπάνω παράδειγμα, μπορείτε να δείτε τη συνάρτηση lsh_loop(), η οποία θα κάνει βρόχο μέσω εντολών. Θα δούμε την υλοποίηση παρακάτω.

Βασικός βρόχος κελύφους

Πρώτα απ 'όλα, πρέπει να σκεφτούμε πώς πρέπει να τρέχει το πρόγραμμα. Και εδώ είναι σημαντικό να καταλάβουμε τι κάνει το κέλυφος κατά τη διάρκεια του βρόχου. Ένας απλός τρόπος επεξεργασίας εντολών αποτελείται από τρία βήματα:

  1. Ανάγνωση: Διαβάστε μια εντολή από τυπικές ροές.
  2. Ανάλυση: αναγνώριση του προγράμματος και των ορισμάτων στη συμβολοσειρά εισόδου.
  3. Εκτέλεση: Εκτελέστε την αναγνωρισμένη εντολή.

Αυτή η ιδέα υλοποιείται στη συνάρτηση lsh_loop():

Void lsh_loop(void) ( char *line; char **args; int status; do ( printf("> "); line = lsh_read_line(); args = lsh_split_line(line); status = lsh_execute(args); free(line δωρεάν (args), ενώ (κατάσταση);

Ας περάσουμε από τον κώδικα. Οι πρώτες γραμμές είναι απλώς ανακοινώσεις. Ένας βρόχος postcondition είναι πιο βολικός για τον έλεγχο της κατάστασης μιας μεταβλητής επειδή εκτελείται πριν από τον έλεγχο της τιμής της. Μέσα στον βρόχο, εμφανίζεται η προτροπή εισόδου, οι συναρτήσεις καλούνται να διαβάσουν τη συμβολοσειρά εισόδου και να χωρίσουν τη συμβολοσειρά σε ορίσματα και στη συνέχεια εκτελούνται τα ορίσματα. Στη συνέχεια, η μνήμη που έχει εκχωρηθεί για τη συμβολοσειρά και τα ορίσματα ελευθερώνεται. Αξίζει να σημειωθεί ότι ο κώδικας χρησιμοποιεί μεταβλητή κατάστασης, επιστρέφεται από την lsh_execute() και υποδεικνύει πότε πρέπει να βγείτε από τη συνάρτηση.

Διαβάζοντας μια γραμμή

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

#define LSH_RL_BUFSIZE 1024 χαρακτήρες *lsh_read_line(void) (int bufsize = LSH_RL_BUFSIZE; int position = 0; char *buffer = malloc(sizeof(char) * bufsize); int c; if (!buffer) (",fprintl(lshder) : σφάλμα εκχώρησης μνήμης\n"); exit(EXIT_FAILURE); ) while (1) ( // Διαβάστε τον χαρακτήρα c = getchar(); // Όταν συναντήσετε EOF, αντικαταστήστε τον με έναν τερματιστή null και επιστρέψτε το buffer εάν (c == EOF ||. c == "\n") (buffer = "\n"; επιστροφής; = bufsize) ( bufsize += LSH_RL_BUFSIZE; buffer = realloc(buffer, bufsize); if (!buffer) ( fprintf(stderr, "lsh: σφάλμα εκχώρησης μνήμης\n"); έξοδος(EXIT_FAILURE); ) ) )

Υπάρχουν πολλές ανακοινώσεις στο πρώτο μέρος. Αξίζει να σημειωθεί ότι ο κώδικας χρησιμοποιεί παλιό στυλΓ, δηλαδή τη δήλωση των μεταβλητών πριν από το κύριο μέρος του κώδικα. Το κύριο μέρος της συνάρτησης βρίσκεται μέσα σε έναν φαινομενικά ατελείωτο βρόχο while(1). Στον βρόχο, ο χαρακτήρας διαβάζεται και αποθηκεύεται ως int και όχι ως χαρακτήρας (το EOF είναι ακέραιος αριθμός, όχι χαρακτήρας, επομένως χρησιμοποιήστε το int για έλεγχο). Αν είναι νέα γραμμή ή ΕΟΦ, τερματίζουμε την τρέχουσα γραμμή και την επιστρέφουμε. Διαφορετικά, ο χαρακτήρας προστίθεται στην υπάρχουσα συμβολοσειρά.

Στη συνέχεια ελέγχουμε για να δούμε αν ο επόμενος χαρακτήρας βρίσκεται εκτός του buffer. Εάν συμβαίνει αυτό, τότε αναδιανέμουμε το buffer (ενώ το ελέγχουμε για σφάλματα κατανομής) και συνεχίζουμε την εκτέλεση.

Όσοι είναι εξοικειωμένοι με νεότερες εκδόσεις της βασικής βιβλιοθήκης C μπορεί να παρατηρήσουν ότι το stdio.h έχει μια συνάρτηση getline() που κάνει το μεγαλύτερο μέρος της εργασίας που υλοποιείται στον παραπάνω κώδικα. Αυτή η δυνατότητα ήταν μια επέκταση GNU στη βιβλιοθήκη C μέχρι το 2008, και στη συνέχεια προστέθηκε στις προδιαγραφές, επομένως τα περισσότερα σύγχρονα συστήματα Unix διαθέτουν ήδη. Με το getline η συνάρτηση γίνεται ασήμαντη:

Char *lsh_read_line(void) ( char *line = NULL; ssize_t bufsize = 0; // το getline θα εκχωρήσει τη γραμμή λήψης μνήμης (&line, &bufsize, stdin); γραμμή επιστροφής; )

Ανάλυση χορδών

Τώρα πρέπει να αναλύσουμε τη συμβολοσειρά εισόδου σε μια λίστα ορισμάτων. Θα κάνουμε μια μικρή απλούστευση και θα αποτρέψουμε τον χρήστη από τη χρήση εισαγωγικών και ανάστροφων κάθετου στα ορίσματα της γραμμής εντολών. Αντίθετα, θα χρησιμοποιήσουμε απλώς κενά για να διαχωρίσουμε τα ορίσματα. Έτσι η εντολή echo "εδώ είναι το μήνυμα" θα προκαλέσει εντολή echoόχι με ένα επιχείρημα «εδώ είναι το μήνυμα», αλλά με δύο: «εδώ» και «μήνυμα».

Τώρα το μόνο που χρειάζεται να κάνουμε είναι να χωρίσουμε τη χορδή σε κομμάτια χρησιμοποιώντας κενά ως οριοθέτες. Αυτό σημαίνει ότι μπορούμε να χρησιμοποιήσουμε την κλασική συνάρτηση βιβλιοθήκης strtok.

#define LSH_TOK_BUFSIZE 64 #define LSH_TOK_DELIM "\t\r\n\a" char **lsh_split_line(char *line) (int bufsize = LSH_TOK_BUFSIZE, position = 0; char **tokens = malloc((bufsize) * size char *token, if (! tokens = θέση ++; \n"); έξοδος(EXIT_FAILURE); ) ) διακριτικό = strtok(NULL, LSH_TOK_DELIM); ) διακριτικά = NULL; κουπόνια επιστροφής; )

Η υλοποίηση αυτής της συνάρτησης είναι ύποπτα παρόμοια με την lsh_read_line() , και για καλό λόγο! Η ίδια στρατηγική χρησιμοποιείται εδώ, αλλά αντί για έναν πίνακα χαρακτήρων με μηδενικό τερματισμό, χρησιμοποιούμε έναν πίνακα δεικτών με μηδενικό τερματισμό.

Ξεκινάμε την κατάτμηση καλώντας το strtok. Επιστρέφει έναν δείκτη στο πρώτο κομμάτι της συμβολοσειράς (κουπόνι). Γενικά, η strtok() επιστρέφει δείκτες σε θέσεις στη συμβολοσειρά και τοποθετεί μηδενικούς τερματιστές στο τέλος κάθε διακριτικού. Αποθηκεύουμε αυτούς τους δείκτες σε ξεχωριστό πίνακα.

Εάν είναι απαραίτητο, θα ανακατανείμουμε τον πίνακα δεικτών. Επαναλαμβάνουμε τη διαδικασία έως ότου το strtok σταματήσει να επιστρέφει διακριτικά και τερματίζουμε τη συστοιχία διακριτικών με έναν τερματιστή null.

Τώρα έχουμε μια σειρά από διακριτικά έτοιμη για εκτέλεση.

Πώς ξεκινούν τις διαδικασίες τα κελύφη εντολών

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

Στο Unix υπάρχουν μόνο δύο τρόποι εκτέλεσης διεργασιών. Το πρώτο (που δεν θα το μετρήσουμε) είναι το Init . Βλέπετε, όταν ένα σύστημα Unix εκκινεί, ο πυρήνας του φορτώνεται. Μετά την εκκίνηση και την προετοιμασία, ο πυρήνας ξεκινά μόνο μία διεργασία, που ονομάζεται Init. Αυτή η διαδικασία εκτελείται ενώ ο υπολογιστής εκτελείται και διαχειρίζεται τη φόρτωση άλλων διεργασιών που είναι απαραίτητες για τη λειτουργία του.

Δεδομένου ότι όλες οι άλλες διεργασίες δεν είναι Init, υπάρχει μόνο ένας πρακτικός τρόπος για να ξεκινήσετε διεργασίες: η κλήση συστήματος fork(). Όταν καλείται αυτή η συνάρτηση, το λειτουργικό σύστημα δημιουργεί ένα αντίγραφο της διαδικασίας και τις εκτελεί παράλληλα. Η αρχική διαδικασία ονομάζεται «γονέας» και η νέα διαδικασία ονομάζεται «παιδί». Η Fork() επιστρέφει 0 στη θυγατρική διεργασία και επιστρέφει το αναγνωριστικό διεργασίας (PID) του παιδιού της στον γονέα. Έτσι, οποιαδήποτε νέα διαδικασία μπορεί να δημιουργηθεί μόνο από ένα αντίγραφο μιας υπάρχουσας.

Αυτό μπορεί να φαίνεται σαν πρόβλημα. Συνήθως, όταν θέλετε να ξεκινήσετε μια νέα διαδικασία, δεν θέλετε ένα αντίγραφο ενός προγράμματος που εκτελείται ήδη - θέλετε να ξεκινήσετε ένα διαφορετικό πρόγραμμα. Για να γίνει αυτό, πρέπει να χρησιμοποιήσετε την κλήση συστήματος exec(). Αντικαθιστά το τρέχον πρόγραμμα με ένα εντελώς νέο. Αυτό σημαίνει ότι όταν καλείται το exec, το λειτουργικό σύστημα σταματά τη διαδικασία, φορτώνει ένα νέο πρόγραμμα και το ξεκινά από την ίδια θέση. Η κλήση exec() δεν επιστρέφει τη διαδικασία εκτός και αν υπάρχει σφάλμα.

Αυτές οι δύο κλήσεις συστήματος καθιστούν δυνατή την εκτέλεση των περισσότερων προγραμμάτων στο Unix. Πρώτα, η υπάρχουσα διεργασία διαχωρίζεται σε έναν γονέα και ένα παιδί και, στη συνέχεια, η θυγατρική διαδικασία χρησιμοποιεί την exec() για να αντικατασταθεί νέο πρόγραμμα. Η γονική διαδικασία μπορεί να συνεχίσει να κάνει άλλα πράγματα, καθώς και να παρακολουθεί τα παιδιά της, χρησιμοποιώντας την κλήση συστήματος wait().

Ναι, υπάρχουν πολλές πληροφορίες. Ας δούμε τον κώδικα εκκίνησης του προγράμματος:

Int lsh_launch(char **args) ( pid_t pid, wpid; int status; pid = fork(); if (pid == 0) ( // Θυγατρική διαδικασία if (execvp(args, args) == -1) ( σφάλμα ("lsh" ) έξοδος (EXIT_FAILURE) αλλιώς εάν (pid)< 0) { // Ошибка при форкинге perror("lsh"); } else { // Родительский процесс do { wpid = waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } return 1; }

Αυτή η συνάρτηση παίρνει μια λίστα ορισμάτων που δημιουργήσαμε νωρίτερα. Στη συνέχεια ξετυλίγει τη διαδικασία και αποθηκεύει την τιμή επιστροφής. Μόλις επιστρέψει το fork() παίρνουμε δύο παράλληλη διαδικασία. Η θυγατρική διαδικασία ταιριάζει με την πρώτη συνθήκη if (όπου pid == 0).

Στη θυγατρική διαδικασία, θέλουμε να εκτελέσουμε μια εντολή που καθορίζεται από το χρήστη. Επομένως, χρησιμοποιούμε μια παραλλαγή της κλήσης συστήματος exec, execvp. Διάφορες επιλογέςοι exec κάνουν διαφορετικά πράγματα. Ορισμένοι λαμβάνουν έναν μεταβλητό αριθμό ορισμάτων συμβολοσειρών, άλλοι λαμβάνουν μια λίστα συμβολοσειρών και άλλοι σας επιτρέπουν να καθορίσετε το περιβάλλον στο οποίο εκτελείται η διαδικασία. Αυτή η συγκεκριμένη παραλλαγή παίρνει ένα όνομα προγράμματος και έναν πίνακα (ονομάζεται επίσης διάνυσμα, εξ ου και το "v") ορισμάτων συμβολοσειράς (το πρώτο πρέπει να είναι το όνομα του προγράμματος). Το "p" σημαίνει ότι αντί να παρέχουμε την πλήρη διαδρομή προς το αρχείο προγράμματος για εκτέλεση, θα καθορίσουμε μόνο το όνομά του και επίσης θα πούμε στο λειτουργικό σύστημα να το αναζητήσει μόνο του.

Εάν η εντολή exec επιστρέψει -1 (ή οποιαδήποτε άλλη τιμή), τότε παρουσιάστηκε σφάλμα. Επομένως, χρησιμοποιούμε το σφάλμα για να εκτυπώσουμε το μήνυμα σφάλματος μαζί με το όνομα του προγράμματος, ώστε να είναι σαφές πού παρουσιάστηκε το σφάλμα. Μετά ολοκληρώνουμε τη διαδικασία, αλλά έτσι κέλυφοςσυνέχισε να εργάζεται.

Δεύτερη προϋπόθεση (πιδ< 0) проверяет, произошла ли в процессе выполнения fork() ошибка. Если ошибка есть, мы выводим сообщение об этом на экран, но программа продолжает работать.

Η τρίτη συνθήκη σημαίνει ότι η κλήση fork() ολοκληρώθηκε με επιτυχία. Εδώ βρίσκεται η γονική διαδικασία. Γνωρίζουμε ότι το παιδί πρόκειται να εκτελέσει τη διαδικασία, επομένως ο γονέας πρέπει να περιμένει να ολοκληρωθεί η εντολή. Χρησιμοποιούμε την waitpid() για να περιμένουμε να αλλάξει μια κατάσταση διεργασίας. Δυστυχώς η waitpid() έχει πολλές επιλογές (για παράδειγμα, exec(). Οι διεργασίες μπορούν να αλλάξουν την κατάστασή τους με πολλούς τρόπους και δεν σημαίνουν όλες οι καταστάσεις ότι η διαδικασία έχει τερματιστεί. Η διαδικασία μπορεί είτε να τελειώσει κανονικά (με επιτυχία ή με κωδικό σφάλματος), είτε να διακοπεί από ένα σήμα. Επομένως, χρησιμοποιούμε τις μακροεντολές που παρέχονται από την waitpid() για να βεβαιωθούμε ότι η διαδικασία έχει ολοκληρωθεί. Στη συνέχεια, η συνάρτηση επιστρέφει το 1 ως σήμα στη συνάρτηση κλήσης ότι μπορεί να εκτυπώσει ξανά μια προτροπή.

Εντοιχισμένα κοχύλια

Ίσως έχετε παρατηρήσει ότι η συνάρτηση lsh_loop() καλεί τη lsh_execute() , αλλά παραπάνω ονομάσαμε τη συνάρτησή μας lsh_launch(). Αυτό ήταν σκόπιμα! Το θέμα είναι ότι οι περισσότερες εντολές που εκτελεί ο φλοιός είναι προγράμματα - αλλά όχι όλες. Μερικές από τις εντολές είναι ενσωματωμένες απευθείας στο κέλυφος.

Ο λόγος είναι αρκετά απλός. Εάν θέλετε να αλλάξετε τον κατάλογο, πρέπει να χρησιμοποιήσετε τη συνάρτηση chdir(). Το θέμα είναι ότι ο τρέχων κατάλογος είναι μια ιδιότητα της διαδικασίας. Ας υποθέσουμε λοιπόν ότι γράψατε ένα πρόγραμμα cd που αλλάζει έναν κατάλογο. Απλώς αλλάζει τον τρέχοντα κατάλογο και βγαίνει, αλλά ο τρέχων κατάλογος της γονικής διαδικασίας δεν αλλάζει. Αντίθετα, η διαδικασία φλοιού πρέπει να εκτελέσει την chdir() για να ενημερώσει τον τρέχοντα κατάλογο. Στη συνέχεια, όταν εκκινεί θυγατρικές διεργασίες, κληρονομούν επίσης αυτόν τον κατάλογο.

Ομοίως, ένα πρόγραμμα με το όνομα exit δεν θα μπορεί να βγει από το κέλυφος εντολών που το κάλεσε. Αυτή η εντολή πρέπει επίσης να ενσωματωθεί στο κέλυφος. Επιπλέον, τα περισσότερα κελύφη διαμορφώνονται χρησιμοποιώντας σενάρια ρύθμισης παραμέτρων όπως ~/.bashrc. Αυτά τα σενάρια χρησιμοποιούν εντολές που αλλάζουν τον τρόπο λειτουργίας του κελύφους. Οι ίδιες οι εντολές μπορούν να αλλάξουν τον τρόπο λειτουργίας του φλοιού, υπό την προϋπόθεση ότι έχουν εφαρμοστεί μέσα στο ίδιο το φλοιό.

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

/* Δήλωση συναρτήσεων για ενσωματωμένα κελύφη: */ int lsh_cd(char **args); int lsh_help(char **args); int lsh_exit(char **args); /* Λίστα ενσωματωμένων εντολών ακολουθούμενη από αντίστοιχες συναρτήσεις */ char *builtin_str = ( "cd", "help", "exit" ); int (*builtin_func) (char **) = ( &lsh_cd, &lsh_help, &lsh_exit ); int lsh_num_builtins() ( return sizeof(builtin_str) / sizeof(char *); ) /* Υλοποιήσεις ενσωματωμένων συναρτήσεων */ int lsh_cd(char **args) ( if (args == NULL) ( fprintf(stderr, " lsh: αναμενόμενο όρισμα για \"cd\"\n"); ) else (if (chdir(args) != 0) (error("lsh"); ) ) return 1; ) int lsh_help(char **args) ( int i ; printf("LSH by Stephen Brennan\n"); printf("Πληκτρολογήστε το όνομα του προγράμματος και τα ορίσματά του και πατήστε enter.\n"); printf("Ακολουθεί μια λίστα με ενσωματωμένες εντολές: \n");< lsh_num_builtins(); i++) { printf(" %s\n", builtin_str[i]); } printf("Используйте команду man для получения информации по другим программам.\n"); return 1; } int lsh_exit(char **args) { return 0; }

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

Το επόμενο μέρος είναι μια σειρά από ενσωματωμένα ονόματα εντολών, ακολουθούμενη από μια σειρά από αντίστοιχες συναρτήσεις. Αυτό σημαίνει ότι στο μέλλον ενδέχεται να προστεθούν ενσωματωμένες εντολές τροποποιώντας αυτούς τους πίνακες αντί μεγάλος χειριστήςαλλάξτε κάπου στον κωδικό. Εάν σας μπερδεύει η δήλωση buildin_func, δεν πειράζει. Αυτός είναι ένας πίνακας δεικτών συνάρτησης (που παίρνουν έναν πίνακα συμβολοσειρών και επιστρέφουν ένα int). Οποιαδήποτε δήλωση που περιλαμβάνει δείκτες συνάρτησης στο C μπορεί να γίνει πολύ περίπλοκη.

Τέλος, υλοποιείται κάθε λειτουργία. Η συνάρτηση lsh_cd() ελέγχει πρώτα για την παρουσία του δεύτερου ορίσματος και εκτυπώνει ένα μήνυμα σφάλματος εάν δεν υπάρχει. Στη συνέχεια καλεί την chdir() , ελέγχει για σφάλματα και βγαίνει. Η λειτουργία βοήθειας εμφανίζει ένα ενημερωτικό μήνυμα και τα ονόματα όλων των ενσωματωμένων λειτουργιών. Και η συνάρτηση εξόδου επιστρέφει το 0 ως σήμα για τον τερματισμό του βρόχου εντολών.

Συνδυασμός ενσωματωμένων λειτουργιών και διαδικασιών

Το τελευταίο κομμάτι του παζλ που λείπει είναι η υλοποίηση της συνάρτησης lsh_execute(), η οποία εκκινεί είτε μια εγγενή είτε μια άλλη διεργασία.

Int lsh_execute(char **args) ( int i; if (args == NULL) ( // Εισήχθη κενή εντολή. return 1; ) for (i = 0; i< lsh_num_builtins(); i++) { if (strcmp(args, builtin_str[i]) == 0) { return (*builtin_func[i])(args); } } return lsh_launch(args); }

Ο κώδικας ελέγχει εάν η εντολή είναι ενσωματωμένη. Αν ναι, το εκκινεί, διαφορετικά καλεί την lsh_launch() για να ξεκινήσει η διαδικασία.

Βάζοντάς τα όλα μαζί

Αυτός είναι όλος ο κώδικας που μπαίνει στο κέλυφος εντολών. Εάν διαβάσετε προσεκτικά το άρθρο, θα πρέπει να έχετε καταλάβει πώς λειτουργεί το κέλυφος. Για να δοκιμάσετε το κέλυφος (σε Linux), πρέπει να αντιγράψετε αυτά τα τμήματα κώδικα στο αρχείο main.c και να το μεταγλωττίσετε. Φροντίστε να συμπεριλάβετε μόνο μία υλοποίηση lsh_read_line(). Θα χρειαστεί να συμπεριλάβετε τα ακόλουθα αρχεία κεφαλίδας:

  • #συμπεριλαμβάνω
    • waitpid() και σχετικές μακροεντολές
  • #συμπεριλαμβάνω
    • chdir()
    • πιρούνι()
    • exec()
    • pid_t
  • #συμπεριλαμβάνω
    • malloc()
    • realloc()
    • δωρεάν()
    • έξοδος()
    • execvp()
    • EXIT_SUCCESS, EXIT_FAILURE
  • #συμπεριλαμβάνω
    • fprintf()
    • printf()
    • stderr
    • getchar ()
    • σφάλμα ()
  • #συμπεριλαμβάνω
    • strcmp()
    • strtok()

Για να μεταγλωττίσετε το αρχείο, πληκτρολογήστε gcc -o main main.c σε ένα τερματικό, ακολουθούμενο από ./main για εκτέλεση.

Επιπλέον, όλες οι πηγές είναι διαθέσιμες στο GitHub.

Ανακεφαλαίωση

Προφανώς, αυτό το κέλυφος δεν είναι πολυλειτουργικό. Μερικές από τις παραλείψεις της:

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

Για να κατανοήσετε τις κλήσεις συστήματος, σας συνιστούμε να ανατρέξετε στο εγχειρίδιο: man 3p. Εάν δεν γνωρίζετε ποια διεπαφή σας προσφέρεται τυπική βιβλιοθήκη C και Unix, συνιστούμε να εξετάσετε την προδιαγραφή POSIX, ιδίως την ενότητα 13.