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

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

Ανακατεύθυνση

Για την είσοδο (δεδομένα προς επεξεργασία) και την έξοδο (δεδομένα που προκύπτουν από την επεξεργασία) των προγραμμάτων στο Linux, χρησιμοποιούνται οι λεγόμενες ροές χαρακτήρων. Πρόκειται για τα λεγόμενα character streams, για τα οποία όσοι έχουν ασχοληθεί με τη γλώσσα C είναι βέβαιο ότι έχουν ακούσει. Όμως τα character streams είναι ο μηχανισμός που χρησιμοποιείται από το σύστημα και για το χειρισμό των αρχείων. Ακριβώς γι’ αυτό, τα δεδομένα εισόδου κι εξόδου ενός προγράμματος αντιμετωπίζονται από το Linux ως ένα είδος αρχείου. Ο ενιαίος τρόπος αντιμετώπισης αρχείων και δεδομένων που δέχεται ή παράγει ένα πρόγραμμα, επιτρέπει την υλοποίηση μιας σπουδαίας δυνατότητας. Ο λόγος γίνεται για τη λεγόμενη ανακατεύθυνση (redirection). Πριν επεκταθούμε στη χρησιμότητά της, όμως, πρέπει να αναφέρουμε μερικά ακόμα στοιχεία. Η καθιερωμένη ροή που χρησιμοποιείται για την είσοδο δεδομένων στα προγράμματα θεωρείται το πληκτρολόγιο κι ονομάζεται standard input. Αντίστοιχα, η καθιερωμένη ροή για την έξοδο δεδομένων από τα προγράμματα είναι η οθόνη κι ονομάζεται standard output. Τέλος, υπάρχει και μία ακόμα ροή που χρησιμοποιείται ως έξοδος κι ονομάζεται standard error – νομίζουμε ότι καταλαβαίνετε ποια μηνύματα πηγαίνουν εκεί. Συνήθως, η εν λόγω ροή κατευθύνει τα δεδομένα στην οθόνη, όπως συμβαίνει και με την standard output. Ας επιστρέψουμε τώρα στην έννοια της ανακατεύθυνσης.

Η ανακατεύθυνση παρέχει τη δυνατότητα αποστολής οποιασδήποτε εκ των καθιερωμένων ροών εισόδου κι εξόδου, σε κάποιο αρχείο. Έτσι, μπορούμε για παράδειγμα να στείλουμε την έξοδο από την εκτέλεση ενός προγράμματος σε ένα αρχείο ή να τροφοδοτήσουμε την είσοδο ενός προγράμματος με τα περιεχόμενα ενός αρχείου. Για την ανακατεύθυνση της εξόδου χρησιμοποιείται ο χαρακτήρας >, ενώ για την ανακατεύθυνση της εισόδου χρησιμοποιείται ο χαρακτήρας <. Βέβαια, πρέπει να σημειώσουμε ότι η ανακατεύθυνση της εισόδου δεν χρησιμοποιείται συχνά. Βλέπετε, τα περισσότερα προγράμματα δέχονται ως παράμετρο κάποιο αρχείο, από το οποίο αντλούν τα προς επεξεργασία δεδομένα. Επομένως, η ανάγκη για ανακατεύθυνση της εισόδου προκύπτει σπάνια. Πριν περάσουμε σε μερικά χαρακτηριστικά παραδείγματα, πρέπει να αναφέρουμε κάτι ακόμα. Μερικές φορές, όταν ανακατευθύνουμε την έξοδο ενός προγράμματος, απαιτείται να προσδιορίσουμε το είδος της εξόδου (standard ή error) που θέλουμε να στείλουμε στον επιθυμητό προορισμό. Για το λόγο αυτό επιστρατεύονται δύο αριθμητικά ψηφία, που τοποθετούνται ακριβώς πριν από τον χαρακτήρα >. Έτσι, ο συνδυασμός 1> σημαίνει την ανακατεύθυνση του standard output, ενώ ο συνδυασμός 2> σημαίνει την ανακατεύθυνση του standard error. Βέβαια, όταν κάποιος θέλει να αναφερθεί στο standard output, μπορεί απλά να χρησιμοποιήσει το > κι όχι το 1>. Ας δούμε τώρα τα παραδείγματα που υποσχεθήκαμε.

cat my_notes > backup

Τα περιεχόμενα του αρχείου my_notes δεν θα τυπωθούν στην οθόνη, αλλά θα πάνε στο αρχείο backup.

ls -lh > dir_listing

Η λίστα με τα αρχεία του τρέχοντος καταλόγου αποθηκεύεται στο αρχείο dir_listing.

some_program 2> error_log

Σε αυτό το παράδειγμα ανακατευθύνεται μόνο η ροή standard error. Έτσι, όλα τα φυσιολογικά μηνύματα και τα δεδομένα από την εκτέλεση του προγράμματος some_program θα εμφανιστούν κανονικά στην οθόνη. Ωστόσο, τα τυχόντα μηνύματα λάθους που ενδέχεται να προκύψουν από τη λειτουργία του προγράμματος θα πάνε στο αρχείο error_log.

some_program 2> /dev/null

Αυτή τη φορά τα μηνύματα λάθους που παράγονται από το some_program θα εξαφανιστούν και δεν θα τα βρούμε ποτέ και πουθενά. Το device file ονόματι null αποτελεί κάτι σαν την καταβόθρα του συστήματος. Οτιδήποτε στείλουμε εκεί, χάνεται για πάντα.

Μετά από τα παραπάνω παραδείγματα οφείλουμε να σταθούμε σε μια σημαντική λεπτομέρεια. Αν τα αρχεία προς τα οποία γίνεται η ανακατεύθυνση δεν υπάρχουν, το σύστημα θα φροντίσει να τα δημιουργήσει αυτόματα. Αν όμως υπάρχουν, τότε τα περιεχόμενά τους θα αντικατασταθούν και στη θέση τους θα τοποθετηθούν τα νέα. Για να κατανοήσουμε τον κίνδυνο που κρύβεται εδώ, θεωρείστε ότι έχουμε ένα μεγάλο αρχείο ονόματι moan (από το “mother of all notes”), στο οποίο κρατάμε τις σημειώσεις από τη δουλειά ενός έτους. Υποθέστε τώρα ότι δίνουμε το ακόλουθο:

cat some_notes > moan

Αυτό ήταν. Μπορούμε να κοπανήσουμε το κεφάλι μας στον τοίχο, like, ελεύθερα. Το πολύτιμο περιεχόμενό του moan αντικαταστάθηκε από το περιεχόμενο του αρχείου some_notes. Για την αποφυγή τέτοιων περιπτώσεων το κέλυφος προσφέρει μια ενδιαφέρουσα δυνατότητα, η οποία μπορεί να μας γλιτώσει από πολλούς μπελάδες. Αναφερόμαστε στη λεγόμενη διπλή ανακατεύθυνση. Η διπλή ανακατεύθυνση συμπεριφέρεται όπως και η απλή με τη σημαντική όμως διαφορά ότι δεν αντικαθιστά τα παλιά δεδομένα των αρχείων, αλλά προσθέτει στο τέλος τους τα νέα. Η διπλή ανακατεύθυνση συμβολίζεται με τους χαρακτήρες >> και για τη χρήση της αρκεί να ακολουθήσουμε την ίδια σύνταξη. Επομένως, στην περίπτωση του τελευταίου παραδείγματος, για να μη χάσουμε τα δεδομένα του moan θα έπρεπε να γράψουμε κάτι τέτοιο:

cat some_notes >> moan 

Διασωλήνωση

Η ανακατεύθυνση είναι ιδιαίτερα εξυπηρετική όποτε θέλουμε να κρατήσουμε την έξοδο κάποιων προγραμμάτων σε αρχεία ή όταν απλά θέλουμε να την εξαφανίσουμε (βλέπε /dev/null). Άραγε, γίνεται να αξιοποιηθεί η έξοδος ενός προγράμματος πιο δημιουργικά; Η απάντηση είναι καταφατική και η λύση δίνεται από τη λεγόμενη διασωλήνωση (pipelining). Στην ουσία, πρόκειται για έναν μηχανισμό του λειτουργικού συστήματος που χρησιμοποιείται για την επικοινωνία μεταξύ των εφαρμογών (IPC, Inter-Process Communication). Με τη βοήθεια της διασωλήνωσης, λοιπόν, μπορούμε να πάρουμε την έξοδο ενός προγράμματος και να τη χρησιμοποιήσουμε ως είσοδο για κάποιο άλλο. Έτσι, μπορούμε κατά κάποιον τρόπο να συνδέσουμε μεταξύ τους πολλά απλά εργαλεία και να σχηματίσουμε κάποιο που θα συνδυάζει τις ικανότητες των επιμέρους. Ο χαρακτήρας που χρησιμοποιείται για τη διασωλήνωση είναι ο | (pipe). Ας δούμε μερικά παραδείγματα.

