Systemd, interaktivni skripti in časovniki

Systemd, interaktivni skripti in časovniki

Uvod

Pri razvoju pod linuxom javljaju se zadatci stvaranja interaktivnih skripti koje se izvršavaju prilikom uključivanja ili isključivanja sustava. U system V to se lako radilo, ali systemd unosi promjene. No, on ima svoje tajmere.

Zašto su potrebni targeti

Često se tvrdi da targeti služe kao analog runlevel-a u system V -init. U temelju se ne slažem. Ima ih više i pakete se može razdvajati u grupe i, na primjer, pokretati skupinu servisa jednim naredbom, izvoditi dodatne radnje. Osim toga, nemaju hijerarhiju, samo zavisnosti.

Primjer targeta prilikom uključivanja (pregled mogućnosti) s pokretanjem interaktivne skripte

Opis samog targeta:

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

Ovaj target će se pokrenuti kada bude pokrenut multi-user.target i pokrenut će installer.service. Pri tome može postojati više takvih servisa.

cat installer.service
[Unit]
# opis
Description=installer interactive dialog

[Service]
# Pokrenuti jednom, kada sve ostalo bude pokrenuto
Type=idle
# Komanda za pokretanje - poziv skripte
ExecStart=\/usr\/bin\/installer.sh
# Interaktivna interakcija s korisnikom putem tty3
StandardInput=tty
TTYPath=\/dev\/tty3
TTYReset=yes
TTYVHangup=yes

[Install]
WantedBy=installer.target

I konačno, primjer izvršene skripte:

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

Najvažnije je odabrati final.target - target kojem sustav treba pristupiti pri pokretanju. Tijekom pokretanja systemd će proći kroz zavisnosti i pokrenuti sve što je potrebno.
Odabir final.target može se obaviti na različite načine, ja sam koristio opciju učitavača.

Završno pokretanje izgleda ovako:

  1. Pokreće se učitavač
  2. Učitavač počinje pokretati firmver, proslijeđujući parametar final.target
  3. Systemd počinje pokretati sustav. Postupno ide do installer.target ili work.target od basic.target preko njihovih zavisnosti (na primjer, multi-user.target). Potonji dovode sustav u rad u odgovarajućem režimu

Priprema firmvera za pokretanje

Pri stvaranju firmvera uvijek se javlja zadatak vraćanja stanja sustava pri pokretanju i njegovog očuvanja pri isključivanju. Pod stanjem podrazumijevaju se konfiguracijske datoteke, dumpovi baza podataka, postavke sučelja itd.

Systemd pokreće procese u jednom targetu paralelno. Postoje zavisnosti koje omogućuju određivanje reda pokretanja skripti.

Kako to radi u mom projektu ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Sustav se pokreće
  2. Zagon sevanja settings_restore.service. Preverja prisotnost datoteke settings.txt v razdelku s podatki. Če je ni, se namesto nje postavi referenčna datoteka. Nato sledi obnova sistemskih nastavitev:
    • administratorska gesla
    • hostname,
    • časovni pas
    • lokal
    • Določitev, ali se celoten nosilec uporablja. Privzeto je velikost slike majhna - za enostavno kopiranje in zapisovanje na nosilec. Ob zagonu se preveri, ali je še neizkoriščen prostor. Če je, se disk ponovno razdeli.
    • Generiranje machine-id iz MAC naslov. To je pomembno za pridobitev istega naslova preko DHCP.
    • Nastavitve omrežja
    • Omejuje se velikost logov
    • Pripravlja se zunanji disk (če je ta možnost omogočena in je disk nov)
  3. Zagon postgresq
  4. zagon sevanja restore. Potreben je za pripravo zabbixa in njegove baze podatkov:
    • Preverja se, ali že obstaja baza podatkov zabbix. Če ne, se ustvari iz inicializacijskih dumpov (te pridejo v paket z zabbixom)
    • Ustvarja se seznam časovnih pasov (potreben za njihovo prikazovanje v spletnem vmesniku)
    • Najde se trenutni IP, ki se izpiše v issue (povabilo za vstop v konzolo)
  5. Spremeni se povabilo - pojavi se fraza Ready to work
  6. Firme je pripravljena za delo

Pomembni so datoteke storitev, prav oni določajo zaporedje njihovega zagona

[Unit]
Description=obnovi sistemske nastavitve
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

Kot je vidno, sem postavil odvisnosti, da se najprej izvede moja skripta, šele nato se dvigne omrežje in zažene SGBD.

In druga storitev (priprava zabbixa)

#!/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 nekoliko bolj zapleteno. Zagon je prav tako v multi-user.target, vendar POZNEJE zagonu SGBD postgresq in mojega setting_restore. Ampak PRED zagonu storitev zabbix.

Storitev s časovnikom za logrotate

Systemd lahko nadomesti CRON. Resno. Poleg tega je natančnost ne do minute, temveč do sekunde (morda bo to potrebno). Lahko pa ustvarite monoton timer, ki se odziva na časovno omejitev dogodka.
Natančno monoton timer, ki šteje čas od zagona naprave, sem ustvaril.
Za to bosta potrebna 2 datoteka
logrotateTimer.service - opis storitve:

[Unit]
Description=izvedi logrotate

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

Vse je preprosto - opis ukaza za zagon.
Druga datoteka logrotateTimer.timer - ta pa določa delovanje timerjev:

[Unit]
Description=Izvedi logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Kaj je tukaj:

  • opis timerja
  • Čas prvega zagona, začenši z nalaganjem sistemov
  • obdobje nadaljnjih zagonov
  • Odvisnost od storitve timerjev. Dejstvo je, da ta vrstica ustvari timer

Interaktivni skript ob izklopu in njegova ciljno usmerjena izklopna točka

V drugi različici sem moral ustvariti bolj zapleteno različico izklopa naprave — preko lastne ciljne točke, da izvede več dejanj. Običajno se priporoča ustvarjanje usluge oneshot z možnostjo RemainAfterExit, toda to ne omogoča ustvarjanje interaktivnega skripta.

In dejstvo je, da se ukazi, ki jih sproži možnost ExecOnStop, izvajajo zunaj TTY! Preverite preprosto — vstavite ukaz tty in shranite njegov izhod.

Zato sem izpeljal izklop preko svoje ciljne točke. Ne trdim za 100% pravilnost, toda deluje!
Kako je bilo to izvedeno (na splošno):
Ustvaril sem ciljno točko my_shutdown.target, ki ni bila od nikogar odvisna:
my_shutdown.target

[Enota]
Opis=my shutdown
Dovoli izolacijo=yes
Želi=my_shutdown.service 

Ko preide v to ciljno točko (preko systemctl isolate my_shutdown.target), zažene storitev my_shutdown.service, katere naloga je preprosta — izvesti skript my_shutdown.sh:

[Enota]
Opis=MY shutdown

[Storitev]
Tip=oneshot
ExecStart=\/usr\/bin\/my_shutdown.sh
StandardInput=tty
TTYPath=\/dev\/tty3
TTYReset=yes
TTYVHangup=yes

WantedBy=my_shutdown.target

  • Znotraj tega skripta izvajam potrebna dejanja. V ciljno točko lahko dodam več skriptov za fleksibilnost in udobje:

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

Opomba. Uporaba datotek \/tmp\/reboot in \/tmp\/shutdown. Ciljne točke ni mogoče poklicati s parametri. Lahko samo storitev.

Toda uporabljam ciljno točko, da imam fleksibilnost pri delu in zagotovljen vrstni red izvajanja dejanj.

Vendar pa, najbolj zanimivo je bilo nato. Napravo je treba izklopiti\/ponovno zagnati. In tukaj sta dva načina:

  • Zamenjati ukaze reboot, shutdown in druge (ti so vseeno simbolne povezave na systemctl) s svojim skriptom. Znotraj skripta — prehod v my_shutdown.target. Skripti znotraj ciljne točke nato neposredno kličemo systemctl, na primer, systemctl reboot
  • Bolj preprosta, toda meni manj všečna izbira. V vseh vmesnikih poklicati ne shutdown\/reboot\/druge, temveč neposredno poklicati ciljno točko systemctl isolate my_shutdown.target

Izbral sem prvo izbiro. V systemd je reboot (kot tudi poweroff) simbolna povezava na systemd.

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

Zato jih lahko zamenjamo s svojimi skripti:
reboot

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

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster