
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.serviceEz 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_answerA 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:
- A betöltő elindul.
- A betöltő megkezdi a firmware indítását, átadva a final.target paramétert.
- 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 ( )
- A rendszer elindul.
- 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)
- Starting postgresq
- 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)
- The prompt is changed — the phrase Ready to work appears
- 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.targetAs 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.targetHere 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=300It’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.targetWhat 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/
$commandMegjegyzé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/systemctlEzért ezeket a saját scriptjeinkre cserélhetjük:
újraindítás
#!/bin/sh
touch /tmp/reboot
sudo systemctl isolate my_shutdown.target
fiForrás: habr.com