ls -ld * | wc -l

Το πρόγραμμα wc (word count) μπορεί, μεταξύ άλλων, να καταμετρά λέξεις, γραμμές και χαρακτήρες. Με την παράμετρο -l μετράει τις γραμμές. Στο συγκεκριμένο παράδειγμα, η έξοδος από την εκτέλεση του ls -ld * θα δοθεί ως είσοδος στο πρόγραμμα wc. Έτσι, αυτό που θα πάρουμε από την εκτέλεση του παραπάνω είναι το πλήθος αρχείων του τρέχοντος καταλόγου.

ls -lR | less

Το προγραμματάκι less χρησιμοποιείται για την προβολή των περιεχομένων ενός αρχείου. Σε αντίθεση με το cat, όμως, δεν αραδιάζει όλες τις γραμμές του αρχείου. Αντίθετα, εμφανίζει μόνον όσες χωράνε στην οθόνη. Την ίδια στιγμή επιτρέπει στο χρήστη να χρησιμοποιήσει τα βελάκια για να μετακινηθεί προς τα πάνω ή προς κάτω, ώστε να μελετήσει τα περιεχόμενα του αρχείου με άνεση. Για να τερματιστεί η λειτουργία του less αρκεί ένα πάτημα του πλήκτρου [Q]. Όπως αντιλαμβάνεστε, στέλνοντας την έξοδο του ls στο less (με τη βοήθεια της διασωλήνωσης) μπορούμε να εξετάσουμε την ενδεχομένως μακροσκελή λίστα αρχείων ενός καταλόγου με την ησυχία μας.

ps -aux | grep pvar > pvar_processes

Το προγραμματάκι ps εμφανίζει πληροφορίες σχετικές με τις διεργασίες που εκτελούνται στο σύστημα. Με τις παραμέτρους aux εμφανίζει όλες τις εκτελούμενες διεργασίες και, μεταξύ άλλων, δίπλα από κάθε μία εμφανίζει το όνομα του αντίστοιχου χρήστη. Όσο για το grep, αυτό αποτελεί ένα εξελιγμένο και πανίσχυρο φίλτρο. Στην είσοδό του δέχεται τα περιεχόμενα ενός αρχείου και στην έξοδό του εμφανίζει τις γραμμές που ικανοποιούν το κριτήριο αναζήτησης που έχουμε προσδιορίσει. Στο παράδειγμα που εξετάζουμε, το grep θα επιστρέψει όσες γραμμές περιέχουν τη λέξη pvar. Οπότε, τροφοδοτώντας το με την έξοδο του ps θα λάβουμε μια λίστα με τις διεργασίες που εκτελεί ο χρήστης pvar. Τέλος, με τη βοήθεια της ανακατεύθυνσης οι σχετικές πληροφορίες θα τοποθετηθούν στο αρχείο ονόματι pvar_processes.

Διαδοχική εκτέλεση προγραμμάτων

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

program1 && program2

Χρησιμοποιώντας τους χαρακτήρες &&, το κέλυφος θα προχωρήσει στην εκτέλεση του program2 μόνον αν η εκτέλεση του program1 ολοκληρωθεί με επιτυχία.

program1 || program2

Με τους χαρακτήρες ||, το κέλυφος θα προχωρήσει στην εκτέλεση του program2 μόνον εφόσον η εκτέλεση του program1 απέτυχε.

program1 ; program2

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

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

program1 && program2 && program3 && ...

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

program1 && program2 || program3 && program4 ; program5 && ...

Βέβαια, αν αποφασίσουμε να εκτελέσουμε κάτι τόσο σύνθετο θα πρέπει να έχουμε κατά νου ότι η τελική έκβαση δεν είναι εύκολο να προβλεφθεί. Στο συγκεκριμένο παράδειγμα, το program2 θα εκτελεστεί αν προηγουμένως εκτελεστεί με επιτυχία το program1. Επίσης, αν τουλάχιστον ένα από τα program1 και program2 απέτυχε να εκτελεστεί, το κέλυφος θα προσπαθήσει να εκτελέσει το program3. Αν τα καταφέρει, θα προχωρήσει στην εκτέλεση του program4. Μετά από αυτά, ανεξάρτητα από το αν και ποιο πρόγραμμα εκτελέστηκε μέχρι εκείνη τη στιγμή, το κέλυφος θα εκτελέσει το program5 κ.ο.κ. Μπερδευτήκατε; Όταν προσπαθούμε να αναλύσουμε τόσο σύνθετες εκφράσεις, πρέπει να έχουμε υπόψη ότι οι χαρακτήρες && έχουν προτεραιότητα έναντι των ||. Τέλος, μπορούμε να φανταζόμαστε το ελληνικό ερωτηματικό σαν την τελεία που χωρίζει δύο προτάσεις.

Διαχείριση εργασιών

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

Ας υποθέσουμε ότι θέλουμε να εκτελέσουμε το πρόγραμμα mpg123, ώστε να αποκωδικοποιήσουμε ένα αρχείο MP3 και να στείλουμε το αποτέλεσμα σε ένα άλλο αρχείο. Με αυτόν τον τρόπο, θα μετατρέπαμε το συγκεκριμένο αρχείο MP3 σε WAV. Κάνοντας κάτι τέτοιο η κονσόλα θα παραμείνει κατειλημμένη έως ότου ολοκληρωθεί η επεξεργασία του αρχείου MP3. Υπάρχει άραγε τρόπος το κέλυφος να είναι διαθέσιμο και κατά τη διάρκεια της μετατροπής; Φυσικά και υπάρχει, αρκεί να χρησιμοποιήσουμε τον ειδικό χαρακτήρα &. Συγκεκριμένα, γράφουμε mpg123, δίνουμε τις κατάλληλες παραμέτρους και στο τέλος της γραμμής βάζουμε κι ένα &. Εν ολίγοις, δίνουμε κάτι τέτοιο:

mpg123 –s  my_song.mp3 > my_song.wav &

Όταν χρησιμοποιούμε το χαρακτήρα &, το σύστημα τοποθετεί την εκτέλεση του εκάστοτε προγράμματος στο λεγόμενο υπόβαθρο (background). Έτσι, η κονσόλα παραμένει διαθέσιμη για την εκτέλεση οποιουδήποτε άλλου προγράμματος θέλουμε. Μια εναλλακτική μέθοδος για να πετύχουμε το ίδιο αποτέλεσμα είναι να καλέσουμε το επιθυμητό πρόγραμμα κανονικά, κι όταν η εκτέλεση ξεκινήσει να πατήσουμε το συνδυασμό πλήκτρων [CTRL+Z]. Με αυτόν τον τρόπο, το συγκεκριμένο πρόγραμμα θα πάψει προσωρινά να εκτελείται (suspend) κι εμείς θα επιστρέψουμε στην κονσόλα. Για να συνεχιστεί η λειτουργία του προγράμματος χωρίς να δεσμευτεί η κονσόλα, αρκεί να τρέξουμε το πρόγραμμα bg (από το background). Διαφορετικά, αν αλλάζαμε γνώμη κι επιθυμούσαμε την κανονική εκτέλεση του προγράμματος (επιτρέποντάς του να καταλάβει την κονσόλα), θα αρκούσε να τρέξουμε το πρόγραμμα fg (από το foreground). Χρησιμοποιώντας αυτή τη μέθοδο, σύντομα θα καταλήξουμε σε μία κατάσταση κατά την οποία εκτελούνται πολλά προγράμματα στο υπόβαθρο. Σε αυτή την περίπτωση, είναι πολύ πιθανό να χρειαστούμε τη βοήθεια του προγράμματος jobs. Εκτελώντας το, εμφανίζεται μια λίστα με όλα τα προγράμματα που έχουν τοποθετηθεί στο υπόβαθρο. Μάλιστα, σε κάθε γραμμή και πριν από το όνομα του εκάστοτε προγράμματος εμφανίζεται κι ένας αριθμός. Για να επαναφέρουμε στο προσκήνιο τη λειτουργία κάποιου προγράμματος, αρκεί να δώσουμε τον αντίστοιχο αριθμό ως παράμετρο στο fg. Κάντε μερικές δοκιμές και δείτε.

Καθολικός έλεγχος

Ακόμη και στα πιο στιβαρά λειτουργικά συστήματα, το φαινόμενο του κρεμάσματος μιας εφαρμογής δεν εκλείπει εντελώς. Άλλωστε, τις περισσότερες φορές αυτό οφείλεται σε ζητήματα που σχετίζονται με την εκάστοτε εφαρμογή κι όχι με το λειτουργικό. Σε αυτές τις περιπτώσεις, για τη διαχείριση των εργασιών απαιτούνται πιο δραστικά μέτρα. Για παράδειγμα, μπορούμε να χρησιμοποιήσουμε το πρόγραμμα killall. Δίνοντας το όνομα ενός προγράμματος ως παράμετρο στο killall, το σύστημα θα τερματίσει κάθε στιγμιότυπο του αρχικού προγράμματος. Όμως αυτό ενδέχεται να μην είναι επιθυμητό. Αν, για παράδειγμα, είχαμε εκτελέσει δύο φορές το πρόγραμμα mpg123 και το ένα στιγμιότυπο είχε κολλήσει, θα ήταν ανόητο να τερματίσουμε και τα δύο. Κάπου εδώ παρουσιάζεται η αναγκαιότητα ενός προγράμματος σαν το ps (από το process tree). Με τη βοήθειά του, όπως αναφέραμε και νωρίτερα, μπορούμε να δούμε όλες τις διεργασίες που εκτελούνται, καθώς και πολλές σχετικές πληροφορίες. Εκτελώντας το ps με παράμετρο το ux, εμφανίζονται αποκλειστικά οι εφαρμογές που εκτελούνται από το λογαριασμό μας. Έτσι, δεν έχουμε παρά να εντοπίσουμε το στιγμιότυπο του mpg123 που έχει κολλήσει και να σημειώσουμε το PID (Process ID) που του έχει αντιστοιχίσει το σύστημα. Στη συνέχεια, αρκεί να εκτελέσουμε το πρόγραμμα kill (όχι το killall) και να του δώσουμε ως παράμετρο το συγκεκριμένο PID. Παρεμπιπτόντως, σε περιπτώσεις που η κολλημένη εφαρμογή δεν τερματίζεται με αυτόν τον τρόπο, μπορούμε να της φερθούμε πιο σκληρά. Αφού πληροφορηθούμε το αντίστοιχο PID, μπορούμε να δώσουμε κάτι τέτοιο:

kill -9  αντίστοιχο_PID

Προγραμματισμός εργασιών

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

crontab –e

Με αυτόν τον τρόπο θα εκτελεστεί ο default text editor του συστήματος. Στο Ubuntu, πάντως, την πρώτη φορά που θα εκτελεστεί το crontab δεν θα ξεκινήσει αυτόματα κάποιος editor, αλλά θα ερωτηθούμε για τον ποιον προτιμάμε. Αν σας ενδιαφέρει, εμείς αγαπάμε το nano. Όταν ανοίξει ο text editor, δεν θα δούμε τίποτε απολύτως. Αυτό είναι φυσιολογικό –ειδικά για την πρώτη φορά που θα εκτελέσουμε το crontab– και δεν πρέπει να μας ανησυχήσει. Εκεί, για κάθε εφαρμογή που θέλουμε να αυτοματοποιήσουμε, θα πρέπει να εισάγουμε μια γραμμή της ακόλουθης μορφής:

j   k   l   m   n   όνομα_εφαρμογής

Το j αναφέρεται στα λεπτά (0-59), το k στην ώρα (0-23), το l στην ημέρα του μήνα (1-31), το m στο μήνα (1-12) και το n στην ημέρα της εβδομάδας (0-6). Σημειώστε ότι για κάθε πρόγραμμα δεν αρκεί μόνο το όνομά του, αλλά και η θέση του στους καταλόγους του συστήματος. Γι’ αυτό, πριν ακόμη δώσουμε crontab -e καλό θα ήταν να τρέξουμε το which με παράμετρο το όνομα του επιθυμητού προγράμματος, ώστε να πληροφορηθούμε τη θέση του. Επίσης, όταν κάποιο από τα μεγέθη που προσδιορίζουν το χρόνο εκτέλεσης δεν μας ενδιαφέρει, θα πρέπει να τοποθετήσουμε στη θέση του έναν αστερίσκο. Αφού βάλουμε όσες γραμμές θέλουμε, αρκεί να πατήσουμε το συνδυασμό πλήκτρων CTRL+O για να αποθηκευτούν οι προσθήκες μας. Ακολούθως, δεν έχουμε παρά να πατήσουμε το συνδυασμό πλήκτρων [CTRL+Χ] για να βγούμε από τον editor. Από εκείνη τη στιγμή και μετά, τα προγράμματα που εισαγάγαμε προηγουμένως θα αρχίσουν να εκτελούνται αυτόματα, στους χρόνους που προσδιορίσαμε. Αν σας μπέρδεψε η περιγραφή που μόλις κάναμε, δείτε τα ακόλουθα παραδείγματα και θα καταλάβετε αμέσως πόσο απλό και ισχυρό είναι το crontab.

30 23 * * 0 /usr/bin/my_program

To my_program θα εκτελείται κάθε Κυριακή βράδυ, στις 23:30.

*/30 * * * * /usr/bin/my_program

Το my_program θα εκτελείται ανά 30 λεπτά.

* 18 * */3 0 /usr/bin/my_program

Το my_program θα εκτελείται ανά τρεις μήνες, στις έξι το απόγευμα κάθε Κυριακής του συγκεκριμένου μήνα.

30 8 1 */1 * /usr/bin/my_program

Το my_program θα εκτελείται στις 08:30 το πρωί, κάθε πρώτη του μηνός.

Τέλος, αν θέλουμε να δούμε τις εργασίες που έχουν προγραμματιστεί με το crontab, αρκεί να το εκτελέσουμε με παράμετρο το -l. Aν πάλι θέλουμε να καταργήσουμε όλες τις προγραμματισμένες εργασίες, αρκεί να το εκτελέσουμε με την παράμετρο -r.

Εφαρμογές στο υπόβαθρο, με την κονσόλα κλειστή

Φανταστείτε το εξής σενάριο: Συνδεόμαστε στον νέο μας cloud server κι εκτελούμε ένα πρόγραμμα, του οποίου η ολοκλήρωση απαιτεί αρκετό χρόνο. Μήπως αυτό σημαίνει ότι πρέπει να αφήσουμε το τερματικό ανοιχτό; Όχι τίποτα άλλο, αλλά αυτό θα μας υποχρέωνε να αφήσουμε και τον υπολογιστή αναμμένο. Αυτό το ζήτημα μπορεί να προκύψει με οποιοδήποτε σύστημα Linux, στο οποίο συνηθίζουμε να εργαζόμαστε απομακρυσμένα. Εξάλλου, ακόμη κι όταν εργαζόμαστε τοπικά σε ένα σύστημα, η ιδέα του να αφήσουμε ένα τερματικό ανοιχτό και να φύγουμε –έστω και για λίγο– δεν είναι φρόνιμη. Οποιοσδήποτε αρπάξει την ευκαιρία και καθίσει στο σύστημά μας, θα μπορεί να το χρησιμοποιήσει με τα δικαιώματα του λογαριασμού μας. Για την αντιμετώπιση αυτών των καταστάσεων μπορούμε να στραφούμε στο προγραμματάκι screen. Ας υποθέσουμε, λοιπόν, ότι θέλουμε να τρέξουμε ένα πρόγραμμα του οποίου η εκτέλεση καθυστερεί αρκετά. Αυτό που πρέπει να κάνουμε είναι να τρέξουμε αρχικά το screen. Η οθόνη θα καθαρίσει αμέσως και θα μοιάζει σαν μόλις να συνδεθήκαμε σε μια νέα κονσόλα. Στην πράξη, θα έχει ξεκινήσει ένα νέο screen session, όπως συνηθίζουμε να λέμε. Από εκεί, δεν έχουμε παρά να τρέξουμε το (χρονοβόρο) πρόγραμμα, να πατήσουμε το συνδυασμό πλήκτρων [CTRL+A] και στη συνέχεια να πιέσουμε το πλήκτρο [D]. Με το πάτημα αυτών των πλήκτρων θα πραγματοποιηθεί το λεγόμενο detach. Με απλά λόγια, θα αποσυνδεθούμε από το screen session εντός του οποίου εκτελείται η εφαρμογή. Πλέον θα είμαστε σε θέση να αποσυνδεθούμε από την κονσόλα, γνωρίζοντας ότι το screen session –και κατ’ επέκταση η εφαρμογή μας– θα συνεχίσουν να εκτελούνται ανενόχλητα. Αργότερα, όταν συνδεθούμε εκ νέου σε κάποια κονσόλα του συστήματος, θα μπορούμε να συνδεθούμε ξανά στο αποσυνδεδεμένο screen. Για το σκοπό αυτό αρκεί να πληκτρολογήσουμε:

screen -r

Μ’ αυτόν τον τρόπο το ενεργό screen session θα επιστρέψει στο προσκήνιο και θα βρεθούμε στο περιβάλλον εντός του οποίου είχαμε τρέξει το πρόγραμμα. Πριν εμβαθύνουμε στη χρήση του screen, σημειώστε ότι για τον τερματισμό του screen session θα πρέπει είτε να γράψουμε exit είτε να πατήσουμε το συνδυασμό πλήκτρων [CTRL+D].

Πολλά προγράμματα σε πολλά screen sessions

Όπως αναφέραμε, με τη βοήθεια του screen μπορούμε να αφήσουμε το μηχάνημά μας να εκτελεί μια εργασία χωρίς να είμαστε συνδεδεμένοι σε αυτό. Όμως τι γίνεται αν επιθυμούμε την εκτέλεση πολλών προγραμμάτων; Η πιο απλή λύση είναι να ξεκινήσουμε πολλά screen sessions, τρέχοντας το screen όσες φορές επιθυμούμε. Η σχετική διαδικασία έχει ως εξής: Τρέχουμε το screen, ξεκινάμε την πρώτη εργασία, πατάμε [CTRL+Α] και μετά D. Μετά ξανατρέχουμε το screen, ξεκινάμε τη δεύτερη εργασία και κάνουμε πάλι detach. Αυτό μπορούμε να το επαναλάβουμε για όσα προγράμματα θέλουμε. Τώρα, όμως, αν δώσουμε screen -r θα εμφανιστεί μια λίστα με όλα τα screen sessions που έχουμε ξεκινήσει. Για να συνδεθούμε σε κάποιο, δεν έχουμε παρά να εκτελέσουμε screen -r και να δώσουμε ως παράμετρο το PID (Process ID) του επιθυμητού session. Φυσικά τα PID εμφανίζονται στη λίστα με τα screen sessions, που αναφέραμε μόλις. Με αυτόν τον τρόπο μπορούμε να συνδεθούμε διαδοχικά σε κάθε screen session και να ελέγξουμε την πορεία της αντίστοιχης εργασίας. Σε αυτό το σημείο, αρκετοί από εσάς θα σκεφτείτε ότι η επανασύνδεση σε κάποιο screen session χρησιμοποιώντας το αντίστοιχο PID δεν είναι καθόλου εξυπηρετική. Πράγματι, αν ξεκινήσουμε πέντε-έξι screen sessions, αποκλείεται να θυμόμαστε ποιο πρόγραμμα εκτελείται σε ποιο session. Φυσικά, η διαδοχική σύνδεση στο καθένα, εκτός από χρονοβόρα είναι και εκνευριστική. Για να αποφύγουμε αυτή την κατάσταση, είναι δυνατόν να αποδώσουμε σε κάθε session ένα όνομα. Μετέπειτα, για τη σύνδεσή μας σε αυτό θα αρκεί να χρησιμοποιήσουμε το όνομά του κι όχι το PID του. Η απόδοση ονόματος σε ένα screen session μπορεί να γίνει με δύο τρόπους. Ο πρώτος είναι να δώσουμε το επιθυμητό όνομα κατά την εκκίνηση του session:

screen -S port_scanning

Έτσι, θα ξεκινήσει ένα screen session με το όνομα port_scanning. Αργότερα, όταν χρειαστεί να επανασυνδεθούμε σε αυτό, θα πληκτρολογήσουμε:

screen -r port_scanning

Αν ξεχάσουμε να βαφτίσουμε κάποιο screen session κατά την εκκίνησή του, μπορούμε να το βαφτίσουμε αργότερα. Ας υποθέσουμε, λοιπόν, ότι έχουμε ξεκινήσει ένα session και δεν έχουμε κάνει ακόμα detach. Για να το βαφτίσουμε αρκεί να πατήσουμε το συνδυασμό [CTRL+A] και στη συνέχεια να πιέσουμε το πλήκτρο με την άνω-κάτω τελεία [:]. Κατ’ αυτό τον τρόπο, στην τελευταία γραμμή του screen session θα εμφανιστεί ο εν λόγω χαρακτήρας και το πρόγραμμα θα περιμένει να δώσουμε κάποια εντολή. Όπως αντιλαμβάνεστε, οι εντολές που μπορούμε να δώσουμε εκεί είναι σχετικά περιορισμένες και πρόκειται για “εσωτερικές” εντολές του screen: εντολές που αναγνωρίζει μόνο το screen και οι οποίες αφορούν στη λειτουργία του. Τελικά, για να βαφτίσουμε το screen session πρέπει να γράψουμε τη λέξη title, ακολούθως το επιθυμητό όνομα και να πατήσουμε το [ENTER].

Πολλά προγράμματα, στο ίδιο screen

Αυτή τη στιγμή έχουμε λύσει το αρχικό μας πρόβλημα: Μπορούμε να τρέχουμε ένα ή περισσότερα προγράμματα στο σύστημά μας, χωρίς να παραμένουμε υποχρεωτικά συνδεδεμένοι. Η λύση που είδαμε, όμως, δεν είναι η καλύτερη δυνατή. Το να γεμίσουμε το σύστημα με ένα σωρό screen sessions δεν είναι ό,τι πιο έξυπνο θα μπορούσε να κάνει κανείς. Το ιδανικό θα ήταν να τρέξουμε όλες τις εφαρμογές που θέλουμε μέσα στο ίδιο screen session. Έ, λοιπόν, το screen μπορεί να το κάνει και αυτό. Για την ακρίβεια, προσφέρει μία δυνατότητα που θυμίζει τους web browsers: επιτρέπει τη δημιουργία πολλαπλών καρτελών (tabs). Ας δούμε πώς γίνεται κάτι τέτοιο στην πράξη.

Έστω ότι θέλουμε να τρέξουμε δύο προγράμματα μέσα στο ίδιο screen session. Αφού ξεκινήσουμε το screen εκτελούμε το πρώτο πρόγραμμα, πατάμε το συνδυασμό [CTRL+A] και μετά το [C]. Με αυτόν το συνδυασμό πλήκτρων, το screen θα δημιουργήσει μια νέα καρτέλα. Εδώ πρέπει να σημειώσουμε ότι δεν θα εμφανιστεί κανένα ιδιαίτερο μήνυμα ούτε κάποιο σύμβολο που θα φανερώνει τη δημιουργία της καρτέλας. Ωστόσο η οθόνη θα καθαρίσει, σαν να είχαμε ξεκινήσει ένα νέο session. Πλέον, μπορούμε να εκτελέσουμε και το δεύτερο πρόγραμμα. Για τη μεταφορά από τη μία καρτέλα στην άλλη μπορούμε να πατήσουμε το συνδυασμό [CTRL+A] κι ακολούθως α) το P για να μεταβούμε στην προηγούμενη καρτέλα, β) το N για να μεταβούμε στην επόμενη. Βέβαια, στην περίπτωση που εξετάζουμε υπάρχουν μόνο δύο καρτέλες και η επιλογή του [P] δεν θα έχει καμία διαφορά από την επιλογή του [N]. Οποιαδήποτε στιγμή αποφασίσουμε να κάνουμε detach, μπορούμε να το κάνουμε με το γνωστό τρόπο κι αδιαφορώντας για την καρτέλα στην οποία βρισκόμαστε. Αργότερα, για να ελέγξουμε την κατάσταση των προγραμμάτων μας αρκεί να συνδεθούμε στο screen session και να μετακινηθούμε από καρτέλα σε καρτέλα, με τους συνδυασμούς που αναφέραμε προηγουμένως.

Η συνέχεια στις οθόνες σας

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

Άρθρα της σειράς

Μέρος 14: Αρχική προσέγγιση

Μέρος 24: Πρώτη επίθεση

Μέρος 34: Πλήρης έλεγχος

Μέρος 44: Προγραμματισμός στο BASH

~Spir@l Evolut10n