Вовед
Кога се развивате за 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 за ова.
Конечното лансирање изгледа вака:
- Подигнувачот започнува
- Подигнувачот започнува со лансирање на фирмверот со предавање на параметарот final.target
- Systemd започнува да го стартува системот. Секвенцијално оди до installer.target или work.target од basic.target преку нивните зависности (на пример, multi-user.target). Вторите го доведуваат системот да работи во саканиот режим
Подготовка на фирмверот за лансирање
Кога креирате фирмвер, секогаш се поставува задачата да се врати состојбата на системот при стартување и да се зачува при исклучување. Состојба значи конфигурациски датотеки, депонии од базата на податоци, поставки за интерфејс итн.
Systemd ги извршува процесите во истата цел паралелно. Постојат зависности кои ви дозволуваат да ја одредите низата на стартување на скрипти.
Како функционира во мојот проект (
- Системот започнува
- Се активира услугата settings_restore.service, која проверува присуство на датотеката settings.txt во делот за податоци. Ако не е таму, тогаш на негово место се става референтна датотека. Следно, системските поставки се враќаат:
- администраторска лозинка
- име на домаќин,
- временска зона
- локација
- Определува дали се користат сите медиуми. Стандардно, големината на сликата е мала - за полесно копирање и снимање на медиум. При стартување, проверува дали сè уште има неискористен простор. Ако има, дискот се репартиционира.
- Генерирање машински ID од MAC адреса. Ова е важно за добивање на истата адреса преку DHCP
- Мрежни поставки
- Ја ограничува големината на трупците
- Надворешниот погон се подготвува за работа (доколку е овозможена соодветната опција и уредот е нов)
- Започнете postgresq
- Услугата за обновување започнува. Потребно е да се подготви самиот zabbix и неговата база на податоци:
- Проверува дали веќе постои zabbix база на податоци. Ако не, тој е создаден од депонии за иницијализација (вклучено со zabbix)
- се креира листа на временски зони (потребни за да се прикажат во веб-интерфејсот)
- Тековната IP адреса е пронајдена, таа е прикажана во прашање (покана за најавување на конзолата)
- Поканата се менува - се појавува фразата Ready to work
- Фирмверот е подготвен за употреба
Сервисните датотеки се важни, тие се оние што ја поставуваат низата на нивното лансирање
[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