De ce majoritatea exemplelor systemd conțin WantedBy=multi-user.target? (Unix, Systemd)

Carl a intrebat.

Am citit ce este multi-user.target și ce înseamnă multi-user.target. documentația systemd, care precizează că multi-user.target este o țintă specială. Mai mult, o mulțime de exemple de exemple systemd conțin această linie.

  1. De ce atât de multe servicii de exemplu conțin această linie?
  2. Ce s-ar întâmpla dacă acestea nu ar conține WantedBy=multi-user.target?
  3. Ați putea să-mi dați un exemplu de situație în care ar fi de fapt recomandabil să nu includem această linie în definiția unui fișier de serviciu?
  4. În aceeași ordine de idei, când este o idee bună să se mențină acea linie?

3 răspunsuri
telcoM

1.) multi-user.target este practic cel mai apropiat echivalent al nivelului de execuție 3 clasic al SysVinit care systemd are. Atunci când un systemd sistem pornește, systemd încearcă să facă ca starea sistemului să corespundă cu starea specificată de default.target – care este, de obicei, un pseudonim pentru graphical.target fie multi-user.target.

multi-user.target definește, în mod normal, o stare a sistemului în care toate serviciile de rețea sunt pornite și sistemul va accepta logări, dar nu este pornită o interfață grafică locală. Aceasta este starea implicită tipică a sistemului pentru sistemele server, care pot fi sisteme fără cap montate pe rafturi într-o cameră de servere la distanță.

graphical.target este un alt alias posibil pentru default.target. În mod normal, este definit ca un supraansamblu al lui multi-user.target: include tot ceea ce include multi-user.target face, plus activarea unei autentificări GUI locale. Deci, un fel de runlevel 5 în SysVinit clasic.

Linia WantedBy=multi-user.target dintr-un serviciu este în esență același lucru cu specificarea „acest serviciu ar trebui să pornească în runlevels 3, 4 și 5” în sistemele SysVinit: îi spune lui systemd că acest serviciu ar trebui să fie pornit ca parte a pornirii normale a sistemului, indiferent dacă o interfață grafică locală este activă sau nu.

Cu toate acestea, WantedBy este separată de starea activată/dezactivată: deci, într-un alt sens, este un fel de „presetare”: determină în ce condiții poate avea loc pornirea automată, dar numai atunci când serviciul este activat în primul rând.

2.) dacă omiteți WantedBy=multi-user.target linie și niciun alt serviciu activat nu include un Requires=your.service sau Wants=your.service în definiția sa de serviciu, serviciul dvs. nu va fi pornit automat.

systemd funcționează în funcție de dependențe, iar la pornire, dacă nu se întâmplă nimic Requires sau Wants serviciul dumneavoastră, acesta nu va fi pornit chiar dacă serviciul este activat.

Desigur, ați putea edita serviciul dvs. default.target pentru a adăuga sau șterge Requires sau Wants linii pentru orice serviciu pe care doriți să fie pornit la pornire – dar astfel încât să puteți să introduceți un nou fișier de serviciu în sistem și să funcționeze în mod implicit (ceea ce ușurează foarte mult lucrurile pentru managerii de pachete software), systemd are funcția WantedBy și RequiredBy cuvinte cheie care pot fi utilizate pentru a introduce Wants și Requiresdependențe de tip – (respectiv) de la „celălalt capăt”.

3.) Trebuie să omiteți linia dacă nu doriți ca serviciul să fie vreodată pornit automat la pornire, sau acest serviciu face parte dintr-un lanț de dependențe pe care l-ați definit în mod explicit.

De exemplu, s-ar putea să refactorizați aplicația de server A și, dintr-un motiv sau altul, să decideți să separați o anumită funcționalitate opțională de aceasta într-un serviciu separat B, pentru a permite utilizatorului să aleagă să nu o instaleze dacă nu este necesară. Ați putea apoi să faceți din serviciul B o aplicație separată service-B.rpm, și să definiți B.service cu WantedBy=A.service pentru a face systemd să pornească serviciul B automat ori de câte ori este pornit serviciul A – dar numai atunci când service-B.rpm este instalat efectiv.

Rețineți că a Wants sau WantedBy spune doar că sistemul ar trebui să pornească un serviciu ori de câte ori este pornit și un alt serviciu sau o altă țintă, dar nu specifică absolut nimic despre ordinea de pornire/oprire. Dacă aveți nevoie ca serviciul B să fie deja în funcțiune atunci când se pornește serviciul A, ar trebui să adăugați Before=A.service în coloana B.service fișier pentru a specifica în mod explicit dependența de ordinea de pornire.

4.) De fiecare dată când faceți doriți ca serviciul să aibă capacitatea de a fi pornit automat la pornire și nu există alte dependențe deja definite.

Comentarii

  • Acesta este un răspuns fantastic de amănunțit. Ați clarificat chiar și de ce există atât Wants și WantedBy, ceea ce m-a nedumerit întotdeauna, deoarece nu-mi puteam da seama care dintre ele ar trebui să o folosesc când. –  > Por Wildcard.
  • Se trece cu vederea că WantedBy nu face nimic până când nu activați serviciul. Pachetele bazate pe Debian Linux activează automat serviciile atunci când le instalați. Dar majoritatea pachetelor bazate pe Fedora nu o fac. Iar dacă vă scrieți propriul serviciu, acesta nu va fi activat automat. Trebuie să rulați systemctl enable ... ca o etapă separată. –  > Por sourcejedi.
  • Bună observație – am crezut că am menționat-o, dar se pare că doar în sens negativ. Editat. –  > Por telcoM.
  • Tare!!!! o mulțime de informații bune aici. „Rețineți că un Wants sau WantedBy spune doar că sistemul ar trebui să pornească un serviciu ori de câte ori un alt serviciu [editare:] sau țintă este, de asemenea, pornit, dar nu specifică absolut nimic despre ordinea de pornire/oprire.” – din păcate, editarea nu este chiar corectă, este mai complicat. man systemd.target spune că atunci când ești căutat de un țintă, ești, de asemenea, ordonat automat înaintea țintei. Acest lucru explică de ce în jurnale apare graphical.target este „pornit” doar după ce toate serviciile sunt. Cu excepția cazului în care unitatea căutată (sau ținta?) a DefaultDependencies=no. –  > Por sourcejedi.
  • Un răspuns excelent –  > Por jonahb.
sourcejedi

Dacă eliminați WantedBy=multi-user.target, atunci systemctl enable your-example-here nu va reuși (zgomotos) să facă nimic.

graphical.target

Dacă instalați systemd pur de la sursă, „ținta implicită” pe care se pornește este graphical.target.

Pornirea graphical.target pornește multi-user.target, plus orice unitate (unități) necesară (necesare) pentru a furniza o interfață grafică pentru utilizator. Această complexitate suplimentară a fost aranjată în încercarea de a emula „runlevels” moștenite.

Tu într-adevăr ar trebui să ignorați / să treceți cu vederea emulația „runlevel”; oricum nu funcționează corect. Îmi pare rău! Cred că motivul pentru care se pune accentul pe „grafic” vs. „multi-utilizator” din punct de vedere istoric este că software-ul grafic 1) nu este la fel de robust și matur ca restul sistemului și 2) necesită multe resurse.

În mod obișnuit, doar câteva unități sunt specifice pentru graphical.target. Există un singur serviciu pentru interfața grafică în sine, cum ar fi gdm.target. Există câteva servicii de asistență care sunt în mare parte utilizate în principal de GUI.

Editare: Căutând pe Google se sugerează că, dacă nu aveți o interfață grafică instalată, dar „ținta implicită” a fost lăsată ca fiind graphical.target, atunci systemd ar putea înregistra un avertisment. „Cannot add dependency job for unit display-manager.service, ignoring: Unitatea display-manager.service nu a reușit să se încarce: Nu există un astfel de fișier sau director.” Dorim să evităm să ne murdărim jurnalele cu avertismente inutile. Așadar, dacă nu ați instalat o interfață grafică, este bine să folosiți systemctl set-default multi-user. Deși sistemul de instalare al sistemului dvs. de operare s-ar putea să se fi ocupat deja de acest lucru pentru dvs. În afară de asta, sunt ferm în favoarea apatiei în această chestiune :-).

sysinit.target

Unele servicii și alte tipuri de unități sunt „implicate în early boot”. Acestea sunt definite pentru a porni Before=sysinit.target – fie direct, fie indirect. Majoritatea serviciilor sunt pornite doar After=sysinit.target – acest lucru se întâmplă automat, cu excepția cazului în care serviciul setează DefaultDependencies=no.

multi-user.target

Majoritatea serviciilor de exemplu nu se încadrează în niciuna dintre categoriile de mai sus, prin urmare le atașăm la multi-user.target. Aceasta include majoritatea serviciilor de rețea (de exemplu, un server web), care reprezintă arhetipul serviciilor de sistem.

servicii activate în mod dinamic

O altă posibilitate pe care o puteți vedea, este o unitate de serviciu care este nu este pornită automat la pornire. Prin urmare, nu ar avea nevoie de WantedBy=multi-user.target. În schimb, serviciul poate fi declanșat sau „activat” de altceva.

Un exemplu în acest sens este un serviciu activat de dbus. Dbus poate fi configurat pentru a porni serviciul la cerere, atunci când se face un apel dbus către serviciu.

Pentru serviciile de rețea, puteți utiliza servicii activate de socket. S-ar putea să fie mai ușor de găsit detalii despre acestea, deoarece toată configurația se află în unități systemd. De exemplu sshd.socket sau ssh.socket este de obicei disponibil pentru a activa [email protected] sau [email protected]. Cu toate că, cred că este mai frecventă pornirea serviciului sshd în momentul pornirii.


Ca întotdeauna, cele de mai sus simplifică și omite detalii care nu păreau a fi necesare.

Comentarii

  • Mulțumesc mult. unde pot găsi nume precum multi-user.target, sysinit.target Vreau să știu ce alte opțiuni mai am în afară de acestea -.  > Por Rika.
  • @Rika Nu sunt foarte sigur de ceea ce cereți. Dar sună mai degrabă ca o altă întrebare decât un comentariu la aceasta. Încercați să puneți o nouă întrebare? Ai putea să postezi un link către ea aici, dacă vrei să o văd și eu. Totuși, nu petrec prea mult timp pe acest site în acest moment. –  > Por sourcejedi.
Jonathan Komar

The multi-user.target este un nume semantic, adică este asociat cu o semnificație. Permiteți-mi să demonstrez conceptul cu un contraexemplu. Voi aduce argumentul că decizia de a utiliza multi-user.target depinde de context.

Dacă ar fi să creați un sistem systemd unitate de utilizator mai degrabă decât o configurație unitate de sistem configurație, ați putea urma naiv convențiile unităților de sistem systemd și ați putea utiliza multi-user.target1.

Explicație cu un exemplu

Luați în considerare fișierul /home/jonathan/.config/systemd/user/coolstuff.service

Acest utilizator va fi utilizat numai în ceea ce privește utilizatorul jonathan, prin urmare, nu are sens să numesc ținta mea „multi-user.target”.

[Unit]
Description=Does some cool stuff.

[Service]
ExecStart=/bin/bash -c '/usr/bin/echo "Cool stuff" >> %h/coolstuff.txt'

[Install]
WantedBy=user.target

Observați cum am ales să folosesc WantedBy=user.target. Acest lucru se datorează faptului că domeniul de aplicare al acestui context este contul meu de utilizator și, prin urmare, am optat să folosesc propriile convenții semantice. Cu alte cuvinte, mai mulți utilizatori nu vor fi afectați de această unitate. La nivel de sistem, totuși, este mai logic să se urmeze convențiile standardizate din cauza secvenței de pornire paralelă. În timpul pornirii, multe proceduri converg către mai multe ținte. La multi-user.target este asociat semantic cu ideea de „citit pentru angajarea utilizatorului / interacțiunea cu sistemul” (fără un sistem de ferestre, așa cum a menționat telcoM), prin urmare, este un pariu sigur pentru majoritatea fișierelor de unitate de sistem.

Note de subsol

  1. Deși nu ar avea sens din acest context, ar funcționa totuși.

Tags: