Το προφίλ μας στο Google Plus
4

Το Systemd κι ο έλεγχος του logging

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

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

  • Φορτώνει αρχεία ρυθμίσεων, τα οποία συνήθως βρίσκονται στον κατάλογο /etc/systemd.
  • Καθορίζει ποιο είναι το λεγόμενο boot goal, μ’ άλλα λόγια ποια είναι η κατάσταση στην οποία πρέπει να βρεθεί το σύστημα μετά την ολοκλήρωση της διαδικασίας εκκίνησης. Συνήθως το boot goal υποδεικνύεται από το αρχείο default.target (εντός του καταλόγου /etc/systemd/system), το οποίο αποτελεί symbolic link προς το αρχείο που πράγματι περιγράφει τον στόχο εκκίνησης και βρίσκεται κάτω από τον κατάλογο /usr/lib/systemd/system.
  • Εντοπίζει όλες τις εξαρτήσεις που έχει το boot goal και προσπαθεί να τις ικανοποιήσει.

Όπως το παλιό System V έφερνε το λειτουργικό σύστημα σε κάποιο runlevel, ομοίως και το Systemd φέρνει το λειτουργικό σε μία κατάσταση που περιγράφεται από ένα εκ των ακόλουθων αρχείων *.target:

  • poweroff.target: το σύστημα κλείνει (shutdown, αντίστοιχο του runlevel 0)
  • rescue.target: το σύστημα φορτώνει σε single user mode και για την ακρίβεια μόνον ο χρήστης root μπορεί να συνδεθεί, ενώ δεν υπάρχει και δικτύωση (αντίστοιχο του runlevel 1)
  • multi-user.target: το σύστημα φορτώνει σε multiuser mode, δηλαδή πολλοί χρήστες μπορούν να συνδέονται, ενώ υπάρχει και δικτύωση (αντίστοιχο του runlevel 3)
  • graphical.target: το σύστημα υποστηρίζει πολλούς χρήστες, προσφέρει περιβάλλον γραφικών, υπάρχει και δικτύωση (αντίστοιχο του runlevel 5)
  • reboot.target: το σύστημα επανεκκινεί (αντίστοιχο του runlevel 6)

Το default.target σε ένα σύστημα desktop συνήθως δείχνει στο αρχείο graphical.target (εντός του /usr/lib/systemd/system). Σε ένα σύστημα server, από την άλλη, το default.target δείχνει στο multi-user.target (ναι, επίσης εντός του /usr/lib/systemd/system). Τώρα, τα βασικά αρχεία με τα οποία το Systemd δουλεύει ονομάζονται μονάδες (units). Υπάρχουν units διαφόρων τύπων, κι αυτό διότι το Systemd πέρα από τη διαχείριση υπηρεσιών διεκπεραιώνει κι άλλες εργασίες όπως, π.χ., είναι η προσάρτηση συστημάτων αρχείων ή η παρακολούθηση network sockets. Επιγραμματικά, παραθέτουμε τρεις συνηθισμένους τύπους units:

  • Service units (αρχεία με κατάληξη .service): Προορίζονται για την εκκίνηση υπηρεσιών (services), όπως, π.χ., είναι o Apache ή ο OpenSSH server.
  • Mount units (αρχεία με κατάληξη .mount): Χρησιμεύουν για την προσάρτηση συστημάτων αρχείων.
  • Target units (αρχεία με κατάληξη .target): Πρόκειται για αρχεία που ομαδοποιούν άλλα units.

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

Σημείωση. Για τις ανάγκες του παρόντος δουλέψαμε σε ένα σύστημα με openSUSE Leap. Εννοείται, φυσικά, ότι τους πειραματισμούς σας μπορείτε να τους κάνετε και σ’ οποιαδήποτε άλλη διανομή Linux που υιοθετεί το Systemd.

Σε κάθε διανομή Linux το systemd ξεκινάει απευθείας από τον πυρήνα, έχει process ID το 1 και αγνοεί το 'θανατηφόρο' signal 9, το οποίο τερματίζει κάθε άλλη διεργασία. Όλα τα άλλα προγράμματα του συστήματος ξεκινούν είτε απευθείας από το systemd είτε από κάποια διεργασία-απόγονό του (child process).

Σε κάθε διανομή Linux το systemd ξεκινάει απευθείας από τον πυρήνα, έχει process ID το 1 και αγνοεί το “θανατηφόρο” signal 9, το οποίο τερματίζει κάθε άλλη διεργασία. Όλα τα άλλα προγράμματα του συστήματος ξεκινούν είτε απευθείας από το systemd είτε από κάποια διεργασία-απόγονό του (child process).

Πρώτη γνωριμία με το Systemd
Είπαμε προηγουμένως ότι το boot goal υποδεικνύεται από το αρχείο default.target, το οποίο σε ένα σύστημα desktop, όπως είναι το openSUSE Leap, εξ ορισμού δείχνει στο αρχείο graphical.target. Υποθέστε ότι θέλουμε να χρησιμοποιήσουμε το μηχάνημά μας προσωρινά ως server. Ένα τέτοιο σύστημα δεν έχει λόγο να φορτώνει το υποσύστημα γραφικών. Το ιδανικό boot goal, λοιπόν, είναι το multi-user.target. Ένας τρόπος ώστε να ξεκινήσουμε το σύστημα στο multi-user.target, είναι να περάσουμε στον πυρήνα την παράμετρο

systemd.unit=multi-user.target

Συγκεκριμένα, στην αρχική οθόνη του GRUB επιλέγουμε τον πυρήνα πρoς εκκίνηση (με τα πάνω και κάτω βελάκια) και πατάμε το πλήκτρο [E] (από το Edit). Εμφανίζεται ένα παράθυρο με κείμενο, όπου βλέπουμε όλες τις οδηγίες προς τον GRUB. Με τα βελάκια του δρομέα μεταβαίνουμε στη γραμμή που αρχίζει με “linux”, και καθορίζει την έκδοση του πυρήνα προς φόρτωση. Στο τέλος της γραμμής αφήνουμε ένα κενό και προσθέτουμε το “systemd.unit=multi-user.target” (χωρίς τα εισαγωγικά, βλ. και screenshot που ακολουθεί). Για την εκκίνηση του λειτουργικού πατάμε το συνδυασμό πλήκτρων [CTRL+X].

Προσωρινή αλλαγή boot goal μέσα από τον GRUB, περνώντας στον πυρήνα την κατάλληλη παράμετρο.

Προσωρινή αλλαγή boot goal μέσα από τον GRUB, περνώντας στον πυρήνα την κατάλληλη παράμετρο.

Το σύστημα desktop των δοκιμών μας μόλις ξεκίνησε *χωρίς* περιβάλλον γραφικών. Υποστηρίζει ωστόσο δικτύωση κι επιτρέπει σύνδεση σε πολλούς χρήστες. Το boot goal του Systemd ήταν το multi-user.target, αντίστοιχο του runlevel 3 που έχει το System V.

Το σύστημα desktop των δοκιμών μας μόλις ξεκίνησε χωρίς περιβάλλον γραφικών. Υποστηρίζει ωστόσο δικτύωση κι επιτρέπει σύνδεση σε πολλούς χρήστες. Το boot goal του Systemd ήταν το multi-user.target, αντίστοιχο του runlevel 3 που έχει το System V.

Υπενθυμίζουμε ότι η αλλαγή target με τον τρόπο που μόλις δείξαμε είναι προσωρινή, υπό την έννοια ότι στο επόμενο reboot το σύστημα θα ξεκινήσει στο προκαθορισμένο target, το οποίο για εμάς είναι το graphical.target. Εκτός από το GRUB η προσωρινή αλλαγή target γίνεται κι από τη γραμμή εντολών, χωρίς επανεκκίνηση του συστήματος. Απλά πληκτρολογούμε:

ajoe@osuse-vm:~> sudo systemctl isolate multi-user.target

Αργότερα, όταν θα θέλουμε και πάλι να επιστρέψουμε στο graphical.target, θα γράψουμε:

ajoe@osuse-vm:~> sudo systemctl isolate graphical.target

Τι κάνουμε όμως αν θέλουμε μόνιμη αλλαγή boot goal, ώστε κάθε φορά που ανοίγουμε ή επανεκκινούμε τον υπολογιστή να βρισκόμαστε στο νέο target; Κοιτάξτε, μπορούμε να πραγματοποιήσουμε την αλλαγή είτε από τη γραμμή εντολών είτε από το όποιο εργαλείο διαχείρισης για το περιβάλλον γραφικών διαθέτει η διανομή μας (στο openSUSE χρησιμοποιούμε το YaST). Συγκεκριμένα, από τη γραμμή εντολών πληκτρολογούμε:

ajoe@osuse-vm:~> sudo ln -sf /usr/lib/systemd/system/multi-user.target /etc/systemd/system/default.target

Όπως βλέπετε, αυτό που κάναμε μόλις ήταν, απλά, να αλλάξουμε το αρχείο .target, στο οποίο δείχνει το default.target: έδειχνε στο graphical.target, τώρα δείχνει στο multi-user.target, άρα το λειτουργικό σε κάθε εκκίνηση/επανεκκίνηση θα υποστηρίζει πολλούς χρήστες και δικτύωση, χωρίς όμως να φορτώνει περιβάλλον γραφικών. Αν εξάλλου προτιμάμε τα εργαλεία για το GUI, πραγματοποιούμε αλλαγή boot goal με τη βοήθεια του YaST — και συγκεκριμένα μέσα από το module ονόματι Services Manager.

Αλλαγή boot goal με τη βοήθεια του YaST -- και συγκεκριμένα μέσα από το module ονόματι Services Manager.

Αλλαγή boot goal με τη βοήθεια του YaST — και συγκεκριμένα μέσα από το module ονόματι Services Manager.

Διαχείριση υπηρεσιών και προαπαιτούμενα στόχων
Το systemctl είναι το βασικό εργαλείο για τη διαχείριση των υπηρεσιών στον κόσμο του Systemd. Το χρησιμοποιήσαμε στην προηγούμενη ενότητα, ώστε ν’ αλλάξουμε προσωρινά target. Είναι ώρα να το γνωρίσουμε καλύτερα. Το συντακτικό που καταλαβαίνει το systemctl έχει ως ακολούθως:

systemctl [γενικές επιλογές] υποεντολή [επιλογές υποεντολής]

Δίνοντας σε ένα τερματικό systemctl χωρίς τίποτε άλλο, επιστρέφονται όλα τα units που έχουν φορτωθεί. Δοκιμάστε να δώσετε την εντολή — και μην αποθαρρυνθείτε από την πληθώρα των αποτελεσμάτων. Παρατηρήστε ότι επειδή δεν χωρούν όλα σε μία οθόνη, το systemctl τα στέλνει σε έναν pager. Έτσι, με το που γεμίζει η οθόνη πατάμε [Space] για συνέχεια ή τα βελάκια του δρομέα για πάνω/κάτω ή το πλήκτρο [Q] για έξοδο. Αν πάλι δεν θέλουμε pager, δίνουμε στο systemctl τη γενική επιλογή –no-pager. Με τη δε υποεντολή list-unit-files το systemctl επιστρέφει όλα τα παρόντα στο σύστημα unit files, ασχέτως της κατάστασής τους. Και πάλι μιλάμε για πολλή πληροφορία –περισσότερη από πριν–, οπότε ίσως θέλουμε να δούμε μόνο τα unit files που αντιστοιχούν σε υπηρεσίες. Σ’ αυτή την περίπτωση, στην υποεντολή list-unit-files δίνουμε την επιλογή –type=service. Συνοψίζοντας: Προκειμένου να δούμε όλες τις διαθέσιμες στο Systemd υπηρεσίες χωρίς τα αποτελέσματα να περάσουν από pager, γράφουμε:

ajoe@osuse-vm:~> systemctl --no-pager list-unit-files --type=service

Θα παρατηρήσετε ότι το παραπάνω δεν ξεχωρίζει ενεργές από μη-ενεργές υπηρεσίες και τις επιστρέφει όλες. Ένας τρόπος ώστε να δούμε μόνο τις ενεργές, είναι να δώσουμε άλλη μια επιλογή στην υποεντολή list-unit-files. Δείτε:

ajoe@osuse-vm:~> systemctl --no-pager list-unit-files --type=service --state=enabled

Παρεμπιπτόντως, η προηγούμενη γραμμή έχει απ’ όλα: εντολή (systemctl), γενική επιλογή (–no-pager), υποεντολή (list-unit-files), επιλογές υποεντολής (–type=service και –state=enabled). Μπορείτε τώρα να φανταστείτε πώς παίρνουμε μια λίστα με όλες τις υπηρεσίες που δεν είναι ενεργές; Και βέβαια μπορείτε: αντί για –state=enabled, δίνουμε –state=disabled.

Λίστα με όλες τις ενεργές υπηρεσίες του συστήματος των δοκιμών μας. Για μια λίστα με τις μη-ενεργές υπηρεσίες, στην υποεντολή list-unit-files δίνουμε την επιλογή --status=disabled.

Λίστα με όλες τις ενεργές υπηρεσίες του συστήματος των δοκιμών μας. Για μια λίστα με τις μη-ενεργές υπηρεσίες, στην υποεντολή list-unit-files δίνουμε την επιλογή –status=disabled.

Αν παρατηρήσετε λίγο τη λίστα με τις ανενεργές υπηρεσίες, θα δείτε ότι μεταξύ αυτών είναι και εκείνη του OpenSSH daemon (βλ. unit file ονόματι sshd.service). Για την κατάσταση μιας υπηρεσίας της οποίας γνωρίζουμε το unit file, πληκτρολογούμε:

ajoe@osuse-vm:~> systemctl status sshd.service 
sshd.service - OpenSSH Daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled)
   Active: inactive (dead)

Όπως βλέπετε, το αρχείο sshd.service έχει φορτωθεί (loaded) αλλά η υπηρεσία είναι απενεργοποιημένη (disabled). Είναι επίσης και ανενεργή (inactive). Λογικά θ’ αναρωτηθείτε τώρα για τη διαφορά –αν υφίσταται διαφορά– μεταξύ των όρων “απενεργοποιημένος” και “ανενεργός”. Ίσως δεν φαίνεται αμέσως, αλλά διαφορά υφίσταται. Θα την εξηγήσουμε σε πολύ λίγο, αλλά ας πούμε από τώρα ότι παρόμοια διαφορά έχουμε και με τους όρους “ενεργοποιημένος” (enabled) και “ενεργός” (active). Όταν θέλουμε να ξεκινήσουμε μια υπηρεσία που είναι ανενεργή, τότε δίνουμε στο systemctl την υποεντολή start ακολουθούμενη από το όνομα του αντίστοιχου unit file. Παράδειγμα:

ajoe@osuse-vm:~> sudo systemctl start sshd.service

Δεν παίρνουμε κάποια ειδοποίηση στο τερματικό, οπότε για να βεβαιωθούμε ότι όλα πήγαν καλά γράφουμε:

ajoe@osuse-vm:~> systemctl status sshd.service
sshd.service - OpenSSH Daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled)
   Active: active (running) since Sun 2016-09-04 08:31:32 CEST; 1min 20s ago
  Process: 2473 ExecStartPre=/usr/sbin/sshd-gen-keys-start (code=exited, status=0/SUCCESS)
 Main PID: 2477 (sshd)
   CGroup: /system.slice/sshd.service
           └─2477 /usr/sbin/sshd -D

Θεσπέσια. Βλέπουμε ότι τώρα η υπηρεσία του OpenSSH είναι ενεργή (active). Παραμένει όμως απενεργοποιημένη (disabled), κι αυτή η φαινομενική ασυνέπεια φωνάζει ότι είναι ώρα να δοθούν εξηγήσεις και διευκρινίσεις.

  • Ενεργοποιημένη (enabled) υπηρεσία: Ξεκινά κάθε φορά που ανοίγουμε ή επανεκκινούμε τον υπολογιστή, ασχέτως αν στο προηγούμενο session την είχαμε σταματήσει.
  • Απενεργοποιημένη (disabled) υπηρεσία: Δεν ξεκινά όταν ανοίγουμε ή επανεκκινούμε τον υπολογιστή, ασχέτως αν στο προηγούμενο session την είχαμε ξεκινήσει.
  • Ενεργή (active) υπηρεσία: Στο παρόν session τρέχει, όμως αυτό δεν σημαίνει ότι θα τρέχει και μετά από επανεκκίνηση του υπολογιστή. Για να ξεκινά αυτόματα και μετά από επανεκκίνηση, η υπηρεσία θα πρέπει να είναι *και* ενεργοποιημένη (enabled).
  • Ανενεργή (inactive) υπηρεσία: Στο παρόν session δεν τρέχει, όμως αυτό δεν σημαίνει ότι δεν θα τρέχει και μετά από επανεκκίνηση του υπολογιστή. Για να μην τρέχει και μετά από επανεκκίνηση, η υπηρεσία θα πρέπει να είναι *και* απενεργοποιημένη (disabled).

Και μετά τα προηγούμενα, νομίζουμε ότι οι διαφορές μεταξύ των όρων enabled/active και disabled/inactive έχουν γίνει φανερές. Είδαμε εξάλλου ότι μετά την εκκίνηση του SSH daemon η υπηρεσία παραμένει disabled. Προκειμένου να είναι και enabled και συνεπώς να ξεκινά κάθε φορά που ανοίγουμε ή επανεκκινούμε τον υπολογιστή, η υποεντολή που δίνουμε στο systemctl είναι η enable:

ajoe@osuse-vm:~> sudo systemctl enable sshd.service
ln -s '/usr/lib/systemd/system/sshd.service' '/etc/systemd/system/multi-user.target.wants/sshd.service'

Αυτό που μόλις έγινε, είναι ότι δημιουργήθηκε ένα symbolic link από το sshd.service του καταλόγου /etc/systemd/system/multi-user.target.wants, προς το αρχείο sshd.service του καταλόγου /usr/lib/systemd/system.

Ξεκινάμε την υπηρεσία του OpenSSH (1) και βεβαιωνόμαστε ότι όλα πήγαν καλά (2). Παρατηρούμε ότι η υπηρεσία, παρά το γεγονός ότι τώρα τρέχει, δεν είναι ενεργοποιημένη και συνεπώς δεν θα ξεκινήσει αυτόματα κατά την επόμενη εκκίνηση ή επανεκκίνηση του λειτουργικού. Θέλουμε η υπηρεσία να είναι διαθέσιμη ανά πάσα στιγμή, οπότε την ενεργοποιούμε (3). Μετά από έναν ακόμα έλεγχο, βλέπουμε ότι όλα είναι όπως τα θέλουμε: η υπηρεσία είναι *και* ενεργή *και* ενεργοποιημένη (4).

Ξεκινάμε την υπηρεσία του OpenSSH (1) και βεβαιωνόμαστε ότι όλα πήγαν καλά (2). Παρατηρούμε ότι η υπηρεσία, παρά το γεγονός ότι τώρα τρέχει, δεν είναι ενεργοποιημένη και συνεπώς δεν θα ξεκινήσει αυτόματα κατά την επόμενη εκκίνηση ή επανεκκίνηση του λειτουργικού. Θέλουμε η υπηρεσία να είναι διαθέσιμη ανά πάσα στιγμή, οπότε την ενεργοποιούμε (3). Μετά από έναν ακόμα έλεγχο, βλέπουμε ότι όλα είναι όπως τα θέλουμε: η υπηρεσία είναι και ενεργή και ενεργοποιημένη (4).

Από τις ονομασίες και μόνο κάποιων καταλόγων, αμέσως υποψιαζόμαστε τι συμβαίνει. Εν προκειμένω, το muti-user.target –όπως κι άλλα targets– έχει μια σειρά από προαπαιτούμενα. Αυτά παρατίθενται, εν είδη συμβολικών δεσμών, μέσα στον κατάλογο multi-user.target.wants. Ένας τρόπος προκειμένου να μάθουμε για όλα τα προαπαιτούμενα του multi-user.target, είναι απλά να δούμε τα περιεχόμενα του καταλόγου /etc/systemd/system/multi-user.target.wants.

Για τα προαπαιτούμενα του multi-user.target αρκεί να δούμε τους συμβολικούς δεσμούς που περιλαμβάνονται εντός του καταλόγου /etc/systemd/system/multi-user.target.wants.

Για τα προαπαιτούμενα του multi-user.target αρκεί να δούμε τους συμβολικούς δεσμούς που περιλαμβάνονται εντός του καταλόγου /etc/systemd/system/multi-user.target.wants.

Το σύστημα στο οποίο εργαζόμαστε γι’ αυτή την παρουσίαση, το χρησιμοποιούμε ως desktop. Το default.target, λοιπόν, είναι το graphical.target. Μετά την ενεργοποίηση του SSH daemon, όμως, αρχίσαμε να ασχολούμαστε με το multi-user.target και τα προαπαιτούμενά του, στον κατάλογο multi-user.target.wants. Δεν θα έπρεπε να ασχοληθούμε με το graphical.target και τα περιεχόμενα του καταλόγου graphical.target.wants — ή κάτι τέτοιο; Λογική η σκέψη, όμως όπως εύκολα μπορείτε να διαπιστώσετε ο προαναφερθείς κατάλογος δεν υπάρχει εντός του /etc/systemd/system (στον οποίο κατοικεί ο multi-user.target.wants). Τι συμβαίνει εδώ; Δύο πράγματα πρέπει να λάβουμε υπόψη. Κατά πρώτον, όπως μπορούμε να διαπιστώσουμε παρατηρώντας το περιεχόμενο του αρχείου /usr/lib/systemd/system/sshd.service, η υπηρεσία του SSH “εγκαθίσταται” για το multi-user.target, αφού αυτό το target τη θέλει.

Εξετάζοντας το αρχείο /usr/lib/systemd/system/sshd.service, διαπιστώσουμε ότι η υπηρεσία του SSH απαιτείται από το multi-user.target. Έτσι, μετά την ενεργοποίησή της θα είναι διαθέσιμη τόσο σ’ αυτό όσο και σε κάθε άλλο target που “εμπεριέχει” το multi-user.target. Παρατηρήστε εξάλλου ότι η υπηρεσία ενεργοποιείται μετά το network.target. Λογικό, από τη στιγμή που έχουμε να κάνουμε με δικτυακή υπηρεσία.

Κατά δεύτερον, το graphical.target απαιτεί την ενεργοποίηση του multi-user.target — είναι υπερσύνολό του, όπως θα έλεγε ενθουσιωδώς ένα μαθηματικός. Άρα, από τη στιγμή που η υπηρεσία του SSH ενεργοποιείται για το multi-user.target, παραμένει ενεργοποιημένη και για το graphical.target. Προκειμένου να δούμε τι απαιτεί το graphical.target, αρκεί να εξετάσουμε το περιεχόμενο του ομώνυμου αρχείου εντός του καταλόγου /usr/lib/systemd/system.

Ρίχνοντας μια ματιά στο περιεχόμενο του αρχείου /usr/lib/systemd/system/graphical.target, καταλαβαίνουμε ότι το αντίστοιχο target απαιτεί το multi-user.target. Επιπρόσθετα, το graphical ενεργοποιείται *μετά* το multi-user, ενώ θέλει και την υπηρεσία του display manager. Δεν ξέρουμε πώς το βλέπετε, νομίζουμε όμως ότι το περιεχόμενο των target files συμβαδίζει με αρκετά απ' όσα γνωρίζουμε από την καθημερινή μας ενασχόληση με το Linux -- τι λέτε κι εσείς;

Ρίχνοντας μια ματιά στο περιεχόμενο του αρχείου /usr/lib/systemd/system/graphical.target, καταλαβαίνουμε ότι το αντίστοιχο target απαιτεί το multi-user.target. Επιπρόσθετα, το graphical ενεργοποιείται μετά το multi-user, ενώ θέλει και την υπηρεσία του display manager. Δεν ξέρουμε πώς το βλέπετε, νομίζουμε όμως ότι το περιεχόμενο των target files συμβαδίζει με αρκετά απ’ όσα γνωρίζουμε από την καθημερινή μας ενασχόληση με το Linux — τι λέτε κι εσείς;

Χρήσιμες υποεντολές για το systemctl
Από τη συζήτηση που ξεκινήσαμε για το systemctl και μέσα από το παράδειγμα με την υπηρεσία του SSH, έχουμε ήδη κάνει σημαντική πρόοδο στο θέμα της διαχείρισης υπηρεσιών σε ένα σύστημα Linux με Systemd. Παραθέτουμε στη συνέχεια μερικές χρήσιμες υποεντολές και τη χρησιμότητα καθεμιάς. Εκτός από μια ανάγνωση, σας προτρέπουμε να πειραματιστείτε στο δικό σας σύστημα.

start
Εκκίνηση υπηρεσίας για το τρέχον session. Οφείλουμε να γνωρίζουμε το όνομα του αντίστοιχου service unit. Παράδειγμα:

ajoe@osuse-vm:~> sudo systemctl start sshd.service

Αν θέλουμε η υπηρεσία να ξεκινά αυτόματα σε κάθε (επαν)εκκίνηση, τότε πρέπει να την ενεργοποιήσουμε κιόλας. Δείτε παρακάτω.

stop
Ομαλός τερματισμός υπηρεσίας για το τρέχον session. Παράδειγμα:

ajoe@osuse-vm:~> sudo systemctl stop sshd.service

Αν θέλουμε η υπηρεσία να μην ξεκινά αυτόματα κατά την (επαν)εκκίνηση, τότε πρέπει να την απενεργοποιήσουμε κιόλας. Δείτε παρακάτω.

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

ajoe@osuse-vm:~> sudo systemctl restart sshd.service

try-restart
Επανεκκίνηση υπηρεσίας αλλά μόνον αν τρέχει ήδη.

ajoe@osuse-vm:~> sudo systemctl try-restart sshd.service

reload
Υποχρεώνει μια υπηρεσία να διαβάσει εκ νέου τα αρχεία ρυθμίσεων, χωρίς όμως να επανεκκινήσει. Ίσως, π.χ., έχουμε τροποποιήσει το configuration file του SSH daemon, ώστε να δέχεται μόνο key-based authentication ή/και για να αφουγκράζεται αιτήσεις πελατών από εναλλακτικό port (το στάνταρτ είναι το 22/TCP). Για να δουλέψει το reload πρέπει να υποστηρίζεται από την αντίστοιχη υπηρεσία.

ajoe@osuse-vm:~> sudo systemctl reload sshd.service

reload-or-restart
Υποχρεώνει μια υπηρεσία να διαβάσει εκ νέου τα αρχεία ρυθμίσεων. Σε περίπτωση που η υπηρεσία δεν υποστηρίζει το reload, τότε η παρούσα εντολή την επανεκκινεί. Αν η υπηρεσία δεν έτρεχε, τώρα ξεκινά.

ajoe@osuse-vm:~> sudo systemctl reload-or-restart sshd.service

reload-or-try-restart
Υποχρεώνει μια υπηρεσία να διαβάσει εκ νέου τα αρχεία ρυθμίσεων. Σε περίπτωση που η υπηρεσία δεν υποστηρίζει το reload, τότε η παρούσα εντολή την επανεκκινεί αλλά μόνον αν έτρεχε ήδη.

ajoe@osuse-vm:~> sudo systemctl reload-or-try-restart sshd.service

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

ajoe@osuse-vm:~> sudo systemctl status sshd.service
sshd.service - OpenSSH Daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled)
   Active: active (running) since Sun 2016-09-11 09:17:53 CEST; 12s ago
  Process: 2609 ExecStartPre=/usr/sbin/sshd-gen-keys-start (code=exited, status=0/SUCCESS)
 Main PID: 2612 (sshd)
   CGroup: /system.slice/sshd.service
           └─2612 /usr/sbin/sshd -D

Sep 11 09:17:53 osuse-vm.localdomain sshd-gen-keys-start[2609]: Checking for missing server keys in /etc/ssh
Sep 11 09:17:53 osuse-vm.localdomain systemd[1]: Started OpenSSH Daemon.
Sep 11 09:17:53 osuse-vm.localdomain sshd[2612]: Server listening on 0.0.0.0 port 22.
Sep 11 09:17:53 osuse-vm.localdomain sshd[2612]: Server listening on :: port 22.

is-active
Πληροφορία για την κατάσταση της υπηρεσίας στο τρέχον session (ενεργή ή ανενεργή). Παραδείγματα:

ajoe@osuse-vm:~> systemctl is-active sshd.service 
active
ajoe@osuse-vm:~> systemctl is-active ModemManager.service 
inactive

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

