Systembaserte, interaktive skript og tidtakere

Systembaserte, interaktive skript og tidtakere

Innledning

Ved utvikling for Linux oppstår oppgaven med å lage interaktive skript som kjøres når systemet slås på eller slås av. I system V var dette enkelt, men med systemd gjør det justeringer. Men den kan ha sine egne tidtakere.

Hvorfor trenger vi mål?

Det skrives ofte at målet fungerer som en analog av runlevel i system V -init. Jeg er grunnleggende uenig. Det er flere av dem og du kan dele pakker inn i grupper og for eksempel starte en gruppe tjenester med én kommando og utføre ytterligere handlinger. Dessuten har de ikke noe hierarki, bare avhengigheter.

Eksempel på mål når aktivert (funksjonsoversikt) med kjørende interaktivt skript

Beskrivelse av selve målet:

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

Dette målet starter når multi-user.target startes og kaller installer.service. Det kan imidlertid være flere slike tjenester.

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

Og til slutt, et eksempel på at skriptet blir utført:

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

Det viktigste er å velge final.target - målet som systemet skal komme til ved oppstart. Under oppstartsprosessen vil systemd gå gjennom avhengighetene og starte alt det trenger.
Det er forskjellige måter å velge final.target på, jeg brukte loader-alternativet for dette.

Den endelige lanseringen ser slik ut:

  1. Oppstartslasteren starter
  2. Oppstartslasteren starter oppstart av fastvaren ved å sende parameteren final.target
  3. Systemd begynner å starte systemet. Går sekvensielt til installer.target eller work.target fra basic.target gjennom deres avhengigheter (for eksempel multi-user.target). Sistnevnte bringer systemet til å fungere i ønsket modus

Forbereder fastvaren for lansering

Når du oppretter fastvare, oppstår alltid oppgaven med å gjenopprette systemtilstanden ved oppstart og lagre den ved avslutning. Tilstand betyr konfigurasjonsfiler, databasedumper, grensesnittinnstillinger osv.

Systemd kjører prosesser i samme mål parallelt. Det er avhengigheter som lar deg bestemme oppstartssekvensen til skript.

Hvordan fungerer det i prosjektet mitt ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Systemet starter
  2. Tjenesten settings_restore.service startes. Den sjekker for tilstedeværelsen av filen settings.txt i datadelen. Hvis den ikke er der, plasseres en referansefil i stedet. Deretter gjenopprettes systeminnstillingene:
    • administratorpassord
    • vertsnavn
    • tidssone
    • lokalitet
    • Bestemmer om alle medier brukes. Som standard er bildestørrelsen liten - for enkel kopiering og opptak til media. Ved oppstart sjekker den om det fortsatt er ubrukt plass. Hvis det er det, partisjoneres disken på nytt.
    • Genererer maskin-ID fra MAC-adresse. Dette er viktig for å få samme adresse via DHCP
    • Nettverksinnstillinger
    • Begrenser størrelsen på logger
    • Den eksterne stasjonen forberedes for arbeid (hvis det tilsvarende alternativet er aktivert og stasjonen er ny)
  3. Start postgresq
  4. Gjenopprettingstjenesten starter. Det er nødvendig for å forberede selve zabbix og dens database:
    • Sjekker om det allerede finnes en zabbix-database. Hvis ikke, er den opprettet fra initialiseringsdumper (inkludert med zabbix)
    • en liste over tidssoner opprettes (nødvendig for å vise dem i nettgrensesnittet)
    • Den nåværende IP-en er funnet, den vises i utstedt (invitasjon til å logge på konsollen)
  5. Invitasjonen endres - uttrykket Klar til å jobbe vises
  6. Fastvaren er klar til bruk

Tjenestefilene er viktige, det er de som setter rekkefølgen på lanseringen

[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

Som du kan se, installerte jeg avhengigheter slik at skriptet mitt først ville fungere, og først da ville nettverket gå opp og DBMS ville starte.

Og den andre gudstjenesten (zabbix-forberedelse)

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

Det er litt mer komplisert her. Lanseringen er også i multi-user.target, men ETTER å ha startet postgresql DBMS og min setting_restore. Men FØR du starter zabbix-tjenester.

Timertjeneste for logrotate

Systemd kan erstatte CRON. Alvor. Dessuten er nøyaktigheten ikke opp til minuttet, men opp til sekundet (hva om det er nødvendig), eller du kan lage en monoton timer, kalt av en timeout fra en hendelse.
Det var den monotone timeren som teller tiden fra starten av maskinen jeg opprettet.
Dette vil kreve 2 filer
logrotateTimer.service - den faktiske beskrivelsen av tjenesten:

[Unit]
Description=run logrotate

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

Det er enkelt - beskrivelse av startkommandoen.
Den andre filen logrotateTimer.timer er der tidtakerne fungerer:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Hva er her:

  • tidtakerbeskrivelse
  • Første starttidspunkt, starter fra systemoppstart
  • periode med ytterligere lanseringer
  • Avhengighet av timertjenesten. Faktisk er dette strengen som lager timeren

Interaktivt skript når du slår av og nedleggelsesmålet ditt

I en annen utvikling måtte jeg gjøre en mer kompleks versjon av å slå av maskinen – gjennom mitt eget mål, for å kunne utføre mange handlinger. Det anbefales vanligvis å lage en oneshot-tjeneste med alternativet RemainAfterExit, men dette hindrer deg i å lage et interaktivt skript.

Men faktum er at kommandoene som lanseres av ExecOnStop-alternativet, utføres utenfor TTY! Det er enkelt å sjekke - lim inn tty-kommandoen og lagre utdataene.

Derfor implementerte jeg nedleggelsen gjennom målet mitt. Jeg påstår ikke å være 100% riktig, men det fungerer!
Hvordan det ble gjort (i generelle termer):
Jeg opprettet et mål my_shutdown.target, som ikke var avhengig av noen:
my_shutdown.target

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

Når du går til dette målet (via systemctl isolate my_shutdwn.target), lanserte den tjenesten my_shutdown.service, hvis oppgave er enkel - å utføre my_shutdown.sh-skriptet:

[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

  • Inne i dette skriptet utfører jeg de nødvendige handlingene. Du kan legge til mange skript til målet for fleksibilitet og bekvemmelighet:

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

Merk. Bruke filene /tmp/reboot og /tmp/shutdown. Du kan ikke kalle mål med parametere. Kun service er mulig.

Men jeg bruker target for å ha fleksibilitet i arbeidet og en garantert handlingsrekkefølge.

Det mest interessante kom imidlertid senere. Maskinen må slås av/startes på nytt. Og det er 2 alternativer:

  • Erstatt reboot, shutdown og andre kommandoer (de er fortsatt symbolske lenker til systemctl) med skriptet ditt. Inne i skriptet, gå til my_shutdown.target. Og skriptene inne i målet kaller da systemctl direkte, for eksempel systemctl reboot
  • Et enklere alternativ, men jeg liker det ikke. I alle grensesnitt, ikke kall shutdown/reboot/other, men direkte kall målsystemetctl isolate my_shutdown.target

Jeg valgte det første alternativet. I systemd er omstart (som poweroff) symbolkoblinger til systemd.

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

Derfor kan du erstatte dem med dine egne skript:
omstart

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

Kilde: www.habr.com

Legg til en kommentar