Systembaserade, interaktiva skript och timers

Systembaserade, interaktiva skript och timers

Inledning

Vid utveckling för Linux uppstår uppgiften att skapa interaktiva skript som exekveras när systemet slås på eller stängs av. I system V var detta enkelt, men med systemd gör det justeringar. Men den kan ha sina egna timers.

Varför behöver vi mål?

Det skrivs ofta att target fungerar som en analog till runlevel i system V -init. Jag håller i grunden inte med. Det finns fler av dem och du kan dela in paket i grupper och till exempel starta en grupp tjänster med ett kommando och utföra ytterligare åtgärder. Dessutom har de ingen hierarki, bara beroenden.

Exempel på mål när det är aktiverat (funktionsöversikt) med ett interaktivt skript som körs

Beskrivning av själva 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

Detta mål startar när multi-user.target startas och anropar installer.service. Det kan dock finnas flera sådana tjänster.

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

Och slutligen, ett exempel på att skriptet körs:

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

Det viktigaste är att välja final.target - målet som systemet ska komma till vid uppstart. Under startprocessen kommer systemd att gå igenom beroenden och starta allt det behöver.
Det finns olika sätt att välja final.target, jag använde loader-alternativet för detta.

Den slutliga lanseringen ser ut så här:

  1. Starthanteraren startar
  2. Starthanteraren börjar starta den fasta programvaran genom att skicka parametern final.target
  3. Systemd börjar starta systemet. Går sekventiellt till installer.target eller work.target från basic.target genom deras beroenden (till exempel multi-user.target). De senare får systemet att fungera i önskat läge

Förbereder firmware för lansering

När du skapar firmware uppstår alltid uppgiften att återställa systemtillståndet vid start och spara det vid avstängning. Tillstånd betyder konfigurationsfiler, databasdumpar, gränssnittsinställningar etc.

Systemd kör processer i samma mål parallellt. Det finns beroenden som låter dig bestämma startsekvensen för skript.

Hur fungerar det i mitt projekt ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Systemet startar
  2. Tjänsten settings_restore.service startas. Den kontrollerar förekomsten av filen settings.txt i datasektionen. Om den inte finns där placeras en referensfil i dess ställe. Därefter återställs systeminställningarna:
    • administratörslösenord
    • värdnamn
    • tidszon
    • plats
    • Avgör om alla media används. Som standard är bildstorleken liten - för att underlätta kopiering och inspelning till media. Vid start kontrollerar den om det fortfarande finns oanvänt utrymme. Om det finns, partitioneras disken om.
    • Genererar maskin-id från MAC-adress. Detta är viktigt för att få samma adress via DHCP
    • Nätverksinställningar
    • Begränsar storleken på stockar
    • Den externa enheten förbereds för arbete (om motsvarande alternativ är aktiverat och enheten är ny)
  3. Börja postgresq
  4. Återställningstjänsten startar. Det behövs för att förbereda själva zabbix och dess databas:
    • Kontrollerar om det redan finns en zabbix-databas. Om inte, skapas den från initialiseringsdumpar (ingår i zabbix)
    • en lista över tidszoner skapas (behövs för att visa dem i webbgränssnittet)
    • Den aktuella IP-adressen hittas, den visas i fråga (inbjudan att logga in på konsolen)
  5. Inbjudan ändras - frasen Redo att arbeta visas
  6. Den fasta programvaran är klar att användas

Tjänstefilerna är viktiga, det är de som anger sekvensen för deras lansering

[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 installerade jag beroenden så att mitt skript först skulle fungera, och först då skulle nätverket gå upp och DBMS skulle starta.

Och den andra tjänsten (zabbix förberedelse)

#!/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 är lite mer komplicerat här. Lanseringen är också i multi-user.target, men EFTER start av postgresql DBMS och min setting_restore. Men INNAN du börjar zabbix tjänster.

Timertjänst för logrotate

Systemd kan ersätta CRON. Allvarligt. Dessutom är noggrannheten inte upp till minut, utan upp till sekunden (tänk om det behövs), eller så kan du skapa en monoton timer, anropad av en timeout från en händelse.
Det var den monotona timern som räknar tiden från starten av maskinen som jag skapade.
Detta kommer att kräva 2 filer
logrotateTimer.service - den faktiska beskrivningen av tjänsten:

[Unit]
Description=run logrotate

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

Det är enkelt - beskrivning av startkommandot.
Den andra filen logrotateTimer.timer är där timers fungerar:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Vad finns här:

  • timer beskrivning
  • Första starttiden, med start från systemstart
  • period av ytterligare lanseringar
  • Beroende på timertjänsten. Det här är faktiskt strängen som gör timern

Interaktivt skript vid avstängning och ditt avstängningsmål

I en annan utveckling var jag tvungen att göra en mer komplex version av att stänga av maskinen – genom mitt eget mål, för att kunna utföra många åtgärder. Det rekommenderas vanligtvis att skapa en oneshot-tjänst med alternativet RemainAfterExit, men detta hindrar dig från att skapa ett interaktivt skript.

Men faktum är att kommandona som startas av ExecOnStop-alternativet exekveras utanför TTY! Det är lätt att kontrollera - klistra in kommandot tty och spara dess utdata.

Därför implementerade jag avstängningen genom mitt mål. Jag påstår mig inte vara 100% korrekt, men det fungerar!
Hur det gjordes (i allmänna termer):
Jag skapade ett mål my_shutdown.target, som inte berodde på någon:
my_shutdown.target

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

När du går till det här målet (via systemctl isolate my_shutdwn.target), startade den tjänsten my_shutdown.service, vars uppgift är enkel - att köra 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

  • Inuti det här skriptet utför jag de nödvändiga åtgärderna. Du kan lägga till många skript till målet för flexibilitet och bekvämlighet:

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

Notera. Använda filerna /tmp/reboot och /tmp/shutdown. Du kan inte anropa mål med parametrar. Endast service är möjlig.

Men jag använder target för att ha flexibilitet i arbetet och en garanterad ordningsföljd.

Det mest intressanta kom dock senare. Maskinen måste stängas av/startas om. Och det finns 2 alternativ:

  • Byt ut kommandona omstart, avstängning och andra kommandon (de är fortfarande symboliska länkar till systemctl) med ditt skript. Inuti skriptet, gå till my_shutdown.target. Och skripten inuti målet anropar sedan systemctl direkt, till exempel systemctl omstart
  • Ett enklare alternativ, men jag gillar det inte. I alla gränssnitt ska du inte anropa shutdown/reboot/other, utan direkt anropa målsystemet ctl isolate my_shutdown.target

Jag valde det första alternativet. I systemd är omstart (som poweroff) symboliska länkar till systemd.

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

Därför kan du ersätta dem med dina egna skript:
omstart

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

Källa: will.com

Lägg en kommentar