ajoe@osuse-vm:~> sudo systemctl enable sshd.service 
ln -s '/usr/lib/systemd/system/sshd.service' '/etc/systemd/system/multi-user.target.wants/sshd.service'

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

ajoe@osuse-vm:~> sudo systemctl disable sshd.service 
rm '/etc/systemd/system/multi-user.target.wants/sshd.service'

is-enabled
Πληροφορία για το αν η υπηρεσία είναι ενεργοποιημένη ή απενεργοποιημένη.

ajoe@osuse-vm:~> systemctl is-enabled sshd.service 
enabled
ajoe@osuse-vm:~> systemctl is-enabled ModemManager.service 
disabled

reenable
Απενεργοποίηση υπηρεσίας κι αμέσως μετά ενεργοποίηση εκ νέου. Η εντολή είναι χρήσιμη όποτε χρειάζεται να επαναφέρουμε τα symbolic links που αφορούν στην ενεργοποίηση της υπηρεσίας, με τον τρόπο που περιγράφεται στο τμήμα “[Install]” του αντίστοιχου service unit.

ajoe@osuse-vm:~> sudo systemctl reenable sshd.service 
rm '/etc/systemd/system/multi-user.target.wants/sshd.service'
ln -s '/usr/lib/systemd/system/sshd.service' '/etc/systemd/system/multi-user.target.wants/sshd.service'

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

Έχουμε μια υπηρεσία που είναι ενεργοποιημένη και προς το παρόν ανενεργή (1). Μπορούμε φυσικά να την απενεργοποιήσουμε (2). Αν επιπρόσθετα τη μαρκάρουμε (3), τότε το χειροκίνητο ξεκίνημά της *δεν* θα είναι δυνατό (4).

Έχουμε μια υπηρεσία που είναι ενεργοποιημένη και προς το παρόν ανενεργή (1). Μπορούμε φυσικά να την απενεργοποιήσουμε (2). Αν επιπρόσθετα τη μαρκάρουμε (3), τότε το χειροκίνητο ξεκίνημά της δεν θα είναι δυνατό (4).

unmask
Μία υπηρεσία που είναι μασκαρισμένη της αφαιρούμε τη μάσκα με την εντολή unmask. Έτσι, μπορούμε και πάλι να την ξεκινήσουμε χειροκίνητα.

Έχουμε μια υπηρεσία που είναι ενεργοποιημένη και προς το παρόν ανενεργή (1). Μπορούμε φυσικά να την απενεργοποιήσουμε (2). Αν επιπρόσθετα τη μαρκάρουμε (3), τότε το χειροκίνητο ξεκίνημά της *δεν* θα είναι δυνατό (4).

Έχουμε μια υπηρεσία που είναι ενεργοποιημένη και προς το παρόν ανενεργή (1). Μπορούμε φυσικά να την απενεργοποιήσουμε (2). Αν επιπρόσθετα τη μαρκάρουμε (3), τότε το χειροκίνητο ξεκίνημά της δεν θα είναι δυνατό (4).

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

ajoe@osuse-vm:~> systemctl --no-pager show graphical.target

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

ajoe@osuse-vm:~> systemctl --no-pager show -p "Requires" graphical.target
Requires=multi-user.target

τότε βλέπουμε τα προαπαιτούμενα του graphical.target (πρέπει να έχει προηγηθεί το multi-user.target). Αν πάλι πληκτρολογήσουμε

ajoe@osuse-vm:~> systemctl --no-pager show -p "Wants" graphical.target
Wants=display-manager.service YaST2-Firstboot.service systemd-readahead-replay.service YaST2-Second-Stage.service systemd-readahead-collect.service systemd-update-utmp-runlevel.service

τότε μαθαίνουμε για τις υπηρεσίες που είναι επιθυμητές από το graphical.target, αλλά όχι απαραίτητες.

Διαχείριση αρχείων καταγραφής
To Systemd είναι ικανό να διαχειρίζεται το ίδιο τα αρχεία καταγραφής (log files), συνεπώς δεν υπάρχει ανάγκη χρήσης κάποιας άλλης σχετικής υπηρεσίας (τύπου syslog). Πιο συγκεκριμένα, τα log files στον κόσμο του Systemd είναι υπό την εποπτεία και την ευθύνη του λεγόμενου journal, το οποίο δεν είναι τίποτε άλλο από μια υπηρεσία που διαχειρίζεται το ίδιο το Systemd. Το πλήρες όνομα του αντίστοιχου service unit είναι systemd-journald.service και, όπως εύκολα διαπιστώνουμε, η υπηρεσία είναι στατική (static) και ενεργοποιημένη:

ajoe@osuse-vm:~> systemctl status systemd-journald.service 
systemd-journald.service - Journal Service
   Loaded: loaded (/usr/lib/systemd/system/systemd-journald.service; static)
   Active: active (running) since Sun 2016-09-11 14:16:19 CEST; 2h 41min ago
     Docs: man:systemd-journald.service(8)
           man:journald.conf(5)
 Main PID: 374 (systemd-journal)
   Status: "Processing requests..."
   CGroup: /system.slice/systemd-journald.service
           └─374 /usr/lib/systemd/systemd-journald

Σημείωση. Το “static”, στη θέση όπου θα περιμέναμε να δούμε “enabled”, “disabled” ή “masked”, σημαίνει ότι η αντίστοιχη υπηρεσία δεν μπορεί να ενεργοποιηθεί: Είτε κάνει μία συγκεκριμένη εργασία και μετά τερματίζεται, είτε αποτελεί προαπαιτούμενο άλλου unit και δεν πρέπει να χρησιμοποιείται από μόνη της.

