Systemd, mga interactive na script at timer

Systemd, mga interactive na script at timer

Pagpapakilala

Kapag nagde-develop para sa Linux, ang gawain ng paglikha ng mga interactive na script na naisakatuparan kapag ang system ay naka-on o isinara ang arises. Sa system V ito ay madali, ngunit sa systemd ito ay gumagawa ng mga pagsasaayos. Ngunit maaari itong magkaroon ng sarili nitong mga timer.

Bakit kailangan natin ng mga target?

Madalas na nakasulat na ang target ay nagsisilbing analogue ng runlevel sa system V -init. Ako sa panimula ay hindi sumasang-ayon. Marami pa sa kanila at maaari mong hatiin ang mga pakete sa mga pangkat at, halimbawa, maglunsad ng isang pangkat ng mga serbisyo na may isang utos at magsagawa ng mga karagdagang pagkilos. Bukod dito, wala silang hierarchy, mga dependency lamang.

Halimbawa ng target kapag pinagana (pangkalahatang-ideya ng tampok) na may tumatakbong interactive na script

Paglalarawan ng mismong target:

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

Magsisimula ang target na ito kapag inilunsad ang multi-user.target at tumawag sa installer.service. Gayunpaman, maaaring mayroong ilang mga naturang serbisyo.

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

At sa wakas, isang halimbawa ng script na isinasagawa:

#!/bin/bash
# ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ Π² tty3
chvt 3
echo "Install, y/n ?"
read user_answer

Ang pinakamahalagang bagay ay ang piliin ang final.target - ang target kung saan dapat dumating ang system sa startup. Sa panahon ng proseso ng pagsisimula, dadaan ang systemd sa mga dependency at ilulunsad ang lahat ng kailangan nito.
Mayroong iba't ibang paraan upang piliin ang final.target, ginamit ko ang opsyon na loader para dito.

Ang huling paglulunsad ay ganito ang hitsura:

  1. Magsisimula ang bootloader
  2. Ang bootloader ay magsisimulang ilunsad ang firmware sa pamamagitan ng pagpasa sa final.target na parameter
  3. Nagsisimula ang Systemd na simulan ang system. Sunud-sunod na pumupunta sa installer.target o work.target mula sa basic.target sa pamamagitan ng kanilang mga dependency (halimbawa, multi-user.target). Dinadala ng huli ang system upang gumana sa nais na mode

Inihahanda ang firmware para sa paglulunsad

Kapag lumilikha ng firmware, palaging nangyayari ang gawain ng pagpapanumbalik ng estado ng system sa pagsisimula at pag-save nito kapag nagsasara. Ang ibig sabihin ng estado ay mga configuration file, database dump, mga setting ng interface, atbp.

Ang Systemd ay nagpapatakbo ng mga proseso sa parehong target nang magkatulad. May mga dependency na nagbibigay-daan sa iyo upang matukoy ang pagkakasunud-sunod ng startup ng mga script.

Paano ito gumagana sa aking proyekto ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Magsisimula ang sistema
  2. Inilunsad ang serbisyo ng settings_restore.service. Sinusuri nito ang presensya ng settings.txt file sa seksyon ng data. Kung wala ito, pagkatapos ay isang reference na file ang inilalagay sa lugar nito. Susunod, ang mga setting ng system ay naibalik:
    • password ng administrator
    • hostname
    • time zone
    • lokal
    • Tinutukoy kung ang lahat ng media ay ginagamit. Bilang default, ang laki ng imahe ay maliit - para sa kadalian ng pagkopya at pag-record sa media. Sa startup, sinusuri nito kung mayroon pa ring hindi nagamit na espasyo. Kung mayroon, ang disk ay repartitioned.
    • Bumubuo ng machine-id mula sa MAC address. Ito ay mahalaga para sa pagkuha ng parehong address sa pamamagitan ng DHCP
    • Mga setting ng network
    • Nililimitahan ang laki ng mga log
    • Ang panlabas na drive ay inihahanda para sa trabaho (kung ang kaukulang opsyon ay pinagana at ang drive ay bago)
  3. Simulan ang postgresq
  4. Magsisimula ang serbisyo sa pagpapanumbalik. Ito ay kinakailangan upang ihanda ang zabbix mismo at ang database nito:
    • Sinusuri kung mayroon nang database ng zabbix. Kung hindi, ito ay ginawa mula sa initialization dumps (kasama sa zabbix)
    • isang listahan ng mga time zone ay nilikha (kinakailangan upang ipakita ang mga ito sa web interface)
    • Ang kasalukuyang IP ay natagpuan, ito ay ipinapakita sa isyu (imbitasyon upang mag-log in sa console)
  5. Nagbabago ang imbitasyon - lumalabas ang pariralang Handa nang magtrabaho
  6. Handa nang gamitin ang firmware

Ang mga file ng serbisyo ay mahalaga, sila ang nagtatakda ng pagkakasunud-sunod ng kanilang paglulunsad

[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

Tulad ng nakikita mo, nag-install ako ng mga dependencies upang ang aking script ay unang gumana, at pagkatapos lamang ang network ay tataas at ang DBMS ay magsisimula.

At ang pangalawang serbisyo (paghahanda ng 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.target

Ito ay medyo mas kumplikado dito. Ang paglulunsad ay nasa multi-user.target din, ngunit PAGKATAPOS simulan ang postgresql DBMS at ang aking setting_restore. Ngunit BAGO simulan ang mga serbisyo ng zabbix.

Serbisyo ng timer para sa logrotate

Maaaring palitan ng Systemd ang CRON. Seryoso. Bukod dito, ang katumpakan ay hindi hanggang sa minuto, ngunit hanggang sa pangalawa (paano kung kinakailangan). O maaari kang lumikha ng isang monotonous na timer, na tinatawag ng isang timeout mula sa isang kaganapan.
Ito ay ang monotonous timer na nagbibilang ng oras mula sa simula ng machine na ginawa ko.
Mangangailangan ito ng 2 file
logrotateTimer.service - ang aktwal na paglalarawan ng serbisyo:

[Unit]
Description=run logrotate

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

Ito ay simple - paglalarawan ng utos ng paglunsad.
Ang pangalawang file logrotateTimer.timer ay kung saan gumagana ang mga timer:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Anong meron dito:

  • paglalarawan ng timer
  • Unang oras ng pagsisimula, simula sa system boot
  • panahon ng karagdagang paglulunsad
  • Dependency sa serbisyo ng timer. Sa katunayan, ito ang string na gumagawa ng timer

Interactive na script kapag nagsasara at ang iyong target sa pag-shutdown

Sa isa pang pag-unlad, kailangan kong gumawa ng isang mas kumplikadong bersyon ng pag-off ng makina - sa pamamagitan ng sarili kong target, upang maisagawa ang maraming aksyon. Karaniwang inirerekomenda na lumikha ng oneshot na serbisyo gamit ang RemainAfterExit na opsyon, ngunit pinipigilan ka nitong lumikha ng interactive na script.

Ngunit ang katotohanan ay ang mga utos na inilunsad ng opsyon na ExecOnStop ay isinasagawa sa labas ng TTY! Madaling suriin - i-paste ang tty command at i-save ang output nito.

Samakatuwid, ipinatupad ko ang shutdown sa pamamagitan ng aking target. Hindi ko sinasabing 100% tama, ngunit gumagana ito!
Paano ito ginawa (sa mga pangkalahatang tuntunin):
Gumawa ako ng target na my_shutdown.target, na hindi nakadepende sa sinuman:
my_shutdown.target

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

Sa pagpunta sa target na ito (sa pamamagitan ng systemctl isolate my_shutdwn.target), inilunsad nito ang my_shutdown.service service, ang gawain na kung saan ay simple - upang maisagawa ang my_shutdown.sh script:

[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

  • Sa loob ng script na ito ginagawa ko ang mga kinakailangang aksyon. Maaari kang magdagdag ng maraming script sa target para sa flexibility at kaginhawahan:

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

Tandaan. Gamit ang /tmp/reboot at /tmp/shutdown file. Hindi ka makakatawag ng target na may mga parameter. Serbisyo lamang ang posible.

Ngunit ginagamit ko ang target upang magkaroon ng flexibility sa trabaho at isang garantisadong pagkakasunud-sunod ng mga aksyon.

Gayunpaman, ang pinaka-kagiliw-giliw na bagay ay dumating sa ibang pagkakataon. Kailangang patayin/i-restart ang makina. At mayroong 2 pagpipilian:

  • Palitan ang reboot, shutdown at iba pang mga command (mga symlink pa rin sila sa systemctl) ng iyong script. Sa loob ng script, pumunta sa my_shutdown.target. At ang mga script sa loob ng target pagkatapos ay direktang tumawag sa systemctl, halimbawa, systemctl reboot
  • Isang mas simpleng opsyon, ngunit hindi ko ito gusto. Sa lahat ng mga interface, huwag tumawag sa shutdown/reboot/iba pa, ngunit direktang tawagan ang target systemctl ihiwalay my_shutdown.target

Pinili ko ang unang pagpipilian. Sa systemd, ang reboot (tulad ng poweroff) ay mga symlink sa systemd.

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

Samakatuwid, maaari mong palitan ang mga ito ng iyong sariling mga script:
i-reboot

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

Pinagmulan: www.habr.com

Magdagdag ng komento