
Sissejuhatus
Linuxi arendamisel tekivad interaktiivsete skriptide loomise ülesanded, mis viiakse ellu süsteemi sisse- ja väljalülitamise ajal. System V-s oli see lihtne, kuid systemd toob muudatusi. Küll aga suudab see hallata oma taimerite seadistusi.
Miks on need target'id vajalikud?
Tihti väidetakse, et target'id on analoogid runlevel'itele system V -init-s. Sellega ei nõustu ma. Need on rohkem ja pakette saab jagada gruppidesse ning näiteks käivitada üheaegselt terve teenuste rühma ning teha lisatoiminguid. Lisaks ei ole neil hierarhiat, vaid ainult sõltuvused.
Näide target'ist sisselülitamisel (võimaluste ülevaade) koos interaktiivse skripti käivitamisega.
Kirjeldus target'ist:
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.serviceSee target käivitub, kui multi-user.target on aktiveeritud ja kutsub esile installer.service. Selliseid teenuseid võib olla mitu.
cat installer.service
[Unit]
# kirjeldus
Description=installer interaktiivne dialoog
[Service]
# Käivita üks kord, kui kõik muu on käivitatud
Type=idle
# Käivituskomandiks - skripti kutsumine
ExecStart=/usr/bin/installer.sh
# Interaktiivne suhtlemine kasutajaga läbi tty3
StandardInput=tty
TTYPath=/dev/tty3
TTYReset=yes
TTYVHangup=yes
[Install]
WantedBy=installer.targetJa lõpuks, näide käitatavast skriptist:
#!/bin/bash
# Переходим в tty3
chvt 3
echo "Install, y/n ?"
read user_answerOluline on valida final.target - sihtkoht, kuhu süsteem peab käivitamisel jõudma. Käivitamise ajal läbib systemd sõltuvused ja käivitab kõik vajaliku.
Final.target'i valimiseks on erinevaid meetodeid, mina kasutasin selleks laadijat.
Lõppkäivitamine näeb välja järgmine:
- Käivitub laadija
- Laadija alustab püsivara käivitamist, edastades parameetri final.target
- Systemd alustab süsteemi käivitamist. Järjekindlalt liigutakse installer.target või work.target juurde basic.target kaudu nende sõltuvuste kaudu (näiteks multi-user.target). Just need viivad süsteemi töötama soovitud režiimis.
Püsivara käivitamiseks ettevalmistamine
Firmware'ide loomisel on alati ülesanne taastada süsteemi seisund käivitamisel ja salvestada see väljalülitamisel. All mõistetakse olekuna konfiguratsioonifailid, andmebaasi dump'id, liideste seadistused jne.
Systemd käivitab protsessid ühes sihtmärgis paralleelselt. On sõltuvusi, mis võimaldavad määrata skriptide käivitamise järjekorra.
Kuidas see minu projektis töötab ( )
- Süsteem käivitub
- Käivitub teenus settings_restore.service. See kontrollib, kas andmejaotuses on olemas fail settings.txt. Kui seda pole, asendatakse see etalonfailiga. Edasi toimub süsteemi seadistuste taastamine:
- administraatori parool
- hostname,
- ajavöönd
- lokaliseerimine
- Määratakse kindlaks, kas kõik andmekandjad on kasutuses. Vaikimisi on pildi suurus väike — mugavuseks kopeerimiseks ja andmekandjale kirjutamiseks. Käivitamisel kontrollitakse, kas on veel kasutamata ruumi. Kui on, siis ketas partitsioneeritakse uuesti.
- Machine-id genereerimine MAC-aadressist. See on oluline, et saada sama aadress DHCP kaudu.
- Võrgu seadistused
- Logide suurus on piiratud
- Valmistatakse ette väline ketas (kui vastav valik on sisse lülitatud ja ketas on uus)
- Käivitub postgresq
- Käivitatakse taastamise teenus. See on vajalik zabbixi ja selle andmebaasi ettevalmistamiseks:
- Kontrollitakse, kas zabbix'il on juba andmebaas. Kui ei, siis luuakse see initsialiseerimise dump'ide põhjal (mis kuuluvad zabbix'i komplekti)
- Koostatakse ajavööndite nimekiri (vajalik nende kuvamiseks veebiliideses)
- Leitakse praegune IP, mis kuvatakse probleemi teates (kutsudes sisenema konsooli)
- Muudetakse kutset — kuvatakse fraas 'Ready to work'
- Käivitamine on valmis töötama
Teenuste failid on olulised, need määravad nende käivitamise järjestuse
[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.targetKuidas näha, olen seadnud sõltuvused, et kõigepealt töötaks minu skript ja alles siis tõuseks võrk ja käivituks DBMS.
Ja teine teenus (zabbixi ettevalmistamine)
#!/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.targetSiin on natuke keerulisem. Käivitamine samuti multi-user.target'is, kuid PENSIONAJAL postgresql'i DBMS'i ja minu setting_restore'i tõusu. Kuid ENNE zabbixi teenuste käivitamist.
Teenuse taimer logrotate jaoks
Systemd võib asendada CRON-i. Tõsiselt. Täpsus ei ole ainult minutite, vaid ka sekundite kaupa (kasuta seda siis, kui vajad). Lisaks saab luua monotoni ajastuse, mis käivitub sündmustest sõltuvalt.
Just selline monotoni ajastus, mis arvestab aega alates masina käivitamisest, on mul loodud.
Selle jaoks on vajalikud 2 faili
logrotateTimer.service — teenuse tegelik kirjeldus:
[Unit]
Description=run logrotate
[Service]
ExecStart=logrotate /etc/logrotate.conf
TimeoutSec=300See on lihtne — käivitamise kirjeldus.
Teine fail logrotateTimer.timer — just see seab ajastuse töö:
[Unit]
Description=Run logrotate
[Timer]
OnBootSec=15min
OnUnitActiveSec=15min
[Install]
WantedBy=timers.targetMida siin on:
- ajastuse kirjeldus
- esimese käivitamise aeg, alates süsteemi käivitamisest
- edasi käivitamise periood
- sõltuvus ajastuste teenusest. Tegelikult on see rida, mis teeb ajastuse.
Interaktiivne skript väljalülitamisel ja oma välja lülitamise sihtmärk
Teises arenduses pidin tegema keerukama variandi masina väljalülitamiseks — oma sihtmärgi kaudu, et täita mitu tegevust. Üldjuhul soovitatakse luua oneshot teenus koos RemainAfterExit valikuga, kuid see ei võimalda luua interaktiivset skripti.
Asi on see, et ExecOnStop valiku kaudu käivitatud käsklused täidetakse väljaspool TTY-d! Lihtsalt kontrollimiseks—sisestage käsk tty ja salvestage selle väljund.
Seetõttu rakendasin väljalülitamist oma sihtmärgi kaudu. 100% täpsust ei taga, kuid see töötab!
Kuidas see tehti (üldiselt):
Loomine sihtmärk my_shutdown.target, mis ei sõltunud kellestki:
my_shutdown.target
[Unit]
Description=my shutdown
AllowIsolate=yes
Wants=my_shutdown.service Sihtmärki 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=MY shutdown
[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 teen vajalikud toimingud. Sihtmärki võib lisada palju skripte, et tagada 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/
$commandMärkus. Failide /tmp/reboot ja /tmp/shutdown kasutamine. Ei saa käivitada sihtmärki koos parameetritega. Saab ainult teenust.
Kuid ma kasutan sihtmärki, et omada paindlikkust töös ja tagada toimingute täitmise järjekord.
Kuid kõige huvitavam oli siis. Masin tuleb ju välja lülitada/taaskäivitada. Ja siin on kaks varianti:
- Asenda käsklused reboot, shutdown ja teised (need on nagunii sümlinkid systemctl-ile) oma skriptiga. Skripti sees — üleminek my_shutdown.target'ile. Ja skriptid sees tarvis seejärel kutsuvad otse systemctl, näiteks systemctl reboot.
- Lihtsam, aga mulle ei meeldi variant. Kõikides liideses kutsuda mitte shutdown/reboot/teised, vaid otse kutsuda sihtmärki 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/systemctlSeetõttu saab need asendada oma skripti:
taaskäivita
#!/bin/sh
touch /tmp/reboot
sudo systemctl isolate my_shutdown.target
fiAllikas: habr.com
