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

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

Bevezetés

A Linuxra való fejlesztés során felmerül a feladat, hogy interaktív szkripteket hozzanak létre, amelyek a rendszer bekapcsolásakor vagy leállításakor futnak le. Az V rendszerben ez egyszerű volt, de a systemd-vel módosítja. De lehet saját időzítője.

Miért van szükségünk célpontokra?

Gyakran írják, hogy a target a futási szint analógja a V -init rendszerben. Alapvetően nem értek egyet. Több is van belőlük, és a csomagokat csoportokra oszthatja, és például egy paranccsal elindíthat egy szolgáltatáscsoportot, és további műveleteket hajthat végre. Ráadásul nincs hierarchiájuk, csak függőségek.

Példa a célra, ha engedélyezve van (a szolgáltatás áttekintése) interaktív szkripttel

Maga a célpont leírása:

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

Ez a cél akkor indul el, amikor a multi-user.target elindul, és meghívja az installer.service-t. Azonban több ilyen szolgáltatás is létezhet.

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

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

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

A legfontosabb dolog a final.target kiválasztása – ez a cél, amelyhez a rendszernek induláskor meg kell érkeznie. Az indítási folyamat során a systemd végigmegy a függőségeken, és elindít mindent, amire szüksége van.
A final.target kiválasztásának többféle módja van, én ehhez a loader opciót használtam.

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

  1. Elindul a rendszerbetöltő
  2. A rendszerbetöltő elindítja a firmware-t a final.target paraméter átadásával
  3. A Systemd elkezdi elindítani a rendszert. A basic.target fájlból egymás után az installer.target vagy a work.target fájlra lép a függőségeiken keresztül (például többfelhasználós.target). Ez utóbbiak a kívánt üzemmódban működtetik a rendszert

A firmware előkészítése az indításhoz

A firmware létrehozásakor mindig felmerül a feladat, hogy indításkor visszaállítsa a rendszer állapotát, leállításkor pedig elmentse. Az állapot konfigurációs fájlokat, adatbázis-kiíratásokat, interfész beállításokat stb.

A Systemd párhuzamosan futtatja a folyamatokat ugyanazon a célon. 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 projektemben ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. A rendszer elindul
  2. Elindul a settings_restore.service szolgáltatás, amely ellenőrzi a settings.txt fájl meglétét az adatrészben. Ha nincs ott, akkor egy referenciafájl kerül a helyére, majd a rendszerbeállítások visszaállítása:
    • rendszergazdai jelszó
    • gazdagépnév
    • időzóna
    • locale
    • Meghatározza, hogy az összes adathordozó használatban van-e. Alapértelmezés szerint a kép mérete kicsi – a könnyű másolás és adathordozóra való rögzítés érdekében. Indításkor ellenőrzi, hogy van-e még kihasználatlan hely. Ha van, a lemez újraparticionálva van.
    • Gépazonosító generálása MAC-címből. Ez azért fontos, hogy DHCP-n keresztül ugyanazt a címet kapjuk meg
    • Hálózati beállítások
    • Korlátozza a rönk méretét
    • A külső meghajtó előkészítése folyamatban van (ha a megfelelő opció engedélyezve van, és a meghajtó új)
  3. Start postgresq
  4. Elindul a visszaállítási szolgáltatás. Magának a zabbixnak és adatbázisának elkészítéséhez szükséges:
    • Ellenőrzi, hogy létezik-e már zabbix adatbázis. Ha nem, akkor inicializálási kiíratásokból jön létre (a zabbix tartalmazza)
    • létrejön az időzónák listája (a webes felületen való megjelenítésükhöz szükséges)
    • Az aktuális IP-cím megtalálható, megjelenik a kiadásban (meghívás a konzolba való bejelentkezésre)
  5. A meghívó megváltozik – megjelenik a Ready to work (Munkára kész) kifejezés
  6. A firmware használatra kész

A szervizfájlok fontosak, ezek határozzák meg indításuk sorrendjét

[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

Amint látja, a függőségeket úgy telepítettem, hogy először működjön a szkriptem, és csak ezután induljon el a hálózat és induljon el a DBMS.

És a második szolgáltatás (zabbix előkészítés)

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

Itt egy kicsit bonyolultabb. Az indítás a multi-user.targetben is megtörténik, de a postgresql DBMS és a set_restore elindítása UTÁN. De a zabbix szolgáltatások elindítása ELŐTT.

Időzítő szolgáltatás a logrotate számára

A Systemd helyettesítheti a CRON-t. Komolyan. Sőt, a pontosság nem perc, hanem másodpercig terjed (mi van, ha szükség van rá), vagy létrehozhat egy monoton időzítőt, amelyet egy esemény időkorlátja hív meg.
A monoton időzítő számolja az időt az általam létrehozott gép indulásától számítva.
Ehhez 2 fájlra lesz szükség
logrotateTimer.service - a szolgáltatás tényleges leírása:

[Unit]
Description=run logrotate

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

Egyszerű – az indítási parancs leírása.
A második logrotateTimer.timer fájl az, ahol az időzítők működnek:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Mi van itt:

  • időzítő leírása
  • Első indítási időpont, a rendszerindítástól kezdve
  • a további indítások időszaka
  • Az időzítő szolgáltatástól való függés. Valójában ez az a karakterlánc, amely az időzítőt hozza létre

Interaktív szkript leállításkor és a leállítási cél

Egy másik fejlesztés során a gép kikapcsolásának egy bonyolultabb változatát kellett végrehajtanom - a saját célpontomon keresztül, hogy sok műveletet hajtsak végre. Általában javasolt egy oneshot szolgáltatás létrehozása a RemainAfterExit opcióval, de ez megakadályozza, hogy interaktív szkriptet hozzon létre.

De tény, hogy az ExecOnStop opció által indított parancsok a TTY-n kívül futnak! Könnyű ellenőrizni – illessze be a tty parancsot, és mentse el a kimenetét.

Ezért a leállítást a célpontomon keresztül valósítottam meg. Nem állítom, hogy 100%-ban igazam van, de működik!
Hogyan csinálták (általánosságban):
Létrehoztam egy my_shutdown.target célt, amely nem függött senkitől:
my_shutdown.target

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

Amikor erre a célpontra ment (a systemctl isolate my_shutdwn.target segítségével), elindította a my_shutdown.service szolgáltatást, amelynek a feladata egyszerű - a my_shutdown.sh szkript végrehajtása:

[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

  • Ezen a szkripten belül végrehajtom a szükséges műveleteket. A rugalmasság és a kényelem érdekében számos szkriptet adhat hozzá a célhoz:

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

Jegyzet. A /tmp/reboot és /tmp/shutdown fájlok használata. A target nem hívható meg paraméterekkel. Csak szerviz lehetséges.

De a célt azért használom, hogy rugalmas legyen a munkavégzés és garantált legyen a cselekvési sorrend.

A legérdekesebb azonban később jött. A gépet ki kell kapcsolni/újraindítani. És 2 lehetőség van:

  • Cserélje ki a reboot, shutdown és egyéb parancsokat (ezek továbbra is szimbolikus hivatkozások a systemctl-hez) a szkripttel. A célon belüli szkriptek ezután közvetlenül hívják a systemctl-t, például a systemctl reboot parancsot
  • Egyszerűbb lehetőség, de nem szeretem. Minden interfészen ne hívja a shutdown/reboot/other parancsot, hanem közvetlenül a cél systemctl isolate my_shutdown.target parancsát.

Én az első lehetőséget választottam. A systemd-ben az újraindítás (mint a kikapcsolás) a systemd-re mutató hivatkozások.

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

Ezért lecserélheti őket saját szkriptjeire:
újraindítás

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

Forrás: will.com

Hozzászólás