Systemd, scripts interactius i temporitzadors

Systemd, scripts interactius i temporitzadors

Introducció

Quan es desenvolupa per a Linux, sorgeix la tasca de crear scripts interactius que s'executen quan el sistema està encès o tancat. Al sistema V això era fàcil, però amb systemd fa ajustos. Però pot tenir els seus propis temporitzadors.

Per què necessitem objectius?

Sovint s'escriu que l'objectiu serveix com a anàleg del nivell d'execució al sistema V -init. No hi estic fonamentalment d'acord. N'hi ha més i podeu dividir paquets en grups i, per exemple, llançar un grup de serveis amb una ordre i realitzar accions addicionals. A més, no tenen jerarquia, només dependències.

Exemple d'objectiu quan està activat (visió general de les funcions) amb un script interactiu en execució

Descripció del propi objectiu:

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

Aquest objectiu començarà quan s'iniciï multi-user.target i cridi a installer.service. Tanmateix, hi pot haver diversos serveis d'aquest tipus.

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

I, finalment, un exemple de l'script que s'està executant:

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

El més important és seleccionar final.target: l'objectiu al qual hauria d'arribar el sistema a l'inici. Durant el procés d'inici, systemd passarà per les dependències i llançarà tot el que necessita.
Hi ha diferents maneres de seleccionar final.target, he utilitzat l'opció del carregador per a això.

El llançament final és així:

  1. S'inicia el carregador d'arrencada
  2. El carregador d'arrencada comença a llançar el microprogramari passant el paràmetre final.target
  3. Systemd comença a iniciar el sistema. Va seqüencialment a installer.target o work.target des de basic.target a través de les seves dependències (per exemple, multi-user.target). Aquests últims fan que el sistema funcioni en el mode desitjat

Preparant el firmware per al llançament

Quan es crea microprogramari, sempre sorgeix la tasca de restaurar l'estat del sistema a l'inici i desar-lo quan s'apaga. Estat significa fitxers de configuració, abocaments de bases de dades, paràmetres de la interfície, etc.

Systemd executa processos al mateix objectiu en paral·lel. Hi ha dependències que us permeten determinar la seqüència d'inici dels scripts.

Com funciona en el meu projecte ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. El sistema comença
  2. S'inicia el servei settings_restore.service, que comprova la presència del fitxer settings.txt a la secció de dades. Si no hi és, es col·loca un fitxer de referència al seu lloc. A continuació, es restaura la configuració del sistema:
    • contrasenya d'administrador
    • nom d'amfitrió,
    • fus horari
    • local
    • Determina si s'utilitzen tots els mitjans. Per defecte, la mida de la imatge és petita, per facilitar la còpia i la gravació al suport. A l'inici, comprova si encara hi ha espai sense utilitzar. Si n'hi ha, el disc es reparticiona.
    • Generant l'identificador de la màquina a partir de l'adreça MAC. Això és important per obtenir la mateixa adreça mitjançant DHCP
    • Configuració de la xarxa
    • Limita la mida dels registres
    • La unitat externa s'està preparant per treballar (si l'opció corresponent està habilitada i la unitat és nova)
  3. Inicieu postgresq
  4. S'inicia el servei de restauració. És necessari per preparar el propi zabbix i la seva base de dades:
    • Comprova si ja hi ha una base de dades zabbix. Si no, es crea a partir dels abocaments d'inicialització (inclosos amb zabbix)
    • es crea una llista de zones horàries (necessàries per mostrar-les a la interfície web)
    • Es troba la IP actual, es mostra en qüestió (invitació per iniciar sessió a la consola)
  5. La invitació canvia: apareix la frase A punt per treballar
  6. El microprogramari està llest per al seu ús

Els fitxers de servei són importants, són els que marquen la seqüència del seu llançament

[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

Com podeu veure, vaig instal·lar dependències perquè el meu script funcionés primer, i només aleshores la xarxa pujaria i s'iniciaria el SGBD.

I el segon servei (preparació de 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

Aquí és una mica més complicat. El llançament també es fa a multi-user.target, però DESPRÉS d'iniciar el SGBD postgresql i el meu setting_restore. Però ABANS d'iniciar els serveis zabbix.

Servei de temporitzador per a logrotate

Systemd pot substituir CRON. De debò. A més, la precisió no està a l'alçada del minut, sinó del segon (i si és necessari) o podeu crear un temporitzador monòton, cridat per un temps d'espera d'un esdeveniment.
Era el temporitzador monòton que compta el temps des de l'inici de la màquina que vaig crear.
Això requerirà 2 fitxers
logrotateTimer.service - la descripció real del servei:

[Unit]
Description=run logrotate

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

És senzill: descripció de l'ordre de llançament.
El segon fitxer logrotateTimer.timer és on funcionen els temporitzadors:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Què hi ha aquí:

  • descripció del temporitzador
  • Primera hora d'inici, començant des de l'arrencada del sistema
  • període de nous llançaments
  • Dependència del servei de temporitzador. De fet, aquesta és la cadena que fa que el temporitzador

Script interactiu quan s'apaga i el seu objectiu de tancament

En un altre desenvolupament, vaig haver de fer una versió més complexa d'apagar la màquina, a través del meu propi objectiu, per tal de realitzar moltes accions. Normalment es recomana crear un servei d'un sol cop amb l'opció RemainAfterExit, però això impedeix crear un script interactiu.

Però el fet és que les ordres llançades per l'opció ExecOnStop s'executen fora del TTY! És fàcil de comprovar: enganxeu l'ordre tty i deseu-ne la sortida.

Per tant, vaig implementar l'aturada a través del meu objectiu. No dic ser 100% correcte, però funciona!
Com es va fer (en termes generals):
Vaig crear un objectiu my_shutdown.target, que no depenia de ningú:
my_shutdown.target

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

En anar a aquest objectiu (mitjançant systemctl isolate my_shutdwn.target), va llançar el servei my_shutdown.service, la tasca del qual és senzilla: executar l'script my_shutdown.sh:

[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

  • Dins d'aquest script faig les accions necessàries. Podeu afegir molts scripts a l'objectiu per obtenir flexibilitat i comoditat:

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

Nota. Utilitzant els fitxers /tmp/reboot i /tmp/shutdown. No podeu trucar a target amb paràmetres. Només el servei és possible.

Però faig servir target per tenir flexibilitat en el treball i un ordre d'accions garantit.

Tanmateix, el més interessant va venir després. La màquina s'ha d'apagar/reiniciar. I hi ha 2 opcions:

  • Substituïu les ordres de reinici, apagat i altres (encara són enllaços simbòlics a systemctl) pel vostre script. Dins de l'script, aneu a my_shutdown.target. I els scripts dins de l'objectiu criden directament a systemctl, per exemple, systemctl reboot
  • Una opció més senzilla, però no m'agrada. En totes les interfícies, no crideu shutdown/reboot/other, sinó que truqueu directament al systemctl objectiu aïllar my_shutdown.target

Vaig triar la primera opció. A systemd, reiniciar (com poweroff) són enllaços simbòlics a systemd.

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

Per tant, podeu substituir-los amb els vostres propis scripts:
reiniciar

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

Font: www.habr.com

Afegeix comentari