Το journal συλλέγει και οργανώνει δεδομένα logging αντλώντας τα από τον πυρήνα, τις διεργασίες και τις υπηρεσίες. Αναλόγως της διανομής οι πληροφορίες καταγραφής είναι πιθανό να χάνονται κατά το reboot. Μπορούμε, βεβαίως, να επιβάλλουμε τη διατήρησή τους: με δικαιώματα root ανοίγουμε το αρχείο /etc/systemd/journald.conf και φροντίζουμε ώστε στην ενότητα [journal] να υπάρχει η γραμμή

Storage=persistent

(και φυσικά να μην είναι “σχολιασμένη”). Αποθηκεύουμε τις αλλαγές κι επανεκκινούμε την υπηρεσία του logging:

ajoe@osuse-vm:~> sudo systemctl restart systemd-journald.service

Πλέον, τα δεδομένα καταγραφής θα οργανώνονται εντός του καταλόγου /var/log/journal — και θα διατηρούνται και μετά από reboot. Αναλόγως της χρήσης που κάνουμε ή ακόμα και του ρόλου που έχει ο υπολογιστής, ο συνολικός όγκος των δεδομένων καταγραφής είναι πιθανό να ξεφύγει προς τα πάνω, δεσμεύοντας αποθηκευτικό χώρο που ίσως είναι κρίσιμος για άλλες εφαρμογές και υπηρεσίες. Πληκτρολογήστε

ajoe@osuse-vm:~> man 5 journald.conf

ώστε να δείτε πώς θα αποκλείσετε ένα τέτοιο ενδεχόμενο. Προσέξτε, π.χ., την παράμετρο SystemMaxUse, η οποία εξ ορισμού ισούται με το 10% του μεγέθους της κατάτμησης όπου αποθηκεύονται τα δεδομένα καταγραφής. Τις δυνατότητες και την ευελιξία του journal θα τις εκτιμήσουμε αφού αρχίσουμε να χρησιμοποιούμε το journalctl, το οποίο είναι το εργαλείο λήψης πληροφοριών από τα αρχεία καταγραφής. Στη συνέχεια της παρουσίασής μας δίνουμε μερικά παραδείγματα.

Εμφάνιζε ζωντανά (επιλογή -f) τα είκοσι πιο πρόσφατα μηνύματα του journal (παράμετρος -n 20):

ajoe@osuse-vm:~> sudo journalctl -n 20 -f

Εμφάνισε μόνο μηνύματα του πυρήνα (επιλογή -k):

ajoe@osuse-vm:~> sudo journalctl --no-pager -k

(αν παραλείψουμε την επιλογή –no-pager, τα αποτελέσματα εμφανίζονται με τη βοήθεια pager).

Χωρίς τη χρήση pager (επιλογή –no-pager), επίστρεψε τα είκοσι πιο πρόσφατα μηνύματα (παράμετρος -n 20) που αφορούν στο service unit του SSH daemon (παράμετρος -u sshd):

ajoe@osuse-vm:~> sudo journalctl --no-pager -n 20 -u sshd

Τα μηνύματα που αφορούν στην πιο πρόσφατη αλλά και στις προηγούμενες εκκινήσεις (boots) καταγράφονται στο journal. Προκειμένου να δούμε τα διαθέσιμα boots που έχει καταγράψει το journal, πληκτρολογούμε:

ajoe@osuse-vm:~> sudo journalctl --list-boots

Δώστε την παραπάνω εντολή στο σύστημά σας. Μην αποθαρρυνθείτε από το πλήθος των πληροφοριών που θα επιστραφούν. Προσέξτε μόνο τους αριθμούς στην πρώτη στήλη από αριστερά: το 0 είναι το πιο πρόσφατο boot, το -1 το προηγούμενο, το -2 εκείνο πριν το προηγούμενο κ.ο.κ. Δείτε εξάλλου ότι για κάθε boot υπάρχει και το αντίστοιχο timestamp. Αν τώρα θέλουμε τα μηνύματα του πιο πρόσφατου boot, τότε γράφουμε:

ajoe@osuse-vm:~> sudo journalctl --no-pager -b 0

Ειδικά γι’ αυτό μπορούμε να παραλείψουμε τον αριθμό του (δηλαδή το 0). Για όλα τα προηγούμενα, όμως, τον συμπεριλαμβάνουμε υποχρεωτικά:

ajoe@osuse-vm:~> sudo journalctl --no-pager -b -5

Εμφάνιζε ζωντανά (επιλογή -f) όλα τα μηνύματα από τώρα και στο εξής (παράμετρος –since “now”):

ajoe@osuse-vm:~> sudo journalctl -f --since "now"

Χωρίς pager (επιλογή –no-pager) εμφάνισε όλα τα σημερινά μηνύματα (παράμετρος –since “today”) αλλά έως τις δύο και μισή μετά το μεσημέρι (παράμετρος –until “14:30”):

ajoe@osuse-vm:~> sudo journalctl --no-pager --since "today" --until "13:00"

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

ajoe@osuse-vm:~> sudo journalctl --since "04:00" --until "06:00"

Δώσε όλα τα μηνύματα που αφορούν στο χρήστη με user ID το 1000 (παράμετρος _UID=1000), ξεκινώντας από τις επτά το βράδυ (παράμετρος –since “19:00”):

ajoe@osuse-vm:~> sudo journalctl --since "19:00" _UID=1000

(Το τελευταίο ήταν παράδειγμα φιλτραρίσματος με βάση συγκεκριμένο πεδίο: το UID.)

Κλείνουμε την παρουσίασή μας με ένα απλό σενάριο διερεύνησης προβλημάτων περί υπηρεσιών. Ας υποθέσουμε ότι χρησιμοποιούμε τον SSH daemon και κάποια στιγμή αποφασίζουμε ν’ αλλάξουμε το τυπικό port που χρησιμοποιεί η υπηρεσία: είναι το 22, αλλά για λόγους ασφαλείας θέλουμε να το αλλάξουμε στο 50022. Είχαμε διαβάσει κάτι σχετικό κάπου στο deltaHacker –δεν θυμόμαστε σε ποιο άρθρο αλλά δεν έχει σημασία– οπότε τώρα που το θυμηθήκαμε λέμε να το εφαρμόσουμε κιόλας. Με δικαιώματα διαχειριστή, λοιπόν, ανοίγουμε το αρχείο /etc/ssh/sshd_config και τροποποιούμε αναλόγως την παράμετρο Port. Βέβαιοι πως όλα πήγαν καλά, αποθηκεύουμε την αλλαγή, ξεχνάμε το όλο θέμα και συνεχίζουμε τις δουλειές μας. Αργότερα, ίσως και μια άλλη μέρα, συνειδητοποιούμε ότι είναι αδύνατον να συνδεθούμε απομακρυσμένα στο μηχάνημά μας μέσω SSH. Με το που θα βρεθούμε ξανά μπροστά του, αρχικά γράφουμε:

ajoe@osuse-vm:~> systemctl status sshd.service

Διαπιστώνουμε ότι για κάποιον λόγο η υπηρεσία δεν έχει ξεκινήσει. Με τη βοήθεια του journalctl εμφανίζουμε τις τελευταίες δεκαπέντε γραμμές του log που αφορούν ειδικά στο service unit του SSH:

ajoe@osuse-vm:~> sudo journalctl --no-pager -n 15 -u sshd

Ανάμεσα στις γραμμές βρίσκεται και η εξήγηση για την αποτυχία εκκίνησης της υπηρεσίας:

[...]
Sep 11 21:59:01 osuse-vm.localdomain sshd[2369]: /etc/ssh/sshd_config line 13: Badly formatted port number.
[...]

Κάτι δεν πάει καλά με το port, προφανώς: Ανοίγοντας το /etc/ssh/sshd_config βλέπουμε ότι αντί για το port 50022 είχαμε καθορίσει το (ανύπαρκτο) port 500022! Ένα μηδενικό ήταν ο υπαίτιος, αλλά χάρη στο journalctl το βρήκαμε αμέσως.

Διαβάστε το man page του journalctl για όλες τις άλλες δυνατότητές του. Επίσης: Καλωσορίσατε στον κόσμο του Systemd. Τέλος: Το Systemd έχει την ικανότητα παράλληλης εκκίνησης υπηρεσιών, παραβιάζοντας, φαινομενικά, τις μεταξύ τους εξαρτήσεις. Μπορείτε να διερευνήσετε περισσότερο, ώστε να διαπιστώσετε πώς είναι δυνατόν να καταφέρνει κάτι τέτοιο; Αν το ψάξετε, γράψτε μας τι ανακαλύψατε αφήνοντας σχόλιο κάτω από το παρόν άρθρο. Καλή σας διασκέδαση!

Διερεύνηση του πραγματικού αιτίου για την αποτυχία εκκίνησης του SSH deamon. Με το systemctl διαπιστώνουμε ότι έχουμε πρόβλημα, με το journalctl βρίσκουμε σε τι οφείλεται.

Διερεύνηση του πραγματικού αιτίου για την αποτυχία εκκίνησης του SSH deamon. Με το systemctl διαπιστώνουμε ότι έχουμε πρόβλημα, με το journalctl βρίσκουμε σε τι οφείλεται.

Από το YaST, το πολυεργαλείο διαχείρισης συστήματος του openSUSE, δεν θα μπορούσε να λείπει κι ένα module για τη διαχείριση του journal. Ξέρουμε βέβαια ότι αγαπάτε την κονσόλα και τη γραμμή εντολών, κάνουμε ωστόσο και την αναφορά μας στο YaST για τους 7 αναγνώστες που προτιμούν το περιβάλλον γραφικών.

Από το YaST, το πολυεργαλείο διαχείρισης συστήματος του openSUSE, δεν θα μπορούσε να λείπει κι ένα module για τη διαχείριση του journal. Ξέρουμε βέβαια ότι αγαπάτε την κονσόλα και τη γραμμή εντολών, κάνουμε ωστόσο και την αναφορά μας στο YaST για τους 7 αναγνώστες που προτιμούν το περιβάλλον γραφικών.

Σας άρεσε το άρθρο; Αν ναι, τι θα λέγατε για ένα tip στο PayPal;

4 Responses to “Το Systemd κι ο έλεγχος του logging”

  1. drpaneas | 18/09/2016 at 13:47

    Πολύ καλό. Ίσως το καλύτερο ελληνικό άρθρο για το systemd.

  2. hlias | 19/09/2016 at 12:21

    καλημερα σας.
    Θελω να ρωτησω κατι ασχετο με το systamd.
    Στο pc στη δουλεια μου, ως OS εχουν τα windows xp και ως περιηγητη εχω τον firefox εκδοση 48,02,σημερα διαπιστωνω οτι o firefox δεν μπαινει σε ιστοσελιδες με πρωτοκολο https(πχ deltahacker.gr,google.gr…..)και μου λεει οτι η google.gr χρησιμοποιει ενα μη εγκυρο πιστοποιητικο …..
    Μπορει καποιος να μου πει τι ακριβως συμβαίνει;και αν διορθωνεται;
    ΕΥΧΑΡΙΣΤΩ.

  3. hlias | 20/09/2016 at 11:39

    Συγνωμη λαθος δικο μου,ειχα κατα λαθος αλλαξει την μερομηνια στο pc μου και ο firefox εθεωρουσε το πιστοποιητικο οτι ειχε ληξει.
    Η λαθος ημερομηνια ηταν 18/10/2015 το πιστοποιητικο ληγει 13/10/1016 αρα……
    ΕΥΧΑΡΙΣΤΩ

Leave a Reply

You must be logged in to post a comment.

Σύνδεση

Αρχείο δημοσιεύσεων