GNU/Linux >> Znalost Linux >  >> Linux

Spravujte spouštění pomocí systemd

Při nedávném nastavování linuxového systému jsem chtěl vědět, jak zajistit, aby závislosti pro služby a další jednotky fungovaly dříve, než se tyto závislé služby a jednotky spustí. Konkrétně jsem potřeboval více znalostí o tom, jak systemd spravuje spouštěcí sekvenci, zejména při určování pořadí, ve kterém se služby spouštějí v tom, co je v podstatě paralelní systém.

Možná víte, že SystemV (předchůdce systemd, jak jsem vysvětlil v prvním článku této série) objednává spouštěcí posloupnost pojmenováním spouštěcích skriptů s předponou SXX, kde XX je číslo od 00 do 99. SystemV pak použije pořadí řazení podle názvu a spustí každý spouštěcí skript v pořadí pro požadovanou úroveň běhu.

Systemd však používá soubory jednotek, které může vytvořit nebo upravit správce systému, k definování podprogramů nejen pro inicializaci, ale také pro běžný provoz. Ve třetím článku této série jsem vysvětlil, jak vytvořit soubor přípojné jednotky. V tomto pátém článku ukážu, jak vytvořit jiný typ souboru jednotky – soubor servisní jednotky, který spouští program při spuštění. Můžete také změnit určitá konfigurační nastavení v souboru jednotky a použít žurnál systemd k zobrazení umístění vašich změn ve spouštěcí sekvenci.

Příprava

Ujistěte se, že jste odstranili rhgb a quiet z GRUB_CMDLINE_LINUX= řádku v /etc/default/grub souboru, jak jsem ukázal ve druhém článku této série. To vám umožní sledovat proud zpráv při spuštění systému Linux, který budete potřebovat pro některé experimenty v tomto článku.

Program

V tomto tutoriálu vytvoříte jednoduchý program, který vám umožní sledovat zprávu během spouštění na konzole a později v deníku systemd.

Vytvořte shellový program /usr/local/bin/hello.sh a přidejte následující obsah. Chcete zajistit, aby byl výsledek viditelný při spuštění a abyste jej snadno našli při prohlížení deníku systemd. Budete používat verzi programu "Ahoj světe" s několika pruhy kolem, takže vyčnívá. Ujistěte se, že soubor je spustitelný a má vlastnictví uživatele a skupiny root s oprávněními 700 pro zabezpečení:

#!/usr/bin/bash
# Simple program to use for testing startup configurations
# with systemd.
# By David Both
# Licensed under GPL V2
#
echo "###############################"
echo "######### Hello World! ########"
echo "###############################"

Spusťte tento program z příkazového řádku a ověřte, že funguje správně:

[root@testvm1 ~]# hello.sh 
###############################
######### Hello World! ########
###############################
[root@testvm1 ~]#

Tento program může být vytvořen v jakémkoli skriptovacím nebo kompilovaném jazyce. Soubor hello.sh program by také mohl být umístěn na jiných místech na základě hierarchické struktury souborového systému Linux (FHS). Umístím jej do /usr/local/bin adresář, takže jej lze snadno spouštět z příkazového řádku, aniž byste museli při zadávání příkazu přidávat cestu. Zjistil jsem, že mnoho programů shellu, které vytvářím, je třeba spouštět z příkazového řádku a pomocí dalších nástrojů, jako je systemd.

Soubor servisní jednotky

Vytvořte soubor servisní jednotky /etc/systemd/system/hello.service s následujícím obsahem. Tento soubor nemusí být spustitelný, ale kvůli bezpečnosti potřebuje vlastnictví uživatele a skupiny root a oprávnění 644 nebo 640:

# Simple service unit file to use for testing 
# startup configurations with systemd.
# By David Both
# Licensed under GPL V2
#

[Unit]
Description=My hello shell script

[Service]
Type=oneshot
ExecStart=/usr/local/bin/hello.sh

[Install]
WantedBy=multi-user.target

Ověřte, že soubor servisní jednotky funguje podle očekávání zobrazením stavu služby. Veškeré syntaktické chyby se zobrazí zde:

[root@testvm1 ~]# systemctl status hello.service 
● hello.service - My hello shell script
     Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
     Active: inactive (dead)
[root@testvm1 ~]#

Tento typ služby „oneshot“ můžete bez problémů spustit vícekrát. Typ oneshot je určen pro služby, kde je program spuštěný souborem servisní jednotky hlavním procesem a musí být dokončen, než systemd spustí jakýkoli závislý proces.

Existuje sedm typů služeb a vysvětlení každého (spolu s ostatními částmi souboru servisní jednotky) najdete na manuálové stránce systemd.service(5). (Další informace naleznete také ve zdrojích na konci tohoto článku.)

I když jsem zvědavý, chtěl jsem vidět, jak by mohla vypadat chyba. Takže jsem vymazal "o" z Type=oneshot řádek, takže to vypadalo jako Type=neshot a znovu spustil příkaz:

[root@testvm1 ~]# systemctl status hello.service
● hello.service - My hello shell script
     Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
     Active: inactive (dead)

May 06 08:50:09 testvm1.both.org systemd[1]: /etc/systemd/system/hello.service:12: Failed to parse service type, ignoring: neshot
[root@testvm1 ~]#

Tyto výsledky mi přesně řekly, kde se stala chyba, a velmi usnadnily vyřešení problému.

Další zdroje pro Linux

  • Cheat pro příkazy Linuxu
  • Cheat sheet pro pokročilé příkazy systému Linux
  • Bezplatný online kurz:Technický přehled RHEL
  • Síťový cheat pro Linux
  • Cheat sheet SELinux
  • Cheat pro běžné příkazy pro Linux
  • Co jsou kontejnery systému Linux?
  • Naše nejnovější články o Linuxu

Jen si uvědomte, že i po obnovení hello.service soubor do původní podoby, chyba přetrvá. I když restartování chybu vymaže, neměli byste to dělat, takže jsem hledal způsob, jak odstranit přetrvávající chyby, jako je tato. Narazil jsem na chyby služby, které vyžadují příkaz systemctl daemon-reload resetovat chybový stav, ale to v tomto případě nefungovalo. Zdá se, že chybové zprávy, které lze opravit pomocí tohoto příkazu, vždy obsahují prohlášení v tomto smyslu, takže víte, že jej máte spustit.

Doporučuje se však spustit systemctl daemon-reload po změně souboru jednotky nebo vytvoření nového. Toto upozorní systemd, že změny byly provedeny, a může zabránit určitým typům problémů se správou změněných služeb nebo jednotek. Pokračujte a spusťte tento příkaz.

Po opravě překlepu v souboru servisní jednotky stačí systemctl restart hello.service vymazal chybu. Trochu experimentujte zavedením některých dalších chyb do hello.service soubor, abyste viděli, jaké druhy výsledků získáte.

Spusťte službu

Nyní jste připraveni spustit novou službu a zkontrolovat stav, abyste viděli výsledek. Ačkoli jste pravděpodobně provedli restart v předchozí části, můžete jednorázovou službu spustit nebo restartovat tolikrát, kolikrát chcete, protože se jednou spustí a poté se ukončí.

Pokračujte a spusťte službu (jak je uvedeno níže) a poté zkontrolujte stav. V závislosti na tom, jak moc jste s chybami experimentovali, se vaše výsledky mohou lišit od mých:

[root@testvm1 ~]# systemctl start hello.service 
[root@testvm1 ~]# systemctl status hello.service
● hello.service - My hello shell script
     Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
     Active: inactive (dead)

May 10 10:37:49 testvm1.both.org hello.sh[842]: ######### Hello World! ########
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script.
[root@testvm1 ~]#

Všimněte si ve výstupu příkazu status, že zprávy systemd udávají, že hello.sh skript spuštěn a služba dokončena. Můžete také vidět výstup ze skriptu. Toto zobrazení je generováno z žurnálových záznamů nejnovějších vyvolání služby. Zkuste službu spustit několikrát a poté znovu spusťte příkaz status, abyste viděli, co tím myslím.

Měli byste se také podívat přímo na obsah časopisu; existuje několik způsobů, jak to udělat. Jedním ze způsobů je zadat identifikátor typu záznamu, v tomto případě název shell skriptu. Zobrazí se záznamy žurnálu pro předchozí restartování i aktuální relaci. Jak můžete vidět, už nějakou dobu zkoumám a testuji tento článek:

[root@testvm1 ~]# journalctl -t hello.sh
<snip>
-- Reboot --
May 08 15:55:47 testvm1.both.org hello.sh[840]: ###############################
May 08 15:55:47 testvm1.both.org hello.sh[840]: ######### Hello World! ########
May 08 15:55:47 testvm1.both.org hello.sh[840]: ###############################
-- Reboot --
May 08 16:01:51 testvm1.both.org hello.sh[840]: ###############################
May 08 16:01:51 testvm1.both.org hello.sh[840]: ######### Hello World! ########
May 08 16:01:51 testvm1.both.org hello.sh[840]: ###############################
-- Reboot --
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
May 10 10:37:49 testvm1.both.org hello.sh[842]: ######### Hello World! ########
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
[root@testvm1 ~]#

Chcete-li najít systémové záznamy pro hello.service jednotku, můžete hledat na systemd. Můžete použít G+Enter přejděte na konec záznamů deníku a poté přejděte zpět, abyste našli ty, které vás zajímají. Použijte -b možnost zobrazit pouze položky pro poslední spuštění:

[root@testvm1 ~]# journalctl -b -t systemd
<snip>
May 10 10:37:49 testvm1.both.org systemd[1]: Starting SYSV: Late init script for live image....
May 10 10:37:49 testvm1.both.org systemd[1]: Started SYSV: Late init script for live image..
May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
May 10 10:37:50 testvm1.both.org systemd[1]: Starting D-Bus System Message Bus...
May 10 10:37:50 testvm1.both.org systemd[1]: Started D-Bus System Message Bus.

Zkopíroval jsem několik dalších deníkových záznamů, abyste měli představu o tom, co můžete najít. Tento příkaz chrlí všechny řádky deníku týkající se systemd – 109 183 řádků, když jsem to psal. To je spousta dat k třídění. Můžete použít vyhledávací zařízení pageru, které je obvykle less , nebo můžete použít vestavěný grep Vlastnosti. -g (nebo --grep= ) používá regulární výrazy kompatibilní s Perl:

[root@testvm1 ~]# journalctl -b -t systemd -g "hello"
[root@testvm1 ~]# journalctl -b -t systemd -g "hello"
-- Logs begin at Tue 2020-05-05 18:11:49 EDT, end at Sun 2020-05-10 11:01:01 EDT. --
May 10 10:37:49 testvm1.both.org systemd[1]: Starting My hello shell script...
May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script.
[root@testvm1 ~]#

Můžete použít standardní GNU grep příkaz, ale to by neukázalo metadata protokolu na prvním řádku.

Pokud nechcete vidět pouze položky deníku týkající se vašeho hello službu, můžete věci trochu zúžit zadáním časového rozsahu. Například začnu s časem začátku 10:54:00 na mém testovacím virtuálním počítači, což byl začátek minuty, ze které pocházejí výše uvedené položky. Všimněte si, že --since= možnost musí být uzavřena v uvozovkách a že tato možnost může být také vyjádřena jako -S "<time specification>" .

Datum a čas se na vašem hostiteli budou lišit, takže nezapomeňte použít časová razítka, která odpovídají časům ve vašich denících:

[root@testvm1 ~]# journalctl --since="2020-05-10 10:54:00"
May 10 10:54:35 testvm1.both.org audit: BPF prog-id=54 op=LOAD
May 10 10:54:35 testvm1.both.org audit: BPF prog-id=55 op=LOAD
May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script.
May 10 10:54:45 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd"'
May 10 10:54:45 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/"'
May 10 10:56:00 testvm1.both.org NetworkManager[840]: <error> [1589122560.0633] dhcp4 (enp0s3): error -113 dispatching events
May 10 10:56:00 testvm1.both.org NetworkManager[840]: <info>  [1589122560.0634] dhcp4 (enp0s3): state changed bound -> fail
<snip>

since specifikace přeskočí všechny položky před tímto časem, ale po tomto čase stále existuje mnoho položek, které nepotřebujete. Můžete také použít until možnost oříznout záznamy, které přijdou trochu po čase, který vás zajímá. Chci celou minutu, kdy k události došlo, a nic víc:

[root@testvm1 ~]# journalctl --since="2020-05-10 10:54:35" --until="2020-05-10 10:55:00"
-- Logs begin at Tue 2020-05-05 18:11:49 EDT, end at Sun 2020-05-10 11:04:59 EDT. --
May 10 10:54:35 testvm1.both.org systemd[1]: Reloading.
May 10 10:54:35 testvm1.both.org audit: BPF prog-id=27 op=UNLOAD
May 10 10:54:35 testvm1.both.org audit: BPF prog-id=26 op=UNLOAD
<snip>
ay 10 10:54:35 testvm1.both.org audit: BPF prog-id=55 op=LOAD
May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script.
May 10 10:54:45 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd>
May 10 10:54:45 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/>
lines 1-46/46 (END)

Pokud v tomto časovém období došlo k velké aktivitě, můžete výsledný datový tok dále zúžit pomocí kombinace těchto možností:

[root@testvm1 ~]# journalctl --since="2020-05-10 10:54:35" --until="2020-05-10 10:55:00" -t "hello.sh"
-- Logs begin at Tue 2020-05-05 18:11:49 EDT, end at Sun 2020-05-10 11:10:41 EDT. --
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
[root@testvm1 ~]#

Vaše výsledky by měly být podobné mým. Z této série experimentů můžete vidět, že služba fungovala správně.

Restartujte – konečně

Dosud jste nerestartovali hostitele, kam jste nainstalovali službu. Udělejte to nyní, protože koneckonců tento návod je o spuštění programu při spuštění. Nejprve musíte povolit spuštění služby během spouštěcí sekvence:

[root@testvm1 ~]# systemctl enable hello.service 
Created symlink /etc/systemd/system/multi-user.target.wants/hello.service → /etc/systemd/system/hello.service.
[root@testvm1 ~]#

Všimněte si, že odkaz byl vytvořen v /etc/systemd/system/multi-user.target.wants adresář. Je to proto, že soubor servisní jednotky uvádí, že služba je "chcena" multi-user.target .

Restartujte a nezapomeňte sledovat datový proud během spouštěcí sekvence, abyste viděli zprávu „Ahoj světe“. Počkej... tys to neviděl? No, já taky ne. I když to šlo velmi rychle, viděl jsem zprávu systemd, že spouští hello.service .

Podívejte se na deník od posledního spuštění systému. Můžete použít less vyhledávací nástroj pageru k nalezení „Ahoj“ nebo „ahoj“. Prořezal jsem mnoho řádků dat, ale nechal jsem některé okolní záznamy v deníku, takže si můžete udělat představu o tom, jak záznamy týkající se vaší služby lokálně vypadají:

[root@testvm1 ~]# journalctl -b
<snip>
May 10 10:37:49 testvm1.both.org systemd[1]: Listening on SSSD Kerberos Cache Manager responder socket.
May 10 10:37:49 testvm1.both.org systemd[1]: Reached target Sockets.
May 10 10:37:49 testvm1.both.org systemd[1]: Reached target Basic System.
May 10 10:37:49 testvm1.both.org systemd[1]: Starting Modem Manager...
May 10 10:37:49 testvm1.both.org systemd[1]: Starting Network Manager...
May 10 10:37:49 testvm1.both.org systemd[1]: Starting Avahi mDNS/DNS-SD Stack...
May 10 10:37:49 testvm1.both.org systemd[1]: Condition check resulted in Secure Boot DBX (blacklist) updater being skipped.
May 10 10:37:49 testvm1.both.org systemd[1]: Starting My hello shell script...
May 10 10:37:49 testvm1.both.org systemd[1]: Starting IPv4 firewall with iptables...
May 10 10:37:49 testvm1.both.org systemd[1]: Started irqbalance daemon.
May 10 10:37:49 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=irqbalance comm="systemd" exe="/usr/lib/sy>"'
May 10 10:37:49 testvm1.both.org systemd[1]: Starting LSB: Init script for live image....
May 10 10:37:49 testvm1.both.org systemd[1]: Starting Hardware Monitoring Sensors...
<snip>
May 10 10:37:49 testvm1.both.org systemd[1]: Starting NTP client/server...
May 10 10:37:49 testvm1.both.org systemd[1]: Starting SYSV: Late init script for live image....
May 10 10:37:49 testvm1.both.org systemd[1]: Started SYSV: Late init script for live image..
May 10 10:37:49 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=livesys-late comm="systemd" exe="/usr/lib/>"'
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
May 10 10:37:49 testvm1.both.org hello.sh[842]: ######### Hello World! ########
May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
May 10 10:37:49 testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd>"'
May 10 10:37:49 testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/>
May 10 10:37:50 testvm1.both.org audit: BPF prog-id=28 op=LOAD
<snip>

Můžete vidět, že systemd spustil hello.service jednotka, která spustila hello.sh shell skript s výstupem zaznamenaným v deníku. Pokud byste jej mohli zachytit během spouštění, viděli byste také zprávu systemd, která oznamuje, že spouští skript, a další zprávu, která oznamuje, že služba byla úspěšná. Když se podíváte na první zprávu systemd v datovém toku výše, můžete vidět, že systemd spustil vaši službu velmi brzy po dosažení základního cíle systému.

Ale rád bych, aby se ta zpráva zobrazila i při spuštění. Existuje způsob, jak toho dosáhnout:Přidejte následující řádek do [Service] části hello.service soubor:

StandardOutput=journal+console

hello.service soubor nyní vypadá takto:

# Simple service unit file to use for testing 
# startup configurations with systemd.
# By David Both
# Licensed under GPL V2
#

[Unit]
Description=My hello shell script

[Service]
Type=oneshot
ExecStart=/usr/local/bin/hello.sh
StandardOutput=journal+console

[Install]
WantedBy=multi-user.target

Po přidání tohoto řádku restartujte systém a sledujte datový tok, jak se během procesu spouštění posouvá po displeji nahoru. Měli byste vidět zprávu v malé krabičce. Po dokončení spouštěcí sekvence si můžete prohlédnout žurnál posledního spuštění a najít položky pro vaši novou službu.

Změna sekvence

Nyní, když vaše služba funguje, můžete se podívat, kde ve spouštěcí sekvenci začíná, a experimentovat s její změnou. Je důležité si uvědomit, že záměrem systemd je spustit co nejvíce služeb a dalších typů jednotek paralelně v rámci každého z hlavních cílů:basic.target , multi-user.target a graphical.target . Měli jste právě vidět záznamy žurnálu pro poslední spuštění, které by mělo vypadat podobně jako můj žurnál ve výstupu výše.

Všimněte si, že systemd spustil vaši testovací službu brzy poté, co dosáhl cílového základního systému. To je to, co jste zadali v souboru servisní jednotky v WantedBy řádek, takže je to správně. Než cokoli změníte, uveďte obsah souboru /etc/systemd/system/multi-user.target.wants adresář a uvidíte symbolický (soft) odkaz na soubor servisní jednotky. [Install] část souboru servisní jednotky určuje, který cíl spustí službu, a spuštění systemctl enable hello.service příkaz vytvoří odkaz v příslušném adresáři "target want":

hello.service -> /etc/systemd/system/hello.service

Některé služby se musí spustit během basic.target a ostatní se nemusí spouštět, pokud systém nespouští graphical.target . Služba v tomto experimentu se nespustí v basic.target —předpokládejme, že jej ke spuštění nepotřebujete, dokud graphical.target . Změňte tedy WantedBy řádek:

WantedBy=graphical.target

Nezapomeňte vypnout hello.service a znovu jej povolte, abyste odstranili starý odkaz a přidali nový do graphical.targets.wants adresář. Všiml jsem si, že pokud zapomenu deaktivovat službu před změnou cíle, který ji chce, mohu spustit systemctl disable a odkazy budou odstraněny z obou "cílových" adresářů. Pak už jen potřebuji službu znovu povolit a restartovat.

Jedna starost se spouštěním služeb v graphical.target je to, pokud se hostitel zavede do multi-user.target , tato služba se nespustí automaticky. To může být to, co chcete, pokud služba vyžaduje desktopové rozhraní GUI, ale také to nemusí být to, co chcete.

Podívejte se na záznamy deníku pro graphical.target a multi-user.target pomocí -o short-monotonic možnost, která zobrazí sekundy po spuštění jádra s přesností na mikrosekundy:

[root@testvm1 ~]# journalctl -b -o short-monotonic

Některé výsledky pro multi-user.target :

[   17.264730] testvm1.both.org systemd[1]: Starting My hello shell script...
[   17.265561] testvm1.both.org systemd[1]: Starting IPv4 firewall with iptables...
<SNIP>
[   19.478468] testvm1.both.org systemd[1]: Starting LSB: Init script for live image....
[   19.507359] testvm1.both.org iptables.init[844]: iptables: Applying firewall rules: [  OK  ]
[   19.507835] testvm1.both.org hello.sh[843]: ###############################
[   19.507835] testvm1.both.org hello.sh[843]: ######### Hello World! ########
[   19.507835] testvm1.both.org hello.sh[843]: ###############################
<SNIP>
[   21.482481] testvm1.both.org systemd[1]: hello.service: Succeeded.
[   21.482550] testvm1.both.org smartd[856]: Opened configuration file /etc/smartmontools/smartd.conf
[   21.482605] testvm1.both.org systemd[1]: Finished My hello shell script.

A některé výsledky pro graphical.target :

[   19.436815] testvm1.both.org systemd[1]: Starting My hello shell script...
[   19.437070] testvm1.both.org systemd[1]: Starting IPv4 firewall with iptables...
<SNIP>
[   19.612614] testvm1.both.org hello.sh[841]: ###############################
[   19.612614] testvm1.both.org hello.sh[841]: ######### Hello World! ########
[   19.612614] testvm1.both.org hello.sh[841]: ###############################
[   19.629455] testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[   19.629569] testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[   19.629682] testvm1.both.org systemd[1]: hello.service: Succeeded.
[   19.629782] testvm1.both.org systemd[1]: Finished My hello shell script.

Navzdory tomu, že máte graphical.target "chci" v souboru jednotky, hello.service jednotka běží přibližně 19,5 nebo 19,6 sekundy po spuštění. Ale hello.service začíná asi 17,24 sekundy v multi-user.target a 19,43 sekundy v grafickém cíli.

Co to znamená? Podívejte se na /etc/systemd/system/default.target odkaz. Obsah tohoto souboru ukazuje, že systemd nejprve spustí výchozí cíl, graphical.target , který pak stáhne multi-user.target :

[root@testvm1 system]# cat default.target
#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target
Wants=display-manager.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target display-manager.service
AllowIsolate=yes
[root@testvm1 system]#

Zda spouští službu pomocí graphical.target nebo multi-user.target , hello.service jednotka běží přibližně za 19,5 nebo 19,6 sekundy po spuštění. Na základě toho a výsledků časopisu (zejména těch, které používají monotónní výstup), víte, že oba tyto cíle začínají paralelně. Podívejte se na další věc z výstupu deníku:

[   28.397330] testvm1.both.org systemd[1]: Reached target Multi-User System.
[   28.397431] testvm1.both.org systemd[1]: Reached target Graphical Interface.

Oba cíle končí téměř ve stejný čas. To je konzistentní, protože graphical.target stáhne multi-user.target a nemůže skončit, dokud multi.user target je dosaženo, tj. ukončeno. Ale  hello.service skončí mnohem dříve.

To vše znamená, že tyto dva cíle začínají téměř paralelně. Pokud prozkoumáte záznamy deníku, uvidíte různé cíle a služby z každého z těchto primárních cílů, které začínají většinou paralelně. Je jasné, že multi-user.target není nutné dokončit před graphical.target začíná. Pouhé použití těchto primárních cílů k sekvenčnímu spouštění proto nefunguje příliš dobře, i když může být užitečné pro zajištění toho, aby se jednotky spouštěly pouze tehdy, když jsou potřeba pro graphical.target .

Než budete pokračovat, vraťte zpět hello.service soubor jednotky na WantedBy=multi-user.target (pokud již není.)

Zajištění spuštění služby po spuštění sítě

Běžným problémem spouštěcí sekvence je zajištění, že se jednotka spustí poté, co je síť v provozu. Článek Freedesktop.org Spuštění služeb po zapnutí sítě říká, že neexistuje žádný skutečný konsenzus o tom, kdy je síť považována za „nahoru“. Článek však poskytuje tři možnosti a ta, která splňuje potřeby plně funkční sítě, je network-online.target . Mějte na paměti, že network.target se používá spíše při vypínání než při spouštění, takže vám nebude k ničemu, když se pokoušíte seřadit spouštění.

Před provedením jakýchkoli dalších změn se ujistěte, že si prohlédnete deník a ověříte, že hello.service jednotka se spustí mnohem dříve než síť. Můžete hledat network-online.target v deníku ke kontrole.

Vaše služba skutečně nevyžaduje síťovou službu, ale můžete ji použít jako avatar pro službu, která ji vyžaduje.

Protože nastavení WantedBy=graphical.target nezajišťuje, že služba bude spuštěna po spuštění sítě, potřebujete jiný způsob, jak zajistit, že tomu tak je. Fortunately, there is an easy way to do this. Add the following two lines to the [Unit] section of the hello.service unit file:

After=network-online.target                                                                             
Wants=network-online.target

Both of these entries are required to make this work. Reboot the host and look for the location of entries for your service in the journals:

[   26.083121] testvm1.both.org NetworkManager[842]: <info>  [1589227764.0293] device (enp0s3): Activation: successful, device activated.
[   26.083349] testvm1.both.org NetworkManager[842]: <info>  [1589227764.0301] manager: NetworkManager state is now CONNECTED_GLOBAL
[   26.085818] testvm1.both.org NetworkManager[842]: <info>  [1589227764.0331] manager: startup complete
[   26.089911] testvm1.both.org systemd[1]: Finished Network Manager Wait Online.
[   26.090254] testvm1.both.org systemd[1]: Reached target Network is Online.
[   26.090399] testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=NetworkManager-wait-online comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? termina>"'
[   26.091991] testvm1.both.org systemd[1]: Starting My hello shell script...
[   26.095864] testvm1.both.org sssd[be[implicit_files]][1007]: Starting up
[   26.290539] testvm1.both.org systemd[1]: Condition check resulted in Login and scanning of iSCSI devices being skipped.
[   26.291075] testvm1.both.org systemd[1]: Reached target Remote File Systems (Pre).
[   26.291154] testvm1.both.org systemd[1]: Reached target Remote File Systems.
[   26.292671] testvm1.both.org systemd[1]: Starting Notify NFS peers of a restart...
[   26.294897] testvm1.both.org systemd[1]: iscsi.service: Unit cannot be reloaded because it is inactive.
[   26.304682] testvm1.both.org hello.sh[1010]: ###############################
[   26.304682] testvm1.both.org hello.sh[1010]: ######### Hello World! ########
[   26.304682] testvm1.both.org hello.sh[1010]: ###############################
[   26.306569] testvm1.both.org audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[   26.306669] testvm1.both.org audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=hello comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
[   26.306772] testvm1.both.org systemd[1]: hello.service: Succeeded.
[   26.306862] testvm1.both.org systemd[1]: Finished My hello shell script.
[   26.584966] testvm1.both.org sm-notify[1011]: Version 2.4.3 starting

This confirms that the hello.service unit started after the network-online.target . This is exactly what you want. You may also have seen the "Hello World" message as it passed by during startup. Notice also that the timestamp is about six seconds later in the startup than it was before.

The best way to define the start sequence

This article explored Linux startup with systemd and unit files and journals in greater detail and discovered what happens when errors are introduced into the service file. As a sysadmin, I find that this type of experimentation helps me understand the behaviors of a program or service when it breaks, and breaking things intentionally is a good way to learn in a safe environment.

As the experiments in this article proved, just adding a service unit to either the multi-user.target or the graphical.target does not define its place in the start sequence. It merely determines whether a unit starts as part of a graphical environment or not. The reality is that the startup targets multi-user.target and graphical.target —and all of their Wants and Requires—start up pretty much in parallel. The best way to ensure that a unit starts in a specific order is to determine the unit it is dependent on and configure the new unit to "Want" and "After" the unit upon which it is dependent.

Resources

Na internetu je k dispozici velké množství informací o systemd, ale mnohé jsou stručné, tupé nebo dokonce zavádějící. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup.

  • Projekt Fedora má dobrého praktického průvodce systemd. Obsahuje téměř vše, co potřebujete vědět, abyste mohli nakonfigurovat, spravovat a udržovat počítač Fedora pomocí systemd.
  • Projekt Fedora má také dobrý cheat sheet, který křížově odkazuje na staré příkazy SystemV se srovnatelnými příkazy systemd.
  • For detailed technical information about systemd and the reasons for creating it, check out Freedesktop.org's description of systemd.
  • Pokročilejší systémové informace a tipy nabízí stránka Linux.com „More systemd fun“.

Existuje také řada hluboce technických článků pro správce systému Linux od Lennarta Poetteringa, návrháře a primárního vývojáře systemd. Tyto články byly napsány mezi dubnem 2010 a zářím 2011, ale nyní jsou stejně aktuální jako tehdy. Většina všeho dobrého, co bylo napsáno o systemd a jeho ekosystému, je založeno na těchto dokumentech.

  • Přehodnocení PID 1
  • systemd pro administrátory, část I
  • systemd pro administrátory, část II
  • systemd pro administrátory, část III
  • systemd pro administrátory, část IV
  • systemd pro administrátory, část V
  • systemd pro administrátory, část VI
  • systemd pro administrátory, část VII
  • systemd pro administrátory, část VIII
  • systemd pro administrátory, část IX
  • systemd pro administrátory, část X
  • systemd pro administrátory, část XI

Linux
  1. Použití nc pro přenos velkých souborů

  2. Jak použít Systemd k restartování služby, když je vypnutá?

  3. Systemd:Použití After a Requires

  1. Použití příkazu systemctl ke správě jednotek systemd

  2. Ansible Guide:Správa souborů pomocí Ansible

  3. přesměrovat protokoly služeb systemd do souboru

  1. Jak spravovat služby Systemd pomocí Systemctl v systému Linux

  2. Nahrazení rc.local v systemd systémech Linux

  3. Jak používat příkaz Systemctl ke správě služeb Systemd