Gestelselde, interaktiewe skrifte en tydtellers

Gestelselde, interaktiewe skrifte en tydtellers

Inleiding

Wanneer daar vir Linux ontwikkel word, ontstaan ​​die taak om interaktiewe skrifte te skep wat uitgevoer word wanneer die stelsel aangeskakel of afgesluit word. In stelsel V was dit maklik, maar met systemd maak dit aanpassings. Maar dit kan sy eie timers hê.

Hoekom het ons teikens nodig?

Daar word dikwels geskryf dat teiken dien as 'n analoog van runlevel in stelsel V -init. Ek stem fundamenteel nie saam nie. Daar is meer van hulle en jy kan pakkette in groepe verdeel en byvoorbeeld 'n groep dienste met een opdrag begin en bykomende aksies uitvoer. Boonop het hulle geen hiërargie nie, slegs afhanklikhede.

Voorbeeld van teiken wanneer geaktiveer (kenmerkoorsig) met lopende interaktiewe skrip

Beskrywing van die teiken self:

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

Hierdie teiken sal begin wanneer multi-user.target geloods word en installer.service oproep. Daar kan egter verskeie sulke dienste wees.

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

En ten slotte, 'n voorbeeld van die draaiboek wat uitgevoer word:

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

Die belangrikste ding is om final.target te kies - die teiken waarheen die stelsel by opstart moet kom. Tydens die opstartproses sal systemd deur die afhanklikhede gaan en alles begin wat dit nodig het.
Daar is verskillende maniere om final.target te kies, ek het die loader opsie hiervoor gebruik.

Die finale bekendstelling lyk soos volg:

  1. Die selflaaiprogram begin
  2. Die selflaaiprogram begin die firmware begin deur die final.target-parameter deur te gee
  3. Systemd begin die stelsel begin. Gaan opeenvolgend na installer.target of work.target vanaf basic.target deur hul afhanklikhede (byvoorbeeld, multi-user.target). Laasgenoemde bring die stelsel in die gewenste modus te werk

Berei die firmware voor vir bekendstelling

By die skep van firmware, ontstaan ​​die taak altyd om die stelseltoestand by opstart te herstel en dit te stoor wanneer dit afgesluit word. Staat beteken konfigurasielêers, databasisstortings, koppelvlakinstellings, ens.

Systemd loop prosesse in dieselfde teiken in parallel. Daar is afhanklikhede wat jou toelaat om die opstartvolgorde van skrifte te bepaal.

Hoe werk dit in my projek ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Die stelsel begin
  2. Die settings_restore.service-diens word geloods. Dit kyk vir die teenwoordigheid van die settings.txt-lêer in die data-afdeling. As dit nie daar is nie, word 'n verwysingslêer in die plek daarvan geplaas. Vervolgens word die stelselinstellings herstel:
    • administrateur wagwoord
    • gasheernaam,
    • tydsone
    • locale
    • Bepaal of alle media gebruik word. By verstek is die beeldgrootte klein - vir maklike kopiëring en opname na media. By opstart word daar gekyk of daar nog ongebruikte spasie is. As daar is, word die skyf herpartisioneer.
    • Genereer masjien-ID vanaf MAC-adres. Dit is belangrik vir die verkryging van dieselfde adres via DHCP
    • Netwerkstellings
    • Beperk die grootte van logs
    • Die eksterne skyf word voorberei vir werk (as die ooreenstemmende opsie geaktiveer is en die skyf nuut is)
  3. Begin postgresq
  4. Die hersteldiens begin. Dit is nodig om zabbix self en sy databasis voor te berei:
    • Kontroleer of daar reeds 'n zabbix-databasis is. Indien nie, word dit geskep vanaf inisialiseringstortings (ingesluit by zabbix)
    • 'n lys tydsones word geskep (nodig om dit in die webkoppelvlak te vertoon)
    • Die huidige IP word gevind, dit word in die uitgawe vertoon (uitnodiging om by die konsole aan te meld)
  5. Die uitnodiging verander - die frase Gereed om te werk verskyn
  6. Die firmware is gereed vir gebruik

Die dienslêers is belangrik, dit is diegene wat die volgorde van hul bekendstelling bepaal

[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

Soos jy kan sien, het ek afhanklikhede geïnstalleer sodat my script eers sou werk, en eers dan sou die netwerk opgaan en die DBMS sou begin.

En die tweede diens (zabbix voorbereiding)

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

Dit is 'n bietjie meer ingewikkeld hier. Die bekendstelling is ook in multi-user.target, maar NA die begin van die postgresql DBMS en my setting_restore. Maar VOORdat jy begin met zabbix dienste.

Timer diens vir logrotate

Systemd kan CRON vervang. Ernstig. Boonop is die akkuraatheid nie op die minuut nie, maar tot op die sekonde (wat as dit nodig is). Of jy kan 'n eentonige timer skep, geroep deur 'n time-out van 'n gebeurtenis.
Dit was die eentonige timer wat die tyd tel vanaf die begin van die masjien wat ek geskep het.
Dit sal 2 lêers vereis
logrotateTimer.service - die werklike beskrywing van die diens:

[Unit]
Description=run logrotate

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

Dit is eenvoudig - beskrywing van die bekendstelling opdrag.
Die tweede lêer logrotateTimer.timer is waar die timers werk:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Wat is hier:

  • timer beskrywing
  • Eerste begintyd, vanaf stelsellaai
  • tydperk van verdere bekendstellings
  • Afhanklikheid van die tydhouerdiens. Trouens, dit is die string wat die tydteller maak

Interaktiewe skrif wanneer jy afskakel en jou afskakelteiken

In 'n ander ontwikkeling moes ek 'n meer komplekse weergawe doen om die masjien af ​​te skakel - deur my eie teiken, om baie aksies uit te voer. Dit word gewoonlik aanbeveel om 'n eenkopdiens met die RemainAfterExit-opsie te skep, maar dit verhoed dat jy 'n interaktiewe skrif skep.

Maar die feit is dat die opdragte wat deur die ExecOnStop-opsie geloods word, buite die TTY uitgevoer word! Dit is maklik om na te gaan - plak die tty-opdrag en stoor die uitvoer daarvan.

Daarom het ek die afsluiting deur my teiken geïmplementeer. Ek beweer nie dat ek 100% korrek is nie, maar dit werk!
Hoe dit gedoen is (in algemene terme):
Ek het 'n teiken my_shutdown.target geskep, wat van niemand afhanklik was nie:
my_shutdown.target

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

Wanneer jy na hierdie teiken gaan (via systemctl isolate my_shutdwn.target), het dit die my_shutdown.service-diens geloods, waarvan die taak eenvoudig is - om die my_shutdown.sh-skrip uit te voer:

[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

  • Binne hierdie skrif voer ek die nodige aksies uit. Jy kan baie skrifte by die teiken voeg vir buigsaamheid en gerief:

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

Let wel. Gebruik die /tmp/reboot- en /tmp/shutdown-lêers. Jy kan nie teiken met parameters noem nie. Slegs diens is moontlik.

Maar ek gebruik teiken om buigsaamheid in werk en 'n gewaarborgde volgorde van aksies te hê.

Die interessantste ding het egter later gekom. Die masjien moet afgeskakel/herbegin word. En daar is 2 opsies:

  • Vervang die herlaai, afsluit en ander opdragte (dit is steeds simbole na systemctl) met jou skrif. Binne die skrif, gaan na my_shutdown.target. En die skrifte binne die teiken roep dan systemctl direk, byvoorbeeld systemctl reboot
  • ’n Eenvoudiger opsie, maar ek hou nie daarvan nie. In alle koppelvlakke, moenie shutdown/reboot/other roep nie, maar skakel die teikenstelsel direk my_shutdown.target isoleer.

Ek het die eerste opsie gekies. In systemd is herlaai (soos poweroff) simbole na systemd.

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

Daarom kan jy dit vervang met jou eie skrifte:
herlaai

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

Bron: will.com

Voeg 'n opmerking