Järjestelmälliset, interaktiiviset skriptit ja ajastimet

Järjestelmälliset, interaktiiviset skriptit ja ajastimet

Esittely

Linuxille kehitettäessä syntyy tehtävänä luoda interaktiivisia komentosarjoja, jotka suoritetaan, kun järjestelmä käynnistetään tai sammutetaan. System V:ssä tämä oli helppoa, mutta systemdillä se tekee säädöt. Mutta sillä voi olla omat ajastimet.

Miksi tarvitsemme tavoitteita?

Usein kirjoitetaan, että kohde toimii ajontason analogina järjestelmässä V -init. Olen pohjimmiltaan eri mieltä. Niitä on enemmän ja voit jakaa paketteja ryhmiin ja esimerkiksi käynnistää palveluryhmän yhdellä komennolla ja suorittaa lisätoimintoja. Lisäksi heillä ei ole hierarkiaa, vain riippuvuuksia.

Esimerkki kohteesta, kun se on käytössä (ominaisuuksien yleiskatsaus) käynnissä olevan interaktiivisen komentosarjan kanssa

Kuvaus itse kohteesta:

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

Tämä kohde käynnistyy, kun multi-user.target käynnistetään ja kutsuu installer.servicea. Tällaisia ​​palveluita voi kuitenkin olla useita.

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

Ja lopuksi esimerkki suoritettavasta skriptistä:

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

Tärkeintä on valita final.target - kohde, johon järjestelmän tulee saapua käynnistyksen yhteydessä. Käynnistysprosessin aikana systemd käy läpi riippuvuudet ja käynnistää kaiken tarvitsemansa.
Final.target voidaan valita eri tavoin, käytin tähän loader-vaihtoehtoa.

Lopullinen julkaisu näyttää tältä:

  1. Käynnistyslatain käynnistyy
  2. Käynnistyslatain aloittaa laiteohjelmiston käynnistämisen ohittamalla final.target-parametrin
  3. Systemd alkaa käynnistää järjestelmän. Siirrytään peräkkäin osoitteeseen installer.target tai work.target tiedostosta basic.target niiden riippuvuuksien kautta (esimerkiksi usean käyttäjän.target). Jälkimmäinen saa järjestelmän toimimaan halutussa tilassa

Laiteohjelmiston valmistelu käynnistystä varten

Kun laiteohjelmistoa luodaan, tehtävänä on aina palauttaa järjestelmän tila käynnistyksen yhteydessä ja tallentaa se sammutuksen yhteydessä. Tila tarkoittaa määritystiedostoja, tietokantavedoksia, käyttöliittymäasetuksia jne.

Systemd ajaa prosesseja samassa kohteessa rinnakkain. On riippuvuuksia, joiden avulla voit määrittää komentosarjojen käynnistysjärjestyksen.

Miten se toimii projektissani ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Järjestelmä käynnistyy
  2. Palvelu settings_restore.service käynnistetään, ja se tarkistaa, onko dataosiossa settings.txt-tiedosto. Jos sitä ei ole, sen tilalle asetetaan viitetiedosto. Seuraavaksi järjestelmäasetukset palautetaan:
    • järjestelmänvalvojan salasana
    • isäntänimi,
    • aikavyöhyke
    • alue
    • Määrittää, onko kaikki mediat käytössä. Oletusarvoisesti kuvan koko on pieni - kopioinnin ja medialle tallentamisen helpottamiseksi. Käynnistettäessä se tarkistaa, onko vielä käyttämätöntä tilaa. Jos on, levy osioidaan uudelleen.
    • Luodaan konetunnusta MAC-osoitteesta. Tämä on tärkeää saman osoitteen saamiseksi DHCP:n kautta
    • Verkkoasetukset
    • Rajoittaa tukkien kokoa
    • Ulkoista asemaa valmistellaan käyttöä varten (jos vastaava vaihtoehto on käytössä ja asema on uusi)
  3. Aloita postgresq
  4. Palautuspalvelu alkaa. Sitä tarvitaan itse zabbixin ja sen tietokannan valmistelemiseksi:
    • Tarkistaa, onko zabbix-tietokanta jo olemassa. Jos ei, se luodaan alustusvedoksista (sisältyy zabbixiin)
    • aikavyöhykkeiden luettelo luodaan (tarvitaan niiden näyttämiseksi verkkokäyttöliittymässä)
    • Nykyinen IP löytyy, se näytetään ongelmassa (kutsu kirjautua sisään konsoliin)
  5. Kutsu muuttuu - ilmaus Valmis töihin tulee näkyviin
  6. Laiteohjelmisto on valmis käytettäväksi

Palvelutiedostot ovat tärkeitä, ne määrittävät niiden käynnistysjärjestyksen

[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

Kuten näette, asensin riippuvuuksia, jotta komentosarjani toimisi ensin ja vasta sitten verkko nousi ja DBMS käynnistyy.

Ja toinen palvelu (zabbix-valmistelu)

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

Se on hieman monimutkaisempi tässä. Käynnistys on myös multi-user.targetissa, mutta sen jälkeen, kun olen käynnistänyt postgresql DBMS:n ja my setting_restore. Mutta ENNEN zabbix-palvelujen aloittamista.

Ajastinpalvelu logrotatelle

Systemd voi korvata CRONin. Vakavasti. Lisäksi tarkkuus ei ole minuuttiin, vaan sekuntiin asti (entä jos sitä tarvitaan) Tai voit luoda monotonisen ajastimen, jota kutsuu tapahtuman aikakatkaisu.
Se oli yksitoikkoinen ajastin, joka laskee ajan luomani koneen käynnistymisestä.
Tämä vaatii 2 tiedostoa
logrotateTimer.service - palvelun todellinen kuvaus:

[Unit]
Description=run logrotate

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

Se on yksinkertainen - kuvaus käynnistyskomennosta.
Toinen tiedosto logrotateTimer.timer on paikka, jossa ajastimet toimivat:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Mitä täällä on:

  • ajastimen kuvaus
  • Ensimmäinen käynnistysaika, alkaen järjestelmän käynnistyksestä
  • uusien lanseerausten aika
  • Riippuvuus ajastinpalvelusta. Itse asiassa tämä on merkkijono, joka tekee ajastimen

Interaktiivinen skripti sammutettaessa ja sammutuskohde

Toisessa kehitysvaiheessa minun piti tehdä monimutkaisempi versio koneen sammuttamisesta - oman kohteeni kautta suorittaakseni monia toimintoja. Yleensä suositellaan Oneshot-palvelun luomista RemainAfterExit-vaihtoehdolla, mutta tämä estää sinua luomasta interaktiivista komentosarjaa.

Mutta tosiasia on, että ExecOnStop-vaihtoehdon käynnistämät komennot suoritetaan TTY:n ulkopuolella! Se on helppo tarkistaa - liitä tty-komento ja tallenna sen tulos.

Siksi toteutin sammutuksen kohteeni kautta. En väitä olevani 100% oikeassa, mutta se toimii!
Kuinka se tehtiin (yleisesti):
Loin kohteen my_shutdown.target, joka ei ollut riippuvainen kenestäkään:
my_shutdown.target

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

Kun mennään tähän kohteeseen (systemctl isolate my_shutdwn.target kautta), se käynnisti my_shutdown.service-palvelun, jonka tehtävä on yksinkertainen - suorittaa my_shutdown.sh-skripti:

[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

  • Tämän skriptin sisällä teen tarvittavat toimenpiteet. Voit lisätä useita skriptejä kohteeseen joustavuuden ja mukavuuden vuoksi:

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

Huomautus. Käyttämällä /tmp/reboot- ja /tmp/shutdown-tiedostoja. Kohdetta ei voi kutsua parametreilla. Vain palvelu on mahdollista.

Mutta käytän tavoitetta työn joustavuuden ja taatun toimintajärjestyksen vuoksi.

Mielenkiintoisin asia tuli kuitenkin myöhemmin. Kone on sammutettava/käynnistettävä uudelleen. Ja vaihtoehtoja on 2:

  • Korvaa uudelleenkäynnistys-, shutdown- ja muut komennot (ne ovat silti symlinkkejä systemctl:ään) skriptilläsi. Siirry komentosarjan sisällä osoitteeseen my_shutdown.target. Ja kohteen sisällä olevat komentosarjat kutsuvat sitten systemctl:tä suoraan, esimerkiksi systemctl reboot
  • Yksinkertaisempi vaihtoehto, mutta en pidä siitä. Älä kaikissa liitännöissä kutsu shutdown/reboot/other, vaan kutsu suoraan kohde systemctl isolate my_shutdown.target

Valitsin ensimmäisen vaihtoehdon. Systemd:ssä uudelleenkäynnistys (kuten poweroff) ovat symbolilinkkejä systemd:hen.

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

Siksi voit korvata ne omilla skripteilläsi:
uudelleenkäynnistys

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

Lähde: will.com

Lisää kommentti