Systemd, scripts interattivi è timers

Systemd, scripts interattivi è timers

Introduzione

Quandu u sviluppu per Linux, u compitu di creà scripts interattivi chì sò eseguiti quandu u sistema hè attivatu o chjusu sorge. In u sistema V questu era faciule, ma cù systemd faci aghjustamenti. Ma pò avè u so propiu timer.

Perchè avemu bisognu di mira ?

Hè spessu scrittu chì u target serve cum'è un analogu di runlevel in u sistema V -init. Fundamentalmente ùn sò d'accordu. Ci sò più di elli è pudete dividisce i pacchetti in gruppi è, per esempiu, lanciate un gruppu di servizii cù un cumandamentu è eseguite azzioni supplementari. Inoltre, ùn anu micca gerarchia, solu dipendenze.

Esempiu di destinazione quandu attivatu (panoramica di e funzioni) cù script interattivu in esecuzione

Descrizzione di u scopu stessu:

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

Stu scopu principia quandu multi-user.target hè lanciatu è chjama installer.service. Tuttavia, ci ponu esse parechji tali servizii.

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

È infine, un esempiu di u script chì hè eseguitu:

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

A più impurtante hè di selezziunà final.target - u scopu à quale u sistema deve ghjunghje à l'iniziu. Durante u prucessu di startup, systemd passerà per e dipendenze è lanciarà tuttu ciò chì hà bisognu.
Ci hè parechje manere di selezziunà final.target, aghju utilizatu l'opzione di caricatore per questu.

U lanciu finale hè cusì:

  1. U bootloader principia
  2. U bootloader accumincia a lanciari u firmware passendu u paràmetru final.target
  3. Systemd principia à inizià u sistema. Sequentially va à installer.target o work.target da basic.target attraversu e so dependenze (per esempiu, multi-user.target). L'ultimi portanu u sistema à travaglià in u modu desideratu

Preparazione di u firmware per u lanciu

Quandu crea u firmware, u compitu sempre nasce di restaurà u statu di u sistema à l'iniziu è di salvà quandu si chjude. Statu significa schedarii di cunfigurazione, dumps di basa di dati, paràmetri di l'interfaccia, etc.

Systemd esegue i prucessi in u stessu scopu in parallelu. Ci sò dipendenze chì permettenu di determinà a sequenza di startup di scripts.

Cumu funziona in u mo prughjettu ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. U sistema principia
  2. Hè lanciatu u serviziu settings_restore.service, verifica a presenza di u schedariu settings.txt in a sezione di dati. Se ùn hè micca quì, allora un schedariu di riferimentu hè piazzatu in u so locu, dopu, i paràmetri di u sistema sò restaurati:
    • password amministratore
    • hostname,
    • fusu orariu
    • locale
    • Determina se tutti i media sò usati. Per automaticamente, a dimensione di l'imaghjini hè chjuca - per facilità di copia è arregistramentu à i media. À l'iniziu, verifica per vede s'ellu ci hè ancu spaziu inutilizatu. Se ci hè, u discu hè ripartizione.
    • Generating machine-id da l'indirizzu MAC. Questu hè impurtante per ottene u stessu indirizzu via DHCP
    • Paràmetri di a rete
    • Limita a dimensione di logs
    • L'unità esterna hè stata preparata per u travagliu (se l'opzione currispondente hè attivata è l'unità hè nova)
  3. Cumincià postgresq
  4. U serviziu di restaurazione principia. Hè necessariu di preparà zabbix stessu è a so basa di dati:
    • Verifica s'ellu ci hè digià una basa di dati zabbix. Se no, hè creatu da dumps d'inizializazione (inclusi cù zabbix)
    • una lista di fusi orari hè creatu (necessariu per vede in l'interfaccia web)
    • L'IP attuale hè trovata, hè visualizata in u prublema (invitu à accede à a cunsola)
  5. L'invitu cambia - a frasa Ready to work appare
  6. U firmware hè prontu per l'usu

I schedarii di serviziu sò impurtanti, sò quelli chì stabiliscenu a sequenza di u so lanciamentu

[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

Comu pudete vede, aghju installatu dependenzii in modu chì u mo script hà da travaglià prima, è solu allora a reta cullà è u DBMS principia.

È u sicondu serviziu (preparazione 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

Hè un pocu più cumplicatu quì.U lanciamentu hè ancu in multi-user.target, ma DOPO avè principiatu u DBMS postgresql è u mo setting_restore. Ma prima di inizià i servizii di zabbix.

Serviziu di timer per logrotate

Systemd pò rimpiazzà CRON. Seriu. Inoltre, a precisione ùn hè micca finu à u minutu, ma finu à u sicondu (chì s'ellu hè necessariu) O pudete creà un timer monotonu, chjamatu da un timeout da un avvenimentu.
Era u timer monotonu chì conta u tempu da u principiu di a macchina chì aghju creatu.
Questu averebbe bisognu di 2 schedari
logrotateTimer.service - a descrizzione attuale di u serviziu:

[Unit]
Description=run logrotate

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

Hè simplice - descrizzione di u cumandamentu di lanciamentu.
U sicondu schedariu logrotateTimer.timer hè induve i timers travaglianu:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Chì ci hè quì:

  • descrizzione di u timer
  • Prima ora di partenza, partendu da u boot di u sistema
  • periodo di ulteriori lanci
  • Dipendenza di u serviziu di timer.In fattu, questu hè a stringa chì face u timer

Scrittura interattiva quandu si chjude è u vostru scopu di chjusu

In un altru sviluppu, aghju avutu à fà una versione più cumplessa di disattivà a macchina - attraversu u mo propiu scopu, per fà parechje azzioni. Di solitu hè cunsigliatu per creà un serviziu oneshot cù l'opzione RemainAfterExit, ma questu impedisce di creà un script interattivu.

Ma u fattu hè chì i cumandamenti lanciati da l'opzione ExecOnStop sò eseguiti fora di u TTY! Hè faciule di verificà - incollà u cumandamentu tty è salvà a so output.

Dunque, aghju implementatu l'arrestu attraversu u mo mira. Ùn dicenu micca esse 100% currettu, ma funziona!
Cumu hè statu fattu (in termini generale):
Aghju creatu un target my_shutdown.target, chì ùn dipende micca di nimu:
my_shutdown.target

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

Quandu andava à questu scopu (via systemctl isolate my_shutdwn.target), hà lanciatu u serviziu my_shutdown.service, u so compitu hè simplice - per eseguisce u 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

  • Dentru stu script aghju realizatu l'azzioni necessarii. Pudete aghjunghje parechji script à u target per flessibilità è comodità:

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. Utilizendu i schedarii /tmp/reboot è /tmp/shutdown. Ùn pudete micca chjamà target cù parametri. Solu u serviziu hè pussibule.

Ma aghju utilizatu u mira per avè flessibilità in u travagliu è un ordine garantitu di l'azzioni.

Tuttavia, u più interessante hè vinutu dopu. A macchina deve esse disattivata / riavviata. È ci sò 2 opzioni:

  • Sustituisci u reboot, shutdown è altri cumandamenti (sò sempre ligami simbolichi à systemctl) cù u vostru script.Intra u script, andate à my_shutdown.target. È i scripts in u target poi chjamanu systemctl direttamente, per esempiu, systemctl reboot
  • Una opzione più simplice, ma ùn mi piace micca. In tutte l'interfaccia, ùn chjamate micca shutdown / reboot / other, ma chjamate direttamente u sistema di destinazione isolate my_shutdown.target

Aghju sceltu a prima opzione. In systemd, reboot (cum'è poweroff) sò ligami simbolichi à systemd.

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

Dunque, pudete rimpiazzà cù i vostri scripts:
reboot

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

Source: www.habr.com

Add a comment