Systemd, interaktívne skripty a časovače

Systemd, interaktívne skripty a časovače

Úvod

Pri vývoji pod linuxom sa objavujú úlohy vytvárania interaktívnych skriptov, ktoré sa vykonávajú pri zapnutí alebo vypnutí systému. V system V to bolo jednoduché, ale s systemd to prináša úpravy. Na druhej strane, to má svoje časovače.

Na čo sú potrebné ciele

Často píšu, že ciele slúžia ako ekvivalent runlevel v system V – init. S tým sa zásadne nesúhlasím. Je ich viac a môžete rozdeľovať balíky podľa skupín a napríklad spustiť jednou príkazom skupinu služieb, vykonať ďalšie akcie. Okrem toho nemajú hierarchiu, iba závislosti.

Príklad cieľa pri zapnutí (prehľad možností) so spustením interaktívneho skriptu

Popis samotného cieľa:

cat installer.target
[Unit]
Description=Môj inštalátor
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ď bude spustený multi-user.target a vyvolá installer.service. Takýchto služieb môže byť pritom niekoľko.

cat installer.service
[Unit]
# popis
Description=interaktívny dialóg inštalátora

[Service]
# Spustiť raz, keď sa ostatné spustia
Type=idle
# Príkaz na spustenie - vyvolanie skriptu
ExecStart=\/usr\/bin\/installer.sh
# Interaktívna interakcia s užívateľom cez tty3
StandardInput=tty
TTYPath=\/dev\/tty3
TTYReset=yes
TTYVHangup=yes

[Install]
WantedBy=installer.target

A nakoniec, príklad vykonávaného skriptu:

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

Najdôležitejšie je vybrať final.target - cieľ, ku ktorému sa systém má pri spustení priblížiť. Počas spúšťania systemd prejde závislosťami a spustí všetko potrebné.
Final.target je možné vybrať rôznymi spôsobmi, ja som na to použil možnosť bootloadera.

Konečné spustenie vyzerá takto:

  1. Spustí sa bootloader
  2. Bootloader začína spúšťať firmware, prenášajúc parameter final.target
  3. Systemd začína spúšťať systém. Postupne prechádza k installer.target alebo work.target od basic.target cez ich závislosti (napríklad multi-user.target). Posledné privádzajú systém do prevádzky v požadovanom režime.

Príprava firmvéru na spustenie

Pri vytváraní firmvérov sa vždy objavuje úloha obnovy stavu systému pri štarte a jeho uchovania pri vypnutí. Pod stavom sa rozumejú konfiguračné súbory, dumpy databáz, nastavenia rozhraní a pod.

Systemd spúšťa procesy v jednom cieli súbežne. Existujú závislosti, ktoré umožňujú určiť poradové spúšťanie skriptov.

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

  1. Systém sa spúšťa
  2. Služba settings_restore.service sa spustí. Skontroluje prítomnosť súboru settings.txt v sekcii s dátami. Ak tam nie je, nahradí ho referenčným súborom. Následne prebieha obnova nastavení systému:
    • admin hesla
    • hostname,
    • časového pásma
    • lokalizácie
    • Určenie, či je celý spôsob využívaný. Predvolene je veľkosť obrazu malá — pre pohodlie kopírovania a zápisu na zariadenie. Pri spustení sa kontroluje, či je ešte nevyužité miesto. Ak áno, disk sa znova rozdelí.
    • Generovanie machine-id z MAC adresy. To je dôležité pre získanie stálej adresy cez DHCP.
    • Nastavenia siete
    • Obmedzenie veľkosti logov
    • Pripravuje sa externý disk (ak je povolená príslušná možnosť a disk je nový)
  3. Spustenie postgresq
  4. služba restore sa spúšťa. Táto služba je potrebná na prípravu samotného zabbixu a jeho databázy:
    • Kontroluje sa, či už existuje databáza zabbix. Ak nie, vytvorí sa z inicializačných dumpov (tie sú dodávané s zabbixom)
    • vytvorí sa zoznam časových pásiem (dôležité na ich zobrazenie vo webovom rozhraní)
    • Nájde sa aktuálny IP, ktorý sa zobrazuje v pozvaní (výzva na prihlásenie do konzoly)
  5. Pozvánka sa mení — objaví sa fráza Ready to work
  6. Firmware je pripravené na prácu

Dôležité sú súbory služieb, práve tie určujú poradie ich spustenia

[Unit]
Description=obnovenie systémových nastavení
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 vidno, nastavil som závislosti, aby prvý môj skript bol vykonaný, a až potom sa spustila sieť a databáza.

A druhá služba (príprava zabbixu)

#!/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 zložitejšie. Spustenie tiež v multi-user.target, ale PO spustení databázy postgresql a môjho setting_restore. Ale PRED spustením služieb zabbix.

Služba s časovačom pre logrotate

Systemd môže nahradiť CRON. Naozaj. Časová presnosť nie je len na minútu, ale na sekundu (pre prípad, že by bola potrebná). Môže sa tiež vytvoriť monotónny časovač, ktorý sa volá na základe timeoutu od udalosti.
Práve monotónny časovač, ktorý meria čas od spustenia stroja, som vytvoril.
Na to budú potrebné 2 súbory
logrotateTimer.service — propriálne popis služby:

[Unit]
Description=spustiť logrotate

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

Je to jednoduché — popis príkazu na spustenie.
Druhý súbor logrotateTimer.timer — ten určuje prácu časovačov:

[Unit]
Description=Spustiť logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Čo je tu:

  • Opis časova
  • Čas prvog pokretanja, počevši od učitavanja sistema
  • Period narednih pokretanja
  • Zavisnost od usluge tajmera. U suštini, ovo je linija koja čini tajmer

Interaktivni skript prilikom gašenja i vaša ciljana gašenja

U drugom razvoju morao sam napraviti složeniju verziju gašenja mašine — kroz svoju metu, kako bih izvršio više radnji. Obično se preporučuje da se kreira usluga oneshot sa opcijom RemainAfterExit, ali to ne omogućava kreiranje interaktivnog skripta.

Problem je u tome što se komande pokrenute pomoću opcije ExecOnStop izvršavaju van TTY! Proverite jednostavno — umetnite komandu tty i sačuvajte njen izlaz.

Stoga sam implementirao gašenje kroz svoju metu. Ne tvrdim da je 100% ispravno, ali to funkcioniše!
Kako se to radilo (u opštim crtama):
Kreirao sam metu my_shutdown.target, koja nije zavisila ni od koga:
my_shutdown.target

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

Pri prelasku u ovu metu (kroz systemctl isolate my_shutdown.target), pokrenuo je uslugu my_shutdown.service, čija je zadaća jednostavna — izvršiti 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

  • Unutar ovog skripta izvršavam potrebne radnje. Možete dodati mnogo skripti u metu za fleksibilnost i praktičnost:

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

Napomena. Korišćenje datoteka \/tmp\/reboot i \/tmp\/shutdown. Nije moguće pozvati metu sa parametrima. Moguće je samo uslugu.

Ali koristim metu, kako bih imao fleksibilnost u radu i garantovan redosled izvršavanja radnji.

Međutim, najzanimljivije je bilo kasnije. Mašinu treba isključiti/ponovo pokrenuti. I ovde postoje 2 opcije:

  • Zameniti komande reboot, shutdown i ostale (one su ionako simlinkovi na systemctl) svojim skriptom. Unutar skripta — prelazak u my_shutdown.target. A skripti unutar mete nakon toga direktno pozivaju systemctl, na primer, systemctl reboot
  • Jednostavnija, ali mi se ne sviđa, opcija. U svim interfejsima pozivati ne shutdown/reboot/ostale, već direktno pozivati metu systemctl isolate my_shutdown.target

Izabrao sam prvu opciju. U systemd reboot (kao i poweroff) su simlinkovi na systemd.

ls -l \/sbin\/poweroff 
lrwxrwxrwx 1 root root 14 sep 30 18:23 \/sbin\/poweroff -> \/bin\/systemctl

Zato ih možete zameniti svojim skriptima:
reboot

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

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster