Системски, интерактивни скрипти и тајмери

Системски, интерактивни скрипти и тајмери

Вовед

Кога се развивате за Linux, се наметнува задачата за создавање интерактивни скрипти кои се извршуваат кога системот е вклучен или исклучен. Во системот V ова беше лесно, но со systemd прави прилагодувања. Но, може да има свои тајмери.

Зошто ни се потребни цели?

Често се пишува дека целта служи како аналог на рачно ниво во системот V-init. Во основа не се согласувам. Има повеќе од нив и можете да ги поделите пакетите во групи и, на пример, да стартувате група услуги со една команда и да извршите дополнителни дејства. Згора на тоа, тие немаат хиерархија, само зависности.

Пример за цел кога е овозможено (преглед на функции) со вклучена интерактивна скрипта

Опис на самата цел:

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

Оваа цел ќе започне кога ќе се стартува multi-user.target и ќе го повика installer.service. Сепак, може да има неколку такви услуги.

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

И, конечно, пример на скрипта што се извршува:

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

Најважно е да се избере final.target - целта до која системот треба да пристигне при стартување. За време на процесот на стартување, systemd ќе помине низ зависностите и ќе стартува сè што му треба.
Постојат различни начини за избор на final.target, јас ја користев опцијата loader за ова.

Конечното лансирање изгледа вака:

  1. Подигнувачот започнува
  2. Подигнувачот започнува со лансирање на фирмверот со предавање на параметарот final.target
  3. Systemd започнува да го стартува системот. Секвенцијално оди до installer.target или work.target од basic.target преку нивните зависности (на пример, multi-user.target). Вторите го доведуваат системот да работи во саканиот режим

Подготовка на фирмверот за лансирање

Кога креирате фирмвер, секогаш се поставува задачата да се врати состојбата на системот при стартување и да се зачува при исклучување. Состојба значи конфигурациски датотеки, депонии од базата на податоци, поставки за интерфејс итн.

Systemd ги извршува процесите во истата цел паралелно. Постојат зависности кои ви дозволуваат да ја одредите низата на стартување на скрипти.

Како функционира во мојот проект ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Системот започнува
  2. Се активира услугата settings_restore.service, која проверува присуство на датотеката settings.txt во делот за податоци. Ако не е таму, тогаш на негово место се става референтна датотека. Следно, системските поставки се враќаат:
    • администраторска лозинка
    • име на домаќин,
    • временска зона
    • локација
    • Определува дали се користат сите медиуми. Стандардно, големината на сликата е мала - за полесно копирање и снимање на медиум. При стартување, проверува дали сè уште има неискористен простор. Ако има, дискот се репартиционира.
    • Генерирање машински ID од MAC адреса. Ова е важно за добивање на истата адреса преку DHCP
    • Мрежни поставки
    • Ја ограничува големината на трупците
    • Надворешниот погон се подготвува за работа (доколку е овозможена соодветната опција и уредот е нов)
  3. Започнете postgresq
  4. Услугата за обновување започнува. Потребно е да се подготви самиот zabbix и неговата база на податоци:
    • Проверува дали веќе постои zabbix база на податоци. Ако не, тој е создаден од депонии за иницијализација (вклучено со zabbix)
    • се креира листа на временски зони (потребни за да се прикажат во веб-интерфејсот)
    • Тековната IP адреса е пронајдена, таа е прикажана во прашање (покана за најавување на конзолата)
  5. Поканата се менува - се појавува фразата Ready to work
  6. Фирмверот е подготвен за употреба

Сервисните датотеки се важни, тие се оние што ја поставуваат низата на нивното лансирање

[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

Како што можете да видите, инсталирав зависности за да ми работи прво скриптата, па дури потоа мрежата да се качи и да започне DBMS.

И втората услуга (подготовка на 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

Овде е малку покомплицирано. Лансирањето е исто така во multi-user.target, но ОТКАКО ги стартував postgresql DBMS и мојот setting_restore. Но, ПРЕД да започнете zabbix услуги.

Услуга за тајмер за логротат

Systemd може да го замени CRON. Сериозно. Згора на тоа, точноста не е до минута, туку до секунда (што ако е потребно) Или можете да креирате монотон тајмер, повикан со тајмаут од настан.
Монотониот тајмер го брои времето од почетокот на машината што ја создадов.
За ова ќе бидат потребни 2 датотеки
logrotateTimer.service - вистинскиот опис на услугата:

[Unit]
Description=run logrotate

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

Едноставно е - опис на командата за лансирање.
Втората датотека logrotateTimer.timer е местото каде што работат тајмерите:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Што има тука:

  • опис на тајмерот
  • Прво време на стартување, почнувајќи од системот за подигање
  • период на понатамошни лансирања
  • Зависност од услугата на тајмерот Всушност, ова е низата што го прави тајмерот

Интерактивна скрипта при исклучување и вашата цел за исклучување

Во друг развој, морав да направам посложена верзија на исклучување на машината - преку мојата цел, за да извршам многу дејства. Обично се препорачува да креирате услуга oneshot со опцијата RemainAfterExit, но тоа ве спречува да креирате интерактивна скрипта.

Но, факт е дека командите лансирани од опцијата ExecOnStop се извршуваат надвор од TTY! Лесно е да се провери - залепете ја командата tty и зачувајте го нејзиниот излез.

Затоа, го спроведов исклучувањето преку мојата цел. Не тврдам дека сум 100% точен, но функционира!
Како беше направено (во општи термини):
Создадов цел my_shutdown.target, што не зависеше од никого:
my_shutdown.цел

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

Кога се оди до оваа цел (преку systemctl изолира my_shutdwn.target), ја лансираше услугата my_shutdown.service, чија задача е едноставна - да ја изврши скриптата 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

  • Внатре во оваа скрипта ги извршувам потребните дејства. Можете да додадете многу скрипти на целта за флексибилност и погодност:

my_shutdown.ш

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

Забелешка. Користење на датотеките /tmp/reboot и /tmp/shutdown. Не можете да ја повикате целта со параметри. Можна е само услуга.

Но, јас ја користам целта за да имам флексибилност во работата и загарантиран редослед на акции.

Сепак, најинтересното се случи подоцна. Машината треба да се исклучи/рестартира. И има 2 опции:

  • Заменете ги наредбите за рестартирање, исклучување и други команди (тие сè уште се симболи на systemctl) со вашата скрипта. Внатре во скриптата, одете на my_shutdown.target. И скриптите внатре во целта потоа директно повикуваат systemctl, на пример, systemctl рестартирање
  • Поедноставна опција, но не ми се допаѓа. Во сите интерфејси, не повикувајте исклучување/рестартирање/друго, туку директно повикајте го целниот системctl изолирајте my_shutdown.target

Ја избрав првата опција. Во systemd, рестартирањето (како исклучувањето) се симболи на системот.

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

Затоа, можете да ги замените со свои скрипти:
се рестартира

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

Извор: www.habr.com

Додадете коментар