Systemd, interaktivne skripte i tajmeri

Systemd, interaktivne skripte i tajmeri

Uvod

Prilikom razvoja za Linux javlja se zadatak kreiranja interaktivnih skripti koje se izvršavaju kada se sistem uključi ili isključi. U sistemu V to je bilo lako, ali sa systemd-om se prilagođava. Ali može imati svoje tajmere.

Zašto su nam potrebne mete?

Često se piše da cilj služi kao analog runlevel-a u sistemu V -init. U osnovi se ne slažem. Ima ih više i možete podijeliti pakete u grupe i, na primjer, jednom komandom pokrenuti grupu servisa i izvršiti dodatne radnje. Štaviše, nemaju hijerarhiju, već samo zavisnosti.

Primjer cilja kada je omogućen (pregled funkcija) s pokrenutom interaktivnom skriptom

Opis same mete:

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 cilj će se pokrenuti kada se pokrene multi-user.target i pozove installer.service. Međutim, može postojati nekoliko takvih usluga.

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

I na kraju, primjer skripte koja se izvršava:

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

Najvažnije je odabrati final.target - cilj do kojeg sistem treba da stigne pri pokretanju. Tokom procesa pokretanja, systemd će proći kroz zavisnosti i pokrenuti sve što mu je potrebno.
Postoje različiti načini za odabir final.target, za ovo sam koristio opciju loader.

Konačno lansiranje izgleda ovako:

  1. Pokreće se bootloader
  2. Bootloader započinje pokretanje firmvera prenošenjem parametra final.target
  3. Systemd počinje da pokreće sistem. Sekvencijalno ide na installer.target ili work.target iz basic.target kroz njihove zavisnosti (na primjer, multi-user.target). Potonji dovode sistem da radi u željenom režimu

Priprema firmvera za pokretanje

Prilikom kreiranja firmvera, uvijek se javlja zadatak vraćanja stanja sistema pri pokretanju i spremanja pri gašenju. Stanje znači konfiguracijske datoteke, dumpove baze podataka, postavke sučelja, itd.

Systemd paralelno pokreće procese u istom cilju. Postoje zavisnosti koje vam omogućavaju da odredite redoslijed pokretanja skripti.

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

  1. Sistem se pokreće
  2. Pokreće se usluga settings_restore.service koja provjerava prisutnost datoteke settings.txt u odjeljku podataka. Ako ga nema, onda se na njegovo mjesto postavlja referentna datoteka. Zatim se vraćaju sistemske postavke:
    • administratorska lozinka
    • ime domaćina,
    • vremenska zona
    • locale
    • Određuje da li se koriste svi mediji. Podrazumevano, veličina slike je mala - radi lakšeg kopiranja i snimanja na medij. Prilikom pokretanja provjerava da li ima još neiskorištenog prostora. Ako postoji, disk se ponovo particionira.
    • Generisanje mašinskog ID-a sa MAC adrese. Ovo je važno za dobijanje iste adrese putem DHCP-a
    • Mrežne postavke
    • Ograničava veličinu trupaca
    • Eksterni disk se priprema za rad (ako je odgovarajuća opcija omogućena i disk je nov)
  3. Pokreni postgresq
  4. Pokreće se usluga vraćanja. Potrebno je pripremiti sam zabbix i njegovu bazu podataka:
    • Provjerava da li već postoji zabbix baza podataka. Ako nije, kreira se iz inicijalizacijskih dumpova (uključeno uz zabbix)
    • kreira se lista vremenskih zona (potrebno za njihovo prikazivanje u web sučelju)
    • Trenutni IP je pronađen, prikazan je u izdanju (poziv za prijavu na konzolu)
  5. Pozivnica se mijenja - pojavljuje se fraza Spremni za rad
  6. Firmver je spreman za upotrebu

Servisni fajlovi su važni, oni su ti koji određuju redosled njihovog pokretanja

[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

Kao što vidite, instalirao sam zavisnosti da bi moja skripta prvo radila, a tek onda bi se mreža podigla i pokrenuo DBMS.

I drugi servis (zabbix priprema)

#!/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

Ovdje je malo komplikovanije.Pokretanje je također u multi-user.target, ali NAKON pokretanja postgresql DBMS-a i mog setting_restore. Ali PRIJE pokretanja zabbix usluga.

Tajmer servis za logorotaciju

Systemd može zamijeniti CRON. Ozbiljno. Štaviše, tačnost nije do minute, već do sekunde (šta ako je potrebno) Ili možete kreirati monoton tajmer koji se poziva po isteku vremena iz događaja.
Bio je to monotoni tajmer koji broji vrijeme od početka mašine koju sam napravio.
Ovo će zahtijevati 2 fajla
logrotateTimer.service - stvarni opis usluge:

[Unit]
Description=run logrotate

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

Jednostavno je - opis komande za pokretanje.
Druga datoteka logrotateTimer.timer je mjesto gdje rade tajmeri:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

šta je ovdje:

  • opis tajmera
  • Vrijeme prvog pokretanja, počevši od pokretanja sistema
  • period daljih lansiranja
  • Ovisnost o servisu tajmera. U stvari, ovo je niz koji čini tajmer

Interaktivna skripta prilikom gašenja i vaš cilj isključivanja

U drugom razvoju, morao sam da uradim složeniju verziju isključivanja mašine - kroz sopstvenu metu, kako bih izvršio mnoge radnje. Obično se preporučuje da kreirate jednokratnu uslugu sa opcijom RemainAfterExit, ali to vas sprečava da kreirate interaktivnu skriptu.

Ali činjenica je da se komande koje pokreće opcija ExecOnStop izvršavaju izvan TTY-ja! Lako je to provjeriti - zalijepite naredbu tty i sačuvajte njen rezultat.

Stoga sam implementirao gašenje kroz svoju metu. Ne tvrdim da sam 100% tačan, ali radi!
Kako je to urađeno (općenito):
Napravio sam cilj my_shutdown.target, koji nije zavisio ni od koga:
my_shutdown.target

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

Prilikom odlaska na ovu metu (preko systemctl izolacije my_shutdwn.target), pokrenula je uslugu my_shutdown.service, čiji je zadatak jednostavan - da izvrši skriptu 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 ove skripte izvodim potrebne radnje. Možete dodati mnogo skripti cilju radi fleksibilnosti i praktičnosti:

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

Bilješka. Korišćenje datoteka /tmp/reboot i /tmp/shutdown. Ne možete pozvati cilj sa parametrima. Moguća je samo usluga.

Ali koristim cilj da bih imao fleksibilnost u radu i zagarantovan redosled akcija.

Međutim, najzanimljivije je došlo kasnije. Mašinu je potrebno isključiti/ponovno pokrenuti. I postoje 2 opcije:

  • Zamijenite reboot, shutdown i druge komande (oni su i dalje simboličke veze za systemctl) sa svojom skriptom.Unutar skripte idite na my_shutdown.target. A skripte unutar cilja onda direktno pozivaju systemctl, na primjer, systemctl ponovno pokretanje
  • Jednostavnija opcija, ali mi se ne sviđa. U svim sučeljima, ne pozivajte shutdown/reboot/other, već direktno pozovite ciljni systemctl isolate my_shutdown.target

Odabrao sam prvu opciju. U systemd-u, ponovno pokretanje (poput isključenja) su simboličke veze za systemd.

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

Stoga ih možete zamijeniti vlastitim skriptama:
reboot

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

izvor: www.habr.com

Dodajte komentar