
Hyrje
Në zhvillimin nën linux, lindin detyra për të krijuar skripta interaktive që ekzekutohen gjatë krijimit ose mbylljes së sistemit. Në system V kjo bëhej lehtësisht, por me systemd ka disa rregullime. Sidoqoftë, ai ka mundësi për timer-at e tij.
Pse janë të nevojshme targetet
Shpesh shkruhet se targetet shërbejnë si ekuivalent të runlevel në system V -init. Unë nuk pajtohem me këtë. Ato janë më shumë dhe mund të ndahen paketat në grupe dhe, për shembull, të aktivizojnë një grup shërbimesh me një komandë, të kryejnë veprime të tjera. Përveç kësaj, ato nuk kanë hierarki, vetëm varësi.
Shembulli i targetit gjatë aktivizimit (pasqyrë e mundësive) me ekzekutimin e një skripti interaktiv
Përshkrimi i vetë targetit:
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.serviceKy target do të aktivizohet kur të aktivizohet multi-user.target dhe do të thërrasë installer.service. Në të njëjtën kohë, mund të kenë disa shërbime të tilla.
cat installer.service
[Unit]
# përshkrimi
Description=installer interactive dialog
[Service]
# Aktivizohet një herë, kur gjithçka tjetër është e aktivizuar
Type=idle
# Komanda e aktivizimit - thirrja e skriptit
ExecStart=\/usr\/bin\/installer.sh
# Interaksioni interaktiv me përdoruesin përmes tty3
StandardInput=tty
TTYPath=\/dev\/tty3
TTYReset=yes
TTYVHangup=yes
[Install]
WantedBy=installer.targetDhe në fund, një shembull i skriptit të ekzekutuar:
#!/bin/bash
# Переходим в tty3
chvt 3
echo "Install, y/n ?"
read user_answerE rëndësishmja është të zgjidhni final.target - targetin në të cilin sistemi duhet të arrijë gjatë aktivizimit. Gjatë aktivizimit, systemd do të kalojë përmes varësive dhe do të aktivizojë gjithçka të nevojshme.
Mund të zgjidhni final.target në mënyra të ndryshme, unë përdora për këtë opsionin e boot-loader-it.
Aktivizimi përfundimtar duket kështu:
- Boot-loader-i aktivizohet
- Boot-loader-i fillon aktivizimin e firmware-it, duke kaluar parametrin final.target
- Systemd fillon aktivizimin e sistemit. Kjo ndodh një pas një drejt installer.target ose work.target nga basic.target përmes varësive të tyre (p.sh., multi-user.target). Këta të fundit e çojnë sistemin në punë në modin e nevojshëm.
Përgatitja e firmware-it për aktivizim
Gjatë krijimit të firmware-it, gjithmonë lind detyra për të rikthyer gjendjen e sistemit gjatë aktivizimit dhe për ta ruajtur atë gjatë mbylljes. Nga gjendja kuptohen skedarët e konfigurimit, dump-et e databazave, konfigurimet e ndërfaqeve, etj.
Systemd aktivizon proceset në një target në mënyrë paralele. Ka varësi që lejojnë përcaktimin e rendit të aktivizimit të skripteve.
Si funksionon kjo në projektin tim ( )
- Sistemi starton
- Shërbimi settings_restore.service po niset. Ai kontrollon praninë e skedarit settings.txt në seksionin e të dhënave. Nëse nuk ekziston, atëherë vendoset skedari standard në vend të tij. Më pas, ndodh rikthimi i konfigurimeve të sistemit:
- fjalëkalimin e administratorit
- hostname,
- zona kohore
- lokali
- Përkufizimi nëse e gjithë mbajtësja është në përdorim. Si rregull, madhësia e imazhit është e vogël — për lehtësi në kopjim dhe shkrim në mbajtës. Gjatë fillimit kontrollohet — a ka vend të papërdorur. Nëse ka — disku ribëhet.
- Gjenerimi i machine-id nga adresë MAC. Kjo është e rëndësishme për të marrë të njëjtën adresë përmes DHCP
- Konfigurimet e rrjetit
- Madhësia e log-eve kufizohet
- Përgatitet një disk i jashtëm (nëse është aktivizuar opsioni përkatës dhe disku është i ri)
- Nisët postgresq
- shërbimi restore po nis. Ky shërbim është i nevojshëm për përgatitjen e zabbix-it dhe bazës së të dhënave të tij:
- Kontrollohet nëse tashmë ekziston baza e të dhënave zabbix. Nëse nuk ka — krijohet nga dump-et e iniciatimit (që vijnë me furnizimin e zabbix)
- krijohet një listë e zonave kohore (nevojitet për shfaqjen e tyre në ndërfaqen web)
- Gjej IP-në aktuale, e cila shfaqet në issue (futja në konsolë)
- Ftesa ndryshohet — shfaqet fraza Ready to work
- Firmware i gatshëm për punë
Ka rëndësi skedarët e shërbimeve, ata vendosin renditjen e nisjes së tyre
[Unit]
Description=rikthe konfigurimet e sistemit
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.targetSiç duket, kam vendosur varësitë që fillimisht të ekzekutohet skripti im, dhe vetëm atëherë të ngrihet rrjeti dhe të startohet DB.
Dhe shërbimi i dytë (preparimi i 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.targetKëtu është pak më e komplikuar. Nisja gjithashtu në multi-user.target, por PAS NISJES së DB postgresql dhe setting_restore tim. Por PARA nisjes së shërbimeve zabbix.
Shërbimi me timer për logrotate
Systemd mund të zëvendësojë CRON. Me seriozitet. Dhe saktësia jo deri në minutë, por deri në sekondë (nëse ndonjëherë nevojitet). Mund të krijohet gjithashtu një timer monotone, i thirrur nga timeout nga ngjarja.
Saktësisht timer monotone, që llogarit kohën nga nisja e pajisjes, e kam krijuar.
Për këtë nevojiten 2 skedare
logrotateTimer.service — përshkrimi i shërbimit:
[Unit]
Description=ekzekuto logrotate
[Service]
ExecStart=logrotate \/etc\/logrotate.conf
TimeoutSec=300E gjithë e thjeshtë — përshkrimi i komandës së ekzekutimit.
Skedari i dytë logrotateTimer.timer — ky e vendos punën e timerëve:
[Unit]
Description=Ekzekuto logrotate
[Timer]
OnBootSec=15min
OnUnitActiveSec=15min
[Install]
WantedBy=timers.targetÇfarë ka këtu:
- përshkrimi i timerit
- Koha e lançimit të parë, duke filluar nga ngarkimi i sistemit
- periudha e lançimeve të mëtejshme
- Varësia nga shërbimi i timerave. Në fakt, kjo është linja dhe bën timerin
Skripti interaktiv gjatë fikjes dhe targeti im për fikje
Në një zhvillim tjetër, më është dashur të bëj një variant më të komplikuar për fikjen e makinës - përmes targetit tim, për të realizuar shumë veprime. Zakonisht rekomandohet të krijoni një shërbim oneshot me opsionin RemainAfterExit, por kjo nuk lejon krijimin e një skripti interaktiv.
E vërteta është se komandat e nisura nga opsioni ExecOnStop ekzekutohen jashtë TTY! E kontrolloni lehtësisht - futni komandën tty dhe ruani daljen e saj.
Prandaj, realizova fikjen përmes targetit tim. Nuk pretendoj për 100% saktësi, por funksionon!
Si u bë kjo (në terma të përgjithshëm):
Krijova targetin my_shutdown.target, i cili nuk varej nga askush:
my_shutdown.target
[Njësia]
Përshkrimi=my shutdown
LejoIzolim=yes
Dëshiron=my_shutdown.service Kur kaloni në këtë target (nëpërmjet systemctl isolate my_shutdown.target), ai aktivizonte shërbimin my_shutdown.service, detyra e të cilit është e thjeshtë - të ekzekutojë skriptin my_shutdown.sh:
[Njësia]
Përshkrimi=MY shutdown
[Shërbimi]
Tipi=oneshot
ExecStart=\/usr\/bin\/my_shutdown.sh
StandardInput=tty
TTYPath=\/dev\/tty3
TTYReset=yes
TTYVHangup=yes
Dëshiron=my_shutdown.target- Brenda këtij skripti unë i kryej veprimet e nevojshme. Mund të shtoni shumë skripte në target për fleksibilitet dhe komfort:
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/
$commandShënim: Përdorimi i skedarëve \/tmp\/reboot dhe \/tmp\/shutdown. Nuk mund të thirret target me parametra. Mund vetëm shërbimin.
Por unë përdor target, për të pasur fleksibilitet në punë dhe një rend të garantuar të ekzekutimit të veprimeve.
Megjithatë, ajo që ishte interesante erdhi më vonë. Makinën duhet të fikim\/ribillojmë. Dhe këtu ka 2 mundësi:
- Të zëvendësojmë komandat reboot, shutdown dhe të tjera (ato gjithsesi janë linke simbolike në systemctl) me skriptin tim. Brenda skriptit - kalimi në my_shutdown.target. Dhe skriptet brenda targetit pastaj thërrasin drejtpërdrejt systemctl, për shembull, systemctl reboot
- Një variant më i thjeshtë, por që nuk më pëlqen. Në të gjitha ndërfaqet nuk thirrni shutdown\/reboot\/të tjera, por thjesht thirrni targetin systemctl isolate my_shutdown.target
Zgjodha variantin e parë. Në systemd, reboot (ashtu si dhe poweroff) janë linke simbolike në systemd.
ls -l \/sbin\/poweroff
lrwxrwxrwx 1 root root 14 sep 30 18:23 \/sbin\/poweroff -> \/bin\/systemctlPrandaj mund të zëvendësohen me skriptet e mia:
reboot
#!/bin/sh
touch /tmp/reboot
sudo systemctl isolate my_shutdown.target
fiBurimi: habr.com
