Αποστολέας Θέμα: Αναζητώντας νέο init για το voidlinux Μέρος Β΄ (Η επιλογή - 66)  (Αναγνώστηκε 1222 φορές)

mobinmob

  • Global Moderator
  • *****
  • Μηνύματα: 30
    • Προφίλ
Μετά την αναζήτηση που περιγράφω  στο προηγούμενο μέρος της τρέχουσας σειράς, ήρθε μάλλον η ώρα για μια σύντομη αναφορά στο 66, τις ιδιαιτερότητες και τα χαρακτηριστικά που το κάνουν κατά τη γνώμη μου την καλύτερη λύση του υπάρχει αυτή τη στιγμή. Να τονίσω ότι τα παρακάτω δεν είναι αναλυτική παρουσίαση, αλλά ανάδειξη κάποιων χαρακτηριστικών που κατά τη γνώμη μου το κάνουν να ξεχωρίζει. Επίσης, η αναφορά στην οικογένεια και το οικοσύστημα, περιορίζεται στα συστήματα που έχουν ήδη αναφερθεί και υλοποιούν την τεχνική του process supervision.
Το 66 δημιουργήθηκε αρχικά για την διανομή obarun. Η διανομή ξεκίνησε την ζωή της βασισμένη στο arch  χρησιμοποιώντας το runit. Στην συνέχεια ο δημιουργός της (Eric Vidal)  ξεκίνησε να χρησιμοποιεί s6-rc, γράφοντας τα δικά του scripts για να κάνει ευκολότερη την χρήση του και να καλύψει “κενά” που υπήρχαν και υπάρχουν. Κάποια στιγμή όμως έφθασε στα όρια του τι μπορεί να γίνει με scripts, οπότε αποφάσισε να γράψει μια σειρά εργαλείων πάνω από το s6-rc που θα απλοποιούσαν την διαχείρισή του. Η προσπάθεια αυτή κατέληξε στο 66 και τα 66-tools. Τα εργαλεία αυτά είναι λοιπό προϊόν χρόνων τριβής με το s6-rc και κατανόησης των περιορισμών του, κυρίως όσον αφορά το ui του.

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



Frontends

Οι υπηρεσίες δεν αποτελούνται από καταλόγους (servicedirs) με διάφορα αρχεία μέσα τους όπως συμβαίνει στο s6-rc, αλλά από ένα αρχείο ανά υπηρεσία το οποίο περιέχει όλες τις σχετικές πληροφορίες, με δυνατότητα για περισσότερα. Το αρχείο αυτό έχει σύνταξη που μοιάζει με ini (name=value). Ονομάζεται frontend και διατίθεται εξαντλητική και ακριβής τεκμηρίωση [1] για τα περιεχόμενά του. Το αρχείο αυτό αντικαθιστά τρία ή και παραπάνω αρχεία που χρειάζεται το s6-rc  για κάθε υπηρεσία και μεταφράζεται αυτόματα και χωρίς την παρέμβαση του χρήστη σε αυτά κατά την ενεργοποίηση.
Ας δούμε όμως ένα απλό παράδειγμα fontend service file:


Κώδικας
[main]
@type = classic
@version = 0.0.1
@description = "acpid daemon"
@user = ( root )
@options = ( log env )

[start]
@execute = ( execl-cmdline -s { acpid -f ${cmd_args} }  )


[environment]
cmd_args=!-l

Τα πεδία που παρουσιάζονται (και αρχίζουν πάντα με @) είναι μάλλον εύκολο να καταλάβει κανείς τι κάνουν, ενώ μπορεί να δει λεπτομέρειες στην τεκμηρίωση. Έχει νόημα να σταθούμε σε ένα από αυτά, το @execute. Ενώ λοιπόν στα υπόλοιπα δηλώνονται τιμές οι οποίες “μεταφράζονται” κατάλληλα και αυτόματα για το s6-rc, το @execute έχει σαν τιμή ένα κανονικό script. Αυτό μπορεί να είναι γραμμένο σε οποιαδήποτε γλώσσα scripting, αρκεί να δηλωθεί ο σχετικός μεταγλωττιστής (interpreter) στο πεδίο @shebang. Με αυτό τον τρόπο επιτυγχάνεται μεγάλη ευελιξία στο πως γράφεται ένα frontend. Το μεγαλύτερο μέρος του είναι σε τυποποιημένη απλή σύνταξη ενώ όσο ενδέχεται να χρειαστεί κάτι παραπάνω μπορεί να υλοποιηθεί με scripting. Νομίζω πως έτσι επιτυγχάνεται μια ιδανική ισορροπία. Από την μία αποφεύγονται τα τεράστια (shell)scripts που μπορεί να είναι πηγή προβλημάτων και από την άλλη δεν καλούνται να μπουν τα services στο ζουρλομανδύα μιας εντελώς declarative σύνταξης με περίεργα αποτέλεσμα.
Στο παράδειγμα όμως δεν υπάρχει το πεδίο @shebang. Αυτό συμβαίνει γιατί χρησιμοποιείται η execline  που είναι η προκαθορισμένη γλώσσα για τα scripts. H execline[2] είναι μια μικρή non-interactive ταχύτατη γλώσσα  scripting. Ωστόσο, η χρήση της δεν είναι σε καμία περίπτωση υποχρεωτική.


Διαχείριση υπηρεσιών

Οι βελτιώσεις στην αλληλεπίδραση με τον χρήστη δεν σταματούν στον τρόπο που γράφονται τα frontends. Τo s6-rc έχει έναν ιδιαίτερο τρόπο για ενεργοποίηση/απενεργοποίηση services, που η περιγραφή του ξεφεύγει από τους στόχους αυτής της παρουσίασης. Στο 66 υπάρχουν για τον ίδιο σκοπό τα 66-enable/66-disable και 66-start/66-stop. Η λειτουργία τους είναι προφανής από το όνομά τους.
Τα εργαλεία αυτά φέρνουν στο προσκήνιο μια από τις σημαντικότερες καινοτομίες του 66 στον χώρο που περιέγραψα στο προηγούμενο άρθρο. Αυτή δεν είναι άλλη από την ύπαρξη αναλυτικών πληροφοριών (debugging/tracing) για τις ενέργειες των εργαλείων που το αποτελούν. Τα αποτελέσματα εμφανίζονται στον χρήστη με την χρήση της επιλογής/switch -v (verbosity) που ακολουθείται από το επιθυμητό επίπεδο (1 μέχρι 5). Αυτό δίνει την δυνατότητα στο χρήστη να παρακολουθήσει τις ενέργειες που γίνονται στο υπόβαθρο για την λειτουργία που έχει επιλέξει και να δει πληροφορίες για πιθανά προβλήματα καθώς και το σημείο στο οποίο προκύπτουν. Μπορώ να καταθέσω από την προσωπική μου εμπειρία, ότι πρόκειται για εξαιρετικά χρήσιμη δυνατότητα.
Το μοτίβο των χρήσιμων εργαλείων που συμπεριλαμβάνονται στο 66 project συνεχίζει με τα 66-inservice και 66-intree που δείχνουν αντίστοιχα πληροφορίες για τα services η τα trees, τα οποία είναι ομάδες από ενεργοποιημένες υπηρεσίες, ανάλογα των runlevels ή των targets σε άλλα init systems.
Δείτε μια εικόνα από τα δύο και τις πληροφορίες που παρέχονται:

Κώδικας
# 66-inservice NetworkManager

Name                  : NetworkManager
Version               : 0.0.1
In tree               : default
Status                : enabled, up (pid 1410) 1396 seconds
Type                  : longrun
Description           : networkmanager daemon
Source                : /usr/share/66/service/NetworkManager
Live                  : /run/66/tree/0/default/servicedirs/NetworkManager
Dependencies          : dbus NetworkManager-log
External dependencies : dbus:default
Optional dependencies : None
Start script          :  execl-cmdline -s { NetworkManager ${cmd_args} } 
Stop script           : None
Environment source    : /etc/66/conf/NetworkManager/0.0.1
Environment file      :
                        environment variables from: /etc/66/conf/NetworkManager/0.0.1/.NetworkManager
                       
                        # Necessary switches are either -d or -n. -n is for --no-daemon,
                       
                        # -d is for --debug. -d is preferred as it directs log output to
                        # the stdout as well as syslog.
                        cmd_args=! -d

Log name              : NetworkManager-log
Log destination       : /var/log/66/NetworkManager
Log file              :
2021-06-05 16:24:03.728314865  <info>  [1622899443.7280] device (p2p-dev-wlp2s0): supplicant management interface state: 4way_handshake -> completed
2021-06-05 16:24:03.728318516  <info>  [1622899443.7282] device (wlp2s0): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed')
2021-06-05 16:24:03.730772410  <info>  [1622899443.7288] dhcp4 (wlp2s0): activation: beginning transaction (timeout in 45 seconds)
2021-06-05 16:24:03.771244117  <info>  [1622899443.7711] dhcp4 (wlp2s0): state changed unknown -> expire
2021-06-05 16:24:05.545317450  <info>  [1622899445.5449] dhcp6 (wlp2s0): activation: beginning transaction (timeout in 45 seconds)
2021-06-05 16:24:05.752849332  <info>  [1622899445.7526] dhcp4 (wlp2s0): state changed expire -> bound, address=192.168.1.39
2021-06-05 16:24:05.756674065  <info>  [1622899445.7565] device (wlp2s0): state change: ip-config -> ip-check (reason 'none', sys-iface-state: 'managed')
2021-06-05 16:24:05.776139890  <info>  [1622899445.7760] device (wlp2s0): state change: ip-check -> secondaries (reason 'none', sys-iface-state: 'managed')
2021-06-05 16:24:05.776424624  <info>  [1622899445.7763] device (wlp2s0): state change: secondaries -> activated (reason 'none', sys-iface-state: 'managed')
2021-06-05 16:24:05.777017492  <info>  [1622899445.7769] manager: NetworkManager state is now CONNECTED_LOCAL
2021-06-05 16:24:05.778713316  <info>  [1622899445.7786] manager: NetworkManager state is now CONNECTED_SITE
2021-06-05 16:24:05.778886813  <info>  [1622899445.7788] policy: set '****' (wlp2s0) as default for IPv4 routing and DNS
2021-06-05 16:24:05.779160083  <info>  [1622899445.7791] policy: set '****' (wlp2s0) as default for IPv6 routing and DNS
2021-06-05 16:24:05.779400380  <info>  [1622899445.7793] dns-mgr: Writing DNS information to /usr/bin/resolvconf
2021-06-05 16:24:05.886532664  <info>  [1622899445.8864] device (wlp2s0): Activation: successful, device activated.
2021-06-05 16:24:05.889140647  <info>  [1622899445.8889] manager: NetworkManager state is now CONNECTED_GLOBAL
2021-06-05 16:24:50.639032402  <warn>  [1622899490.6389] dhcp6 (wlp2s0): request timed out
2021-06-05 16:24:50.639094834  <info>  [1622899490.6390] dhcp6 (wlp2s0): state changed unknown -> timeout
2021-06-05 16:24:50.639171811  <info>  [1622899490.6391] dhcp6 (wlp2s0): canceled DHCP transaction
2021-06-05 16:24:50.639207773  <info>  [1622899490.6391] dhcp6 (wlp2s0): state changed timeout -> terminated
Κώδικας
# 66-intree -zg

Name         : boot
Initialized  : yes
Enabled      : no
Starts after : None
Current      : no
Allowed      : root
Symlinks     : svc->source db->source
Contents     : /
               ├─(574,Enabled,classic) tty-earlier@tty12
               ├─(up,Enabled,oneshot) system-hostname
               ├─(up,Enabled,oneshot) mount-run
               ├─(up,Enabled,oneshot) populate-run
               ├─(up,Enabled,oneshot) mount-tmp
               ├─(up,Enabled,oneshot) populate-tmp
               ├─(up,Enabled,oneshot) mount-proc
               ├─(up,Enabled,oneshot) mount-sys
               ├─(up,Enabled,oneshot) populate-sys
               ├─(up,Enabled,oneshot) mount-dev
               ├─(up,Enabled,oneshot) mount-pts
               ├─(up,Enabled,oneshot) mount-shm
               ├─(up,Enabled,oneshot) populate-dev
               ├─(up,Enabled,oneshot) mount-cgroups
               ├─(up,Enabled,bundle) 00
               ├─(up,Enabled,oneshot) modules-kernel
               ├─(616,Enabled,longrun) udevd-log
               ├─(791,Enabled,longrun) udevd
               ├─(up,Enabled,oneshot) udevadm
               ├─(up,Enabled,oneshot) modules-system
               ├─(up,Enabled,oneshot) devices-btrfs
               ├─(up,Enabled,oneshot) system-sysctl
               ├─(up,Enabled,oneshot) system-random
               ├─(up,Enabled,oneshot) system-hwclock
               ├─(up,Enabled,bundle) all-Mount
               ├─(up,Enabled,bundle) system-Devices
               ├─(up,Enabled,oneshot) system-fontnkey
               ├─(up,Enabled,oneshot) system-fsck
               ├─(up,Enabled,oneshot) mount-fstab
               ├─(up,Enabled,bundle) all-System
               ├─(up,Enabled,oneshot) mount-rw
               ├─(up,Enabled,oneshot) mount-netfs
               ├─(up,Enabled,oneshot) local-nftables
               ├─(up,Enabled,oneshot) local-time
               ├─(up,Enabled,oneshot) local-sethostname
               ├─(up,Enabled,oneshot) local-loop
               ├─(up,Enabled,oneshot) local-authfiles
               ├─(up,Enabled,oneshot) local-dmesg
               ├─(up,Enabled,bundle) all-Local
               ├─(up,Enabled,oneshot) all-Runtime
               ├─(up,Enabled,bundle) All
               ├─(1448,Enabled,longrun) tty-rc@tty1
               ├─(1449,Enabled,longrun) tty-rc@tty2
               ├─(1444,Enabled,longrun) tty-rc@tty3
               ├─(1445,Enabled,longrun) tty-rc@tty4
               └─(up,Enabled,module) boot@system

Name         : default
Initialized  : yes
Enabled      : yes
Starts after : None
Current      : yes
Allowed      : root
Symlinks     : svc->source db->source
Contents     : /
               ├─(1377,Enabled,longrun) dbus-log
               ├─(1387,Enabled,longrun) dbus
               ├─(1381,Enabled,longrun) lxdm-log
               ├─(1409,Enabled,longrun) lxdm
               ├─(up,Enabled,oneshot) zramen
               ├─(1380,Enabled,longrun) NetworkManager-log
               ├─(1410,Enabled,longrun) NetworkManager
               └─(up,Enabled,oneshot) switch-initutils

Name         : runit
Initialized  : yes
Enabled      : yes
Starts after : default
Current      : no
Allowed      : root
Symlinks     : svc->source db->source
Contents     : /
               ├─(1431,Enabled,classic) runit-log
               └─(1432,Enabled,classic) runit

Στo αποτέλεσμα της δεύτερης εντολής ίσως κάποιος πρόσεξε το tree με την ονομασία boot και την υπηρεσία boot@system. Η υπηρεσία αυτή είναι παράδειγμα μιας από τις καινοτομίες του 66.

Early boot

Ένα από τα δυσκολότερα στάδια της εκκίνησης στην υλοποίηση είναι το  πρώιμο (early boot). Ήδη από το s6-rc υπάρχει δυνατότητα για αξιόπιστο logging πολύ νωρίς και πλήρες tty εξ’ ίσου νωρίς – αντί για κάποιο περιορισμένο emergency console. Το boot-66serv project [3], εκμεταλλεύεται τα παραπάνω για να προσφέρει ένα πλήρες πρώτο επίπεδο εκκίνησης με την υπηρεσία boot@, που είναι φτιαγμένο για να είναι ανεξάρτητο από κάποια διανομή. Με αυτό έχουν εκκινήσει επιτυχώς adelie, gentoo, devuan, voidlinux, KISS linux κ.α. χωρίς πρακτικά να απαιτούνται μετατροπές.
Τι είναι όμως το @system?
To 66 έχει την δυνατότητα υποστήριξης instantiated services, δηλαδή frontends που μπορούν να ενεργοποιηθούν σαν διαφορετικές υπηρεσίες, ανάλογα με το τι ακολουθεί το @. Για παράδειγμα αν θέλουμε να ενεργοποιήσουμε τον dhcpcd μόνο για την κάρτα δικτύου/συσκευή/network interface enp0s2  χρησιμοποιούμε το service dhcpcd@ ως εξής:
Κώδικας
# 66-enable dhcpcd@enp0s2
Αν θέλουμε να ενεργοποιήσουμε το getty του busybox για τα tty8 και tty9, χρησιμοποιούμε το busybox-getty@ service ως εξής:[/size]
Κώδικας
# 66-enable busybox-getty@tty8 busybox-getty@tty9 

To boot@ service όμως είναι κάτι παραπάνω από instantiated service. Είναι εντελώς νέος τύπος υπηρεσίας, διαφορετικός από τους classic, oneshot, longrun του s6-rc, που ονομάζεται module service[4]. Ο συγκεκριμένος τύπος συνδέει μία ή παραπάνω υπηρεσίες με τις ρυθμίσεις τους που υπάρχουν μέσα στην ενεργοποιημένη υπηρεσία. Στην περίπτωση του boot@, αυτές είναι όλες οι ρυθμίσεις του συστήματος που χρησιμοποιούνται στην εκκίνηση. Μπορεί κάποιος να πειραματιστεί με εντελώς διαφορετικούς συνδυασμούς ρυθμίσεων και να τους ενεργοποιήσει με διαφορετικό όνομα που θα ακολουθεί το @. Με την ενεργοποίηση, θα δημιουργηθεί πρακτικά ένα διαφορετικό σύνολο υπηρεσιών. Ο ίδιος μηχανισμός χρησιμοποιείται για την υπηρεσία scandir@, η οποία ακολουθείται από όνομα χρήστη και ετοιμάζει υπηρεσίες που τρέχουν για τα user trees του. Το obarun χρησιμοποιεί module services για να ελέγξει όλο το user session, δεν ήμουν όμως έτοιμος για κάτι τόσο δραστικό στο voidlinux, καθώς απαιτεί ευρύτερες αλλαγές. Λόγω του τρόπου κατασκευής του boot@, οι ρυθμίσεις που είναι κλειστές, απενεργοποιούν εντελώς τις αντίστοιχες υπηρεσίες. Αν στο αρχείο ρυθμίσεων κάποιος δηλώσει LVM=!no για παράδειγμα, δεν θα τρέξει καν το σχετικό script.
Οι υπηρεσίες στο 66 εκτελούνται παράλληλα, ενώ γίνεται χρήση του μηχανισμού εξαρτήσεων και notification του s6-rc για να μην υπάρχουν προβλήματα στην εκκίνηση. Μέχρι το s6 υπήρχε μόνο η δυνατότητα ελέγχου για το αν ξεκίνησε ένα service, όχι για το αν είναι έτοιμο για χρήση. Στο runit αυτό υλοποιείται με ένα check script και την εντολή sv check. Στο s6, υπάρχει πρόσθετα η δυνατότητα να ενημερώσει ένα service τον supervisor για την ετοιμότητά του – readiness notification. Η δυνατότητα μπορεί να υλοποιηθεί είτε στους daemons, είτε με script, ενώ στην πρώτη περίπτωση αποφεύγεται πλήρως το polling [5].
Κατά το πρώτο στάδιο της εκκίνησης για το οποίο είναι υπεύθυνο το boot@  υπάρχει καταγραφή/log η οποία εμφανίζεται στην οθόνη του χρήστη (console/stdout) αλλά και αποθηκεύεται σαν log file. Αυτή μπορεί να έχει επίπεδα verbosity από 1-4.

Τα παραπάνω δεν είναι παρά μια επιφανειακή περιγραφή κάποιων όψεων του 66 που το καθιστούν κατά τη γνώμη μου το καλύτερο σύστημα της οικογένειας :) Είναι γρήγορο, απλό στην χρήση, προσφέρει πρακτικά εργαλεία που “εξανθρωπίζουν” το δύστροπο s6-rc και χαρακτηριστικά που επεκτείνουν τις δυνατότητές του.
Τα όσα περιέγραψα υλοποιούνται με συνεργασία απλών εργαλείων προσφέροντας ένα ωραίο αποτέλεσμα για τον χρήστη. Ο βασικός τρόπος λειτουργίας, τα πρόσθετα εργαλεία, τα όρια αυτής της προσέγγισης για τον έλεγχο διεργασιών καθώς και ο τρόπος να ξεπεραστούν είναι κάτι στο οποίο θα γίνει αναφορά κάποια άλλη στιγμή.

Προσπαθώντας να εντάξω το 66 στο voidlinux αντιμετώπισα κάποιες προκλήσεις. Το επόμενο μέρος της σειράς αυτής θα αναφέρεται σε αυτές.



___________________________________
[1] https://web.obarun.org/software/66/latest/frontend.html
[2] https://skarnet.org/software/execline/
[3] https://framagit.org/pkg/obmods/boot-66serv
[4] https://web.obarun.org/software/66/latest/module-service.html
[5] https://skarnet.org/software/s6/notifywhenup.html



« Τελευταία τροποποίηση: Ιουνίου 06, 2021, 11:58:58 πμ από mobinmob »
friendly
0
funny
0
informative
0
agree
0
disagree
0
pwnt
0
like
1
dislike
0
No reactions
No reactions
No reactions
No reactions
No reactions
No reactions
Members reacted like:
linuxer,
No reactions

Tags: