Systemd, interagaj skriptoj kaj tempigiloj

Systemd, interagaj skriptoj kaj tempigiloj

Enkonduko

Dum evoluado por Linukso, aperas la tasko krei interagajn skriptojn, kiuj estas efektivigitaj kiam la sistemo estas ŝaltita aŭ malŝaltita. En sistemo V tio estis facila, sed kun systemd ĝi faras alĝustigojn. Sed ĝi povas havi siajn proprajn tempigilojn.

Kial ni bezonas celojn?

Estas ofte skribite ke celo funkcias kiel analogo de rulnivelo en sistemo V -init. Mi esence malkonsentas. Estas pli da ili kaj vi povas dividi pakaĵojn en grupojn kaj, ekzemple, lanĉi grupon de servoj per unu komando kaj fari pliajn agojn. Krome, ili havas neniun hierarkion, nur dependecojn.

Ekzemplo de celo kiam ĝi estas ebligita (trajtosuperrigardo) kun funkcianta interaga skripto

Priskribo de la celo mem:

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

Ĉi tiu celo komenciĝos kiam multi-user.target estas lanĉita kaj vokas installer.service. Tamen, povas ekzisti pluraj tiaj servoj.

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

Kaj finfine, ekzemplo de la skripto ekzekutita:

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

La plej grava afero estas elekti final.target - la celon al kiu la sistemo devus alveni ĉe ekfunkciigo. Dum la startprocezo, systemd ekzamenos la dependecojn kaj lanĉos ĉion, kion ĝi bezonas.
Estas malsamaj manieroj elekti final.target, mi uzis la opcion de ŝargilo por ĉi tio.

La fina lanĉo aspektas jene:

  1. La ekŝargilo komenciĝas
  2. La ekŝargilo komencas lanĉi la firmware pasante la parametron final.target
  3. Systemd komencas komenci la sistemon. Sinsekve iras al installer.target aŭ work.target de basic.target tra iliaj dependecoj (ekzemple, multi-user.target). Ĉi-lastaj funkciigas la sistemon en la dezirata reĝimo

Preparante la firmware por lanĉo

Dum kreado de firmvaro, ĉiam aperas la tasko restarigi la sisteman staton ĉe ekfunkciigo kaj konservi ĝin ĉe malŝalto. Ŝtato signifas agordajn dosierojn, datumbazajn rubejojn, interfacajn agordojn ktp.

Systemd kuras procezojn en la sama celo paralele. Estas dependecoj, kiuj permesas vin determini la startsekvencon de skriptoj.

Kiel ĝi funkcias en mia projekto ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. La sistemo komenciĝas
  2. La servo settings_restore.service estas lanĉita, ĝi kontrolas la ĉeeston de la dosiero settings.txt en la sekcio de datumoj. Se ĝi ne estas tie, tiam referencdosiero estas metita en ĝian lokon. Poste, la sistemaj agordoj estas restarigitaj:
    • pasvorto de administranto
    • gastiga nomo,
    • horzono
    • loko
    • Determinas ĉu ĉiuj amaskomunikiloj estas uzataj. Defaŭlte, la grandeco de bildo estas malgranda - por facileco kopii kaj registri al amaskomunikilaro. Ĉe ekfunkciigo, ĝi kontrolas ĉu estas ankoraŭ neuzata spaco. Se ekzistas, la disko estas reparticiigita.
    • Generante maŝin-identigilon de MAC-adreso. Ĉi tio gravas por akiri la saman adreson per DHCP
    • Retaj agordoj
    • Limigas la grandecon de ŝtipoj
    • La ekstera disko estas preta por laboro (se la responda opcio estas ebligita kaj la disko estas nova)
  3. Komencu postgresq
  4. La restariga servo komenciĝas. Necesas prepari zabbix mem kaj ĝian datumbazon:
    • Kontrolas ĉu jam ekzistas zabbix-datumbazo. Se ne, ĝi estas kreita de komencaj rubejoj (inkluditaj kun zabbix)
    • listo de horzonoj estas kreita (bezonata por montri ilin en la retinterfaco)
    • La nuna IP estas trovita, ĝi estas montrata en temo (invito ensaluti al la konzolo)
  5. La invito ŝanĝiĝas - aperas la frazo Preta por labori
  6. La firmvaro estas preta por uzo

La servaj dosieroj estas gravaj, ili estas tiuj, kiuj fiksas la sekvencon de sia lanĉo

[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

Kiel vi povas vidi, mi instalis dependecojn por ke mia skripto unue funkciu, kaj nur tiam la reto iru supren kaj la DBMS komenciĝus.

Kaj la dua servo (zabbix-preparo)

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

Ĉi tie estas iom pli komplika.La lanĉo estas ankaŭ en multi-user.target, sed POST komenci la postgresql DBMS kaj mia setting_restore. Sed ANTAŬ komenci zabbix-servojn.

Temporizilo por logrotate

Systemd povas anstataŭigi CRON. Serioze. Cetere, la precizeco ne estas ĝis la minuto, sed ĝis la dua (kaj se ĝi estas bezonata).Aŭ vi povas krei monotonan tempigilon, nomitan per tempotempo de evento.
Ĝi estis la monotona tempigilo kiu kalkulas la tempon de la komenco de la maŝino, kiun mi kreis.
Ĉi tio postulos 2 dosierojn
logrotateTimer.service - la fakta priskribo de la servo:

[Unit]
Description=run logrotate

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

Ĝi estas simpla - priskribo de la lanĉa komando.
La dua dosiero logrotateTimer.timer estas kie funkcias la tempigiloj:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Kio estas ĉi tie:

  • priskribo de temporizilo
  • Unua komenco-tempo, komencante de la sistemo-ŝargo
  • periodo de pliaj lanĉoj
  • Dependeco de la temporizilo.Fakte, ĉi tiu estas la ĉeno kiu faras la temporizilon

Interaga skripto kiam malŝalto kaj via halto celo

En alia evoluo, mi devis fari pli kompleksan version malŝalti la maŝinon - per mia propra celo, por fari multajn agojn. Kutime rekomendas krei oneshot-servon kun la opcio RemainAfterExit, sed ĉi tio malhelpas vin krei interagan skripton.

Sed la fakto estas, ke la komandoj lanĉitaj de la opcio ExecOnStop estas ekzekutitaj ekster la TTY! Estas facile kontroli - algluu la komandon tty kaj konservu ĝian eliron.

Tial mi efektivigis la haltigon per mia celo. Mi ne asertas esti 100% ĝusta, sed ĝi funkcias!
Kiel ĝi estis farita (ĝenerale):
Mi kreis celon my_shutdown.target, kiu ne dependis de iu ajn:
mia_malŝalto.celo

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

Irante al ĉi tiu celo (per systemctl izoli my_shutdwn.target), ĝi lanĉis la servon my_shutdown.service, kies tasko estas simpla - ekzekuti la skripton my_shutdown.sh:

[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

  • Ene de ĉi tiu skripto mi faras la necesajn agojn. Vi povas aldoni multajn skriptojn al la celo por fleksebleco kaj oportuno:

mia_haltigo.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

Notu. Uzante la dosierojn /tmp/reboot kaj /tmp/shutdown. Vi ne povas nomi celon kun parametroj. Nur servo eblas.

Sed mi uzas celon por havi flekseblecon en laboro kaj garantiita ordon de agoj.

Tamen la plej interesa afero venis poste. La maŝino devas esti malŝaltita/rekomencita. Kaj estas 2 opcioj:

  • Anstataŭigi la reboot, elŝalto kaj aliaj komandoj (ili estas ankoraŭ simbolaj ligiloj al systemctl) per via skripto.Ene de la skripto, iru al my_shutdown.target. Kaj la skriptoj ene de la celo tiam vokas systemctl rekte, ekzemple, systemctl reboot
  • Pli simpla opcio, sed mi ne ŝatas ĝin. En ĉiuj interfacoj, ne voku shutdown/reboot/other, sed rekte voku la celon systemctl izoli my_shutdown.target

Mi elektis la unuan opcion. En systemd, reboot (kiel poweroff) estas simbolligoj al systemd.

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

Tial, vi povas anstataŭigi ilin per viaj propraj skriptoj:
reboot

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

fonto: www.habr.com

Aldoni komenton