Systemderede, interaktive scripts og timere

Systemderede, interaktive scripts og timere

Indledning

Ved udvikling til Linux opstår opgaven med at skabe interaktive scripts, der udføres, når systemet tændes eller lukkes ned. I system V var dette nemt, men med systemd foretager det justeringer. Men den kan have sine egne timere.

Hvorfor har vi brug for mål?

Det skrives ofte, at målet fungerer som en analog af runlevel i system V -init. Jeg er grundlæggende uenig. Der er flere af dem, og du kan opdele pakker i grupper og for eksempel starte en gruppe tjenester med én kommando og udføre yderligere handlinger. Desuden har de intet hierarki, kun afhængigheder.

Eksempel på mål, når det er aktiveret (funktionsoversigt) med kørende interaktivt script

Beskrivelse af 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ål starter, når multi-user.target startes og kalder installer.service. Der kan dog være flere sådanne 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 sidst et eksempel på, at scriptet bliver udført:

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

Det vigtigste er at vælge final.target - det mål som systemet skal nå frem til ved opstart. Under opstartsprocessen vil systemd gennemgå afhængighederne og starte alt, hvad det har brug for.
Der er forskellige måder at vælge final.target på, jeg brugte loader-indstillingen til dette.

Den endelige lancering ser således ud:

  1. Bootloaderen starter
  2. Bootloaderen starter lanceringen af ​​firmwaren ved at sende parameteren final.target
  3. Systemd begynder at starte systemet. Går sekventielt til installer.target eller work.target fra basic.target gennem deres afhængigheder (f.eks. multi-user.target). Sidstnævnte bringer systemet til at arbejde i den ønskede tilstand

Forberedelse af firmwaren til lancering

Ved oprettelse af firmware opstår altid opgaven med at gendanne systemtilstanden ved opstart og gemme den ved nedlukning. Tilstand betyder konfigurationsfiler, databasedumps, grænsefladeindstillinger osv.

Systemd kører processer i samme mål parallelt. Der er afhængigheder, der giver dig mulighed for at bestemme opstartssekvensen af ​​scripts.

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

  1. Systemet starter
  2. Tjenesten settings_restore.service startes. Den kontrollerer tilstedeværelsen af ​​filen settings.txt i dataafsnittet. Hvis den ikke er der, sættes en referencefil i stedet for. Dernæst gendannes systemindstillingerne:
    • administratoradgangskode
    • værtsnavn
    • tidszone
    • lokalitet
    • Bestemmer, om alle medier bliver brugt. Som standard er billedstørrelsen lille - for at lette kopiering og optagelse til medier. Ved opstart tjekker den, om der stadig er ubrugt plads. Hvis der er, ompartitioneres disken.
    • Generering af maskin-id fra MAC-adresse. Dette er vigtigt for at opnå den samme adresse via DHCP
    • Netværks indstillinger
    • Begrænser størrelsen af ​​logs
    • Det eksterne drev forberedes til arbejde (hvis den tilsvarende indstilling er aktiveret, og drevet er nyt)
  3. Start postgresq
  4. Gendannelsestjenesten starter. Det er nødvendigt for at forberede selve zabbix og dens database:
    • Kontrollerer, om der allerede er en zabbix-database. Hvis ikke, er den oprettet fra initialiseringsdumps (inkluderet med zabbix)
    • en liste over tidszoner oprettes (nødvendig for at vise dem i webgrænsefladen)
    • Den aktuelle IP er fundet, den vises i udsendelsen (invitation til at logge ind på konsollen)
  5. Invitationen ændres - sætningen Klar til arbejde vises
  6. Firmwaren er klar til brug

Tjenestefilerne er vigtige, det er dem, der bestemmer rækkefølgen af ​​deres lancering

[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, installerede jeg afhængigheder, så mit script først ville virke, og først derefter ville netværket gå op, og DBMS ville starte.

Og den anden service (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 lidt mere kompliceret her. Lanceringen er også i multi-user.target, men EFTER start af postgresql DBMS og min setting_restore. Men FØR du starter zabbix-tjenester.

Timer service til logrotate

Systemd kan erstatte CRON. Helt seriøst. Desuden er nøjagtigheden ikke op til minuttet, men op til sekundet (hvad nu hvis det er nødvendigt), eller du kan oprette en monoton timer, kaldet af en timeout fra en begivenhed.
Det var den monotone timer, der tæller tiden fra starten af ​​den maskine, jeg oprettede.
Dette kræver 2 filer
logrotateTimer.service - den faktiske beskrivelse af tjenesten:

[Unit]
Description=run logrotate

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

Det er enkelt - beskrivelse af startkommandoen.
Den anden fil logrotateTimer.timer er, hvor timerne fungerer:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Hvad er her:

  • timer beskrivelse
  • Første starttidspunkt, startende fra systemstart
  • periode med yderligere lanceringer
  • Afhængighed af timertjenesten. Faktisk er dette den streng, der laver timeren

Interaktivt script ved nedlukning og dit nedlukningsmål

I en anden udvikling skulle jeg lave en mere kompleks version af at slukke for maskinen – gennem mit eget mål, for at kunne udføre mange handlinger. Det anbefales normalt at oprette en oneshot-tjeneste med muligheden RemainAfterExit, men dette forhindrer dig i at oprette et interaktivt script.

Men faktum er, at de kommandoer, der startes af ExecOnStop-indstillingen, udføres uden for TTY! Det er nemt at kontrollere - indsæt tty-kommandoen og gem dens output.

Derfor implementerede jeg nedlukningen gennem mit mål. Jeg hævder ikke at være 100% korrekt, men det virker!
Hvordan det blev gjort (i generelle vendinger):
Jeg oprettede et mål my_shutdown.target, som ikke afhang af nogen:
my_shutdown.target

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

Når du går til dette mål (via systemctl isolate my_shutdwn.target), lancerede den tjenesten my_shutdown.service, hvis opgave er enkel - at udføre my_shutdown.sh scriptet:

[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

  • Inde i dette script udfører jeg de nødvendige handlinger. Du kan tilføje mange scripts til målet for fleksibilitet og bekvemmelighed:

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

Bemærk. Brug af filerne /tmp/reboot og /tmp/shutdown. Du kan ikke kalde mål med parametre. Kun service er mulig.

Men jeg bruger target til at have fleksibilitet i arbejdet og en garanteret rækkefølge af handlinger.

Det mest interessante kom dog senere. Maskinen skal slukkes/genstartes. Og der er 2 muligheder:

  • Erstat genstart, shutdown og andre kommandoer (de er stadig symbolske links til systemctl) med dit script. Gå til my_shutdown.target inde i scriptet. Og scripts inde i målet kalder derefter systemctl direkte, for eksempel systemctl genstart
  • En enklere mulighed, men jeg kan ikke lide den. I alle grænseflader skal du ikke kalde shutdown/reboot/other, men direkte kald målsystemetctl isolate my_shutdown.target

Jeg valgte den første mulighed. I systemd er genstart (som poweroff) symbolske links 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 scripts:
genstarte

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

Kilde: www.habr.com

Tilføj en kommentar