Systemd, interaktívne skripty a časovače

Systemd, interaktívne skripty a časovače

Úvod

Pri vývoji pre Linux vyvstáva úloha vytvárať interaktívne skripty, ktoré sa spustia pri zapnutí alebo vypnutí systému. V systéme V to bolo jednoduché, ale so systemd to robí úpravy. Ale môže mať svoje vlastné časovače.

Prečo potrebujeme ciele?

Často sa píše, že target slúži ako analóg úrovne behu v systéme V -init. zásadne nesúhlasím. Je ich viac a môžete si balíčky rozdeliť do skupín a napríklad jedným príkazom spustiť skupinu služieb a vykonať ďalšie akcie. Navyše nemajú žiadnu hierarchiu, iba závislosti.

Príklad cieľa, keď je povolený (prehľad funkcií) so spusteným interaktívnym skriptom

Popis samotného cieľa:

cat installer.target
[Unit]
Description=My installer
Requires=multi-user.target 
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target 
AllowIsolate=yes
Wants=installer.service

Tento cieľ sa spustí, keď sa spustí multi-user.target a zavolá installer.service. Takýchto služieb však môže byť viacero.

cat installer.service
[Unit]
# описание
Description=installer interactive dialog

[Service]
# Запустить один раз, когда остальное будет запущенно
Type=idle
# Команда запуска - вызов скрипта
ExecStart=/usr/bin/installer.sh
# Интерактивное взаимодействие с пользователем через tty3
StandardInput=tty
TTYPath=/dev/tty3
TTYReset=yes
TTYVHangup=yes

[Install]
WantedBy=installer.target

A nakoniec príklad spúšťaného skriptu:

#!/bin/bash
# Переходим в tty3
chvt 3
echo "Install, y/n ?"
read user_answer

Najdôležitejšie je vybrať final.target – cieľ, do ktorého má systém doraziť pri štarte. Počas procesu spustenia systemd prejde závislosti a spustí všetko, čo potrebuje.
Final.target sa dá vybrať rôznymi spôsobmi, ja som na to použil možnosť loader.

Konečné spustenie vyzerá takto:

  1. Spustí sa bootloader
  2. Bootloader spustí spúšťanie firmvéru odovzdaním parametra final.target
  3. Systemd začne spúšťať systém. Postupne prejde na installer.target alebo work.target z basic.target cez ich závislosti (napríklad multi-user.target). Ten privedie systém do práce v požadovanom režime

Príprava firmvéru na spustenie

Pri vytváraní firmvéru vždy vzniká úloha obnoviť stav systému pri štarte a uložiť ho pri vypnutí. Stav znamená konfiguračné súbory, výpisy databázy, nastavenia rozhrania atď.

Systemd spúšťa procesy v rovnakom cieli paralelne. Existujú závislosti, ktoré vám umožňujú určiť postupnosť spúšťania skriptov.

Ako to funguje v mojom projekte ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Systém sa spustí
  2. Spustí sa služba settings_restore.service, ktorá skontroluje prítomnosť súboru settings.txt v dátovej časti. Ak tam nie je, potom sa na jeho miesto umiestni referenčný súbor. Ďalej sa obnovia systémové nastavenia:
    • heslo správcu
    • meno hosťa,
    • časové pásmo
    • locale
    • Určuje, či sa používajú všetky médiá. V predvolenom nastavení je veľkosť obrázka malá - pre jednoduché kopírovanie a nahrávanie na médiá. Pri spustení skontroluje, či je ešte nevyužité miesto. Ak existuje, disk sa znova rozdelí.
    • Generovanie strojového ID z MAC adresy. To je dôležité pre získanie rovnakej adresy cez DHCP
    • Nastavenia siete
    • Obmedzuje veľkosť protokolov
    • Externý disk sa pripravuje na prácu (ak je povolená príslušná možnosť a disk je nový)
  3. Začať postgresq
  4. Spustí sa služba obnovenia. Je potrebné pripraviť samotný zabbix a jeho databázu:
    • Skontroluje, či už existuje databáza zabbix. Ak nie, vytvorí sa z inicializačných výpisov (súčasť zabbixu)
    • vytvorí sa zoznam časových pásiem (potrebné na ich zobrazenie vo webovom rozhraní)
    • Aktuálna IP je nájdená, zobrazí sa v čísle (výzva na prihlásenie do konzoly)
  5. Pozvánka sa zmení – zobrazí sa fráza Ready to work
  6. Firmvér je pripravený na použitie

Servisné súbory sú dôležité, sú to tie, ktoré určujú postupnosť ich spúšťania

[Unit]
Description=restore system settings
Before=network.service prepare.service postgresql.service systemd-networkd.service systemd-resolved.service

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

[Install]
WantedBy=multi-user.target

Ako vidíte, nainštaloval som závislosti tak, aby mi najskôr fungoval skript a až potom sa rozbehla sieť a spustil sa DBMS.

A druhá služba (príprava na zabbix)

#!/bin/sh
[Unit]
Description=monitor prepare system
After=postgresql.service settings_restore.service
Before=zabbix-server.service zabbix-agent.service

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

[Install]
WantedBy=multi-user.target

Tu je to trochu komplikovanejšie. Spustenie je tiež v multi-user.target, ale PO spustení postgresql DBMS a mojom nastavení_obnovenia. Ale PRED spustením služieb zabbix.

Služba časovača pre logrotate

Systemd môže nahradiť CRON. vážne. Navyše presnosť nie je na minútu, ale na sekundu (čo ak je to potrebné) Alebo si môžete vytvoriť monotónny časovač, ktorý sa vyvolá časovým limitom z udalosti.
Bol to monotónny časovač, ktorý počíta čas od spustenia stroja, ktorý som vytvoril.
To bude vyžadovať 2 súbory
logrotateTimer.service - skutočný popis služby:

[Unit]
Description=run logrotate

[Service]
ExecStart=logrotate /etc/logrotate.conf
TimeoutSec=300

Je to jednoduché - popis príkazu na spustenie.
V druhom súbore logrotateTimer.timer fungujú časovače:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Čo je tu:

  • popis časovača
  • Čas prvého spustenia, počnúc spustením systému
  • obdobie ďalších spustení
  • Závislosť na službe časovača V skutočnosti je to reťazec, ktorý vytvára časovač

Interaktívny skript pri vypínaní a váš cieľ vypnutia

V inom vývoji som musel urobiť zložitejšiu verziu vypnutia stroja - prostredníctvom vlastného cieľa, aby som mohol vykonať veľa akcií. Zvyčajne sa odporúča vytvoriť jednorazovú službu s možnosťou RemainAfterExit, ale to vám bráni vytvoriť interaktívny skript.

Faktom však je, že príkazy spustené voľbou ExecOnStop sa vykonávajú mimo TTY! Je to jednoduché skontrolovať - ​​vložte príkaz tty a uložte jeho výstup.

Preto som vypnutie implementoval cez môj cieľ. Netvrdím, že mám 100% pravdu, ale funguje to!
Ako to bolo urobené (vo všeobecnosti):
Vytvoril som cieľ my_shutdown.target, ktorý nezávisel od nikoho:
my_shutdown.target

[Unit]
Description=my shutdown
AllowIsolate=yes
Wants=my_shutdown.service 

Pri prechode na tento cieľ (prostredníctvom systemctl izolovať my_shutdwn.target) spustil službu my_shutdown.service, ktorej úloha je jednoduchá - spustiť skript my_shutdown.sh:

[Unit]
Description=MY shutdown

[Service]
Type=oneshot
ExecStart=/usr/bin/my_shutdown.sh
StandardInput=tty
TTYPath=/dev/tty3
TTYReset=yes
TTYVHangup=yes

WantedBy=my_shutdown.target

  • V tomto skripte vykonávam potrebné akcie. Pre flexibilitu a pohodlie môžete do cieľa pridať mnoho skriptov:

my_shutdown.sh

#!/bin/bash --login
if [ -f /tmp/reboot ];then
    command="systemctl reboot"
elif [ -f /tmp/shutdown ]; then
    command="systemctl poweroff"
fi
#Вот здесь нужные команды
#Например, cp /home/user/data.txt /storage/user/
    $command

Poznámka. Pomocou súborov /tmp/reboot a /tmp/shutdown. Nemôžete volať cieľ s parametrami. Možný je len servis.

Ale používam cieľ, aby som mal flexibilitu v práci a zaručený poriadok akcií.

To najzaujímavejšie však prišlo neskôr. Stroj je potrebné vypnúť/reštartovať. A sú 2 možnosti:

  • Nahraďte príkazy reboot, shutdown a ďalšie (stále sú to symbolické odkazy na systemctl) svojim skriptom. Vo vnútri skriptu prejdite na my_shutdown.target. A skripty v cieli potom volajú priamo systemctl, napríklad systemctl reboot
  • Jednoduchšia možnosť, ale nepáči sa mi. Vo všetkých rozhraniach nevolajte shutdown/reboot/other, ale priamo volajte cieľový systemctl isolate my_shutdown.target

Vybral som si prvú možnosť. V systemd, reštart (ako vypnutie) sú symbolické odkazy na systemd.

ls -l /sbin/poweroff 
lrwxrwxrwx 1 root root 14 сен 30 18:23 /sbin/poweroff -> /bin/systemctl

Preto ich môžete nahradiť vlastnými skriptami:
reštart

#!/bin/sh
    touch /tmp/reboot
    sudo systemctl isolate my_shutdown.target
fi

Zdroj: hab.com

Pridať komentár