Systemd, interaktiivsed skriptid ja taimerid

Systemd, interaktiivsed skriptid ja taimerid

Sissejuhatus

Linuxi arendamisel tekivad interaktiivsete skriptide loomise ülesanded, mis täidetakse süsteemi käivitamisel või väljalülitamisel. System V-s oli see lihtne, kuid systemd toob muudatusi. Kuid sellel on omad taimerid.

Miks on vajalikud targetid

Sageli öeldakse, et targetid on analoogid runlevel'ile system V -init. Olen täielikult vastu. Neid on rohkem ja pakette saab jagada gruppidesse ning näiteks käivitada ühte teenuste gruppi ühe käsuga, teostada täiendavaid toiminguid. Samuti pole neil hierarhiat, ainult sõltuvused.

Näide targetist käivitamisel (ülevaade võimalustest) koos interaktiivse skripti käivitamisega

Kirjeldus targetist:

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

See target käivitub, kui multi-user.target on käivitatud ja kutsub esile installer.service'i. Selliseid teenuseid võib olla mitu.

cat installer.service
[Unit]
# kirjeldus
Description=installer interaktiivne dialoog

[Service]
# Käivita üks kord, kui ülejäänud on käivitatud
Type=idle
# Käivitamise käsk - skripti kutse
ExecStart=/usr/bin/installer.sh
# Interaktiivne suhtlemine kasutajaga läbi tty3
StandardInput=tty
TTYPath=/dev/tty3
TTYReset=yes
TTYVHangup=yes

[Install]
WantedBy=installer.target

Ja lõpuks, näide teostatavast skriptist:

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

Kõige olulisem on valida final.target - target, kuhu süsteem peab käivitatuna jõudma. Käivitusprotsessi käigus läbib systemd sõltuvused ja käivitab kõik vajalikud komponendid.
Final.target'i valimiseks on erinevaid viise, ma kasutasin selleks laadijavalikut.

Lõppkäivitamine näeb välja järgmine:

  1. Käivitub laadija
  2. Laadija alustab püsivara käivitamist, edastades parameetri final.target
  3. Systemd alustab süsteemi käivitamist. Järkjärgult liigub see installer.target'i või work.target'i suunas basic.target'i kaudu nende sõltuvuste kaudu (näiteks multi-user.target). Viimased viivad süsteemi soovitud režiimi.

Püsivara ettevalmistamine käivitamiseks

Püsivara loomisel tekib alati ülesanne taastada süsteemi seisund käivitamisel ja säilitada see väljalülitamise ajal. Seisund tähendab konfigureerimisfaile, andmebaasi dump'e, liidesteseadeid jne.

Systemd käivitab protsesse ühes targetis paralleelselt. On sõltuvusi, mis määravad skriptide käivitamise järjestuse.

Kuidas see minu projektis töötab ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Süsteem käivitub
  2. Käivitub teenus settings_restore.service. See kontrollib, kas andmeosa kaustas on olemas fail settings.txt. Kui seda ei ole, asendatakse see malli failiga. Edasi toimub süsteemi seadete taastamine:
    • administraatori parool
    • hostname,
    • ajavöönd
    • locale
    • Määratakse, kas kogu andmekandja on kasutuses. Vaikimisi on kujutise suurus väike — mugavuseks kopeerimise ja kirjutamise jaoks andmekandjale. Käivitamisel kontrollitakse, kas on veel kasutamata ruumi. Kui on, tuuakse ketas üle.
    • Masina ID genereerimine MAC-aadressist. See on oluline, et saada DHCP kaudu sama aadress.
    • Võrgu seaded
    • Logide suurus on piiratud
    • Valmis välise ketta ettevalmistamiseks (kui vastav valik on sisse lülitatud ja ketas on uus)
  3. Käivitub postgresq
  4. Käivitub teenus restore. See on vajalik zabbix'i ja selle andmebaasi ettevalmistamiseks:
    • Kontrollitakse, kas zabbix'i andmebaas on juba olemas. Kui ei, siis luuakse see initsialiseerimistestide põhjal (väljapakutud zabbixiga)
    • Luuakse ajavööndite nimekiri (on vajalik nende kuvamiseks veebiliideses)
    • Otsitakse praegune IP, see kuvatakse issue's (kutse konsooli sisselogimiseks)
  5. Muudetakse kutset — ilmub fraas Ready to work
  6. Seade on töötamiseks valmis

Teenuste failid on olulised, need määravad nende käivitamise järjekorra

[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

Kuna näha, määrasin sõltuvused, et minu skript töötaks esmalt, ja alles siis tõuseks võrk ja käivituks DBMS.

Ja teine teenus (zabbix'i ettevalmistus)

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

Siin on veidi keerulisem. Käivitamine on samuti multi-user.target-is, aga PEALE DBMS postgresql'i ja minu setting_restore'i käivitamist. Kuid ENNE zabbix'i teenuste käivitamist.

Teenuse taimer logrotate'i jaoks

Systemd võib asendada CRONi. Tõsiselt. Ja täpsus on mitte ühe minuti, vaid sekundi täpsusega (äkki läheb vaja). Võib luua monotoonse taimeri, mis kutsutakse välja sündmuse ajavööndist.
Just sellise monotoonse taimeri, mis loendab aega masina käivitamisest, ma lõin.
Selleks on vajalikud 2 faili
logrotateTimer.service — teenuse kirjelduse fail:

[Unit]
Description=run logrotate

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

Kõik on lihtne — käivitamisjärgse käsu kirjeldus.
Teine fail logrotateTimer.timer — see määrab taimerite töö:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Mis siin on:

  • aja arvestus
  • Esimese käivitusaja arvutamine alates süsteemi käivitamisest
  • järgmiste käivituste periood
  • Sõltuvus taimeri teenusest. Tegelikult on see rida, mis kutsub käivitama taimerit

Interaktiivne skript väljalülitamisel ja teie väljalülitus sihtmärk

Teises arenduses pidi tegema keerukama mootori väljalülitamise variandi — läbi iseseisva sihtmärgi, et täita mitmeid toiminguid. Tavaliselt soovitatakse luua oneshot teenus koos valikuga RemainAfterExit, kuid see ei võimalda luua interaktiivset skripti.

Probleem on selles, et ExecOnStop valiku kaudu käivitatavad käsud töötavad väljaspool TTY-d! Kontrollimine on lihtne — sisestage käsk tty ja salvestage selle väljund.

Seetõttu tegin väljalülitamise läbi oma sihtmärgi. 100% täpsuse osas ei saa ma lubada, kuid see töötab!
Kuidas see üldiselt tehti:
Loodud sihtmärk my_shutdown.target, mis ei sõltunud kellestki:
my_shutdown.target

[Unit]
Description=Minu väljalülitus
AllowIsolate=yes
Wants=my_shutdown.service 

Sellele sihtmärgile minnes (kasutades systemctl isolate my_shutdown.target), käivitas see teenuse my_shutdown.service, mille ülesanne oli lihtne — käivitada skript my_shutdown.sh:

[Unit]
Description=MINU väljalülitus

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

WantedBy=my_shutdown.target

  • Selle skripti sees täidan vajalikud toimingud. Sihtmärki saab lisada mitmeid skripte, et saavutada paindlikkus ja mugavus:

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

Märkus. Failide kasutamine \/tmp\/reboot ja \/tmp\/shutdown. Sihtmärki ei saa kutsuda parameetritega. Saab ainult teenust.

Kuid ma kasutan sihtmärki, et omada paindlikkust töös ja tagada toimingute järjekord.

Kuid kõige huvitavam tuli hiljem. Masin tuleb ju välja lülitada\/taaskäivitada. Ja siin on kaks varianti:

  • Asendada käsud reboot, shutdown ja muud (need on ikkagi symlinkid systemctl-ile) oma skriptiga. Skripti sees — üleminek my_shutdown.target. Ja skriptid sees sihtmärgis kutsuvad siis otse systemctl, näiteks systemctl reboot.
  • Lihtsam, kuid mulle ei meeldi variant. Kõigis liideses kutsuda mitte shutdown\/reboot\/muud, vaid otse kutse sihtmärgile systemctl isolate my_shutdown.target.

Valisin esimese variandi. Systemd-s on reboot (nagu ka poweroff) sümlinkid systemd-le.

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

Seega, neid saab asendada oma skriptidega:
taaskäivita

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

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster