Systemd, interaktív szkriptek és időzítők

Systemd, interaktív szkriptek és időzítők

Bevezetés

Linux alatt interaktív szkriptek létrehozásának feladatai merülnek fel, amelyek a rendszer indításakor vagy leállításakor hajtódnak végre. A System V alatt ezt könnyen meg lehetett oldani, de a systemd ezzel némi változást hoz. Azonban saját időzítőkkel rendelkezik.

Mire való a target?

Gyakran írják, hogy a target a System V -init futási szintjének analógja - ezzel teljesen nem értek egyet. Számos ilyen létezését, és lehetővé teszi a csomagok csoportokra osztását, például egy parancs segítségével csoportos szolgáltatások indítását, kiegészítő műveletek végrehajtását. Ezen kívül nincs hierarchiájuk, csak függőségek.

Példa egy targetre bekapcsoláskor (a lehetőségek áttekintése) interaktív szkript indításával.

A target leírása:

cat installer.target
[Unit]
Description=Az én telepítőm
Requires=multi-user.target 
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target 
AllowIsolate=yes
Wants=installer.service

Ez a target elindul, amikor a multi-user.target elindul, és meghívja az installer.service-t. Ilyen szolgáltatások több is létezhet.

cat installer.service
[Unit]
# leírás
Description=telepítő interaktív párbeszéd

[Service]
# Indítsd el egyszer, amikor a többi elindult
Type=idle
# Indítási parancs - szkript meghívása
ExecStart=\/usr\/bin\/installer.sh
# Interaktív interakció a felhasználóval a tty3-on
StandardInput=tty
TTYPath=\/dev\/tty3
TTYReset=yes
TTYVHangup=yes

[Install]
WantedBy=installer.target

És végül, egy példa a futtatott szkriptre:

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

A legfontosabb — a final.target kiválasztása — az a target, ahová a rendszernek el kell jutnia a indítás során. A rendszerindítás folyamatában a systemd végigmegy a függőségeken és elindítja mindent, ami szükséges.
A final.target kiválasztása különböző módokon lehetséges, én ezen célra a betöltő opcióját használtam.

A végső indítás így néz ki:

  1. A betöltő elindul.
  2. A betöltő megkezdi a firmware indítását, átadva a final.target paramétert.
  3. A Systemd elkezdi a rendszer indítását. Sorrendben halad a basic.target-től az installer.target vagy work.target irányába, azok függőségein keresztül (például multi-user.target). Az utóbbiak vezetik a rendszert a kívánt üzemmódba.

A firmware indításának előkészítése.

Firmware írásakor mindig felmerül a rendszer állapotának helyreállításának feladata indításkor, és annak megőrzése leállításkor. Az állapot alatt a konfigurációs fájlokat, adatbázis mentéseket, interfészbeállításokat stb. értjük.

A Systemd egy targetben párhuzamosan indítja a folyamatokat. Vannak függőségek, amelyek lehetővé teszik a szkriptek indítási sorrendjének meghatározását.

Hogyan működik ez a projektben ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. A rendszer elindul.
  2. A settings_restore.service is starting. It checks for the presence of the settings.txt file in the data section. If it is not there, a standard file is placed in its place. Next, the system settings are restored:
    • administrator password
    • hostname,
    • time zone
    • locale
    • Determining if the entire medium is used. By default, the image size is small — for convenience of copying and writing to the medium. At startup, it checks if there is any unused space. If there is, the disk is repartitioned.
    • Generating machine-id from the MAC address. This is important for obtaining the same address via DHCP
    • Network settings
    • Limits the log size
    • Preparing an external drive (if the corresponding option is enabled and the drive is new)
  3. Starting postgresq
  4. The restore service is starting. It is needed to prepare Zabbix itself and its database:
    • It checks if the Zabbix database already exists. If not, it is created from the initializing dumps (included in the Zabbix package)
    • A list of time zones is created (needed for their display in the web interface)
    • The current IP is found and displayed in the issue (invitation for console login)
  5. The prompt is changed — the phrase Ready to work appears
  6. The firmware is ready to work

Service files are important, as they determine the order of their startup

[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

As you can see, I set dependencies so that my script runs first, and only then does the network start and the DBMS start.

And the second service (preparation of Zabbix)

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

Here it’s a bit more complicated. The start is also in multi-user.target, but AFTER the start of the postgresql DBMS and my setting_restore. But BEFORE the startup of Zabbix services.

A service with a timer for logrotate

Systemd can replace CRON. Seriously. Moreover, the precision is not to the minute, but to the second (just in case). A monotonous timer can be created, triggered by a timeout from an event.
It is precisely a monotonous timer, counting time from the machine's startup, that I created.
For this, 2 files will be required
logrotateTimer.service — this is the description of the service:

[Unit]
Description=run logrotate

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

It’s simple — a description of the command to run.
The second file logrotateTimer.timer — this one sets the operation of the timers:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

What is here:

  • A timer leírása
  • Az első indítás ideje a rendszer betöltésétől kezdve
  • A további indítások időszaka
  • A timer szolgáltatás függősége. Valójában ez a sor felel a timer működéséért

Interaktív script leállításkor és a saját leállítási célja

Egy másik fejlesztés során bonyolultabb leállítási változatot kellett készítenem — saját célon keresztül, hogy számos műveletet végrehajtsak. Általában ajánlott egy oneshot szolgáltatást létrehozni RemainAfterExit opcióval, de ez nem teszi lehetővé interaktív script létrehozását.

A dolog az, hogy az ExecOnStop opcióval indított parancsok kívül futnak a TTY-n! Egyszerűen ellenőrizhetó — írja be a tty parancsot, és mentse el a kimenetét.

Ezért saját célon keresztül valósítottam meg a leállítást. 100%-os helyességre nem tartok igényt, de működik!
Hogyan készült (tömören):
Létrehoztam a my_shutdown.target célt, amely senkitől sem függött:
my_shutdown.target

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

Amikor ebbe a célba léptem (a systemctl isolate my_shutdwn.target paranccsal), elindította a my_shutdown.service szolgáltatást, amelynek feladata egyszerű — végrehajtani a my_shutdown.sh scriptet:

[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

  • A scriptben végrehajtom a szükséges műveleteket. A célhoz sok scriptet hozzáadhatunk, a rugalmasság és kényelem érdekében:

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

Megjegyzés: A /tmp/reboot és /tmp/shutdown fájlok használata. Célokat nem lehet paraméterekkel hívni. Csak szolgáltatást lehet.

De én a célt használom, hogy rugalmasságot biztosítsak a munkában és garantált végrehajtási sorrendet biztosítsak.

Azonban a legérdekesebb dolog ezután történt. A gépet ki kell kapcsolni / újra kell indítani. Itt két lehetőség van:

  • A reboot, shutdown és egyéb parancsokat (mivel ezek is szimbolikus linkek a systemctl-re) a saját scriptomra cserélni. A script belsejében — átmegyünk a my_shutdown.target célra. A célen belüli scriptek közvetlenül hívják a systemctl-t, például systemctl reboot.
  • Egyszerűbb, de számomra nem tetsző lehetőség. Minden interfészben ne a shutdown/ reboot/ egyéb parancsokat hívjuk, hanem közvetlenül a systemctl isolate my_shutdown.target célt.

Én az első lehetőséget választottam. A systemd reboot (ahogyan a poweroff) szimbolikus linkek a systemd-re.

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

Ezért ezeket a saját scriptjeinkre cserélhetjük:
újraindítás

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

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster