Systemd, փոխազդեցության սցենարներ և ժամանակաչափեր

Systemd, փոխազդեցության սցենարներ և ժամանակաչափեր

Ներածություն

Linux-ի համար մշակելու ժամանակ առաջանում են փոխազդեցային սցենարներ, որոնք կատարվում են համակարգի միացման կամ անջատման պահին: System V-ում դա հեշտ էր, բայց systemd-ն իջեցնում է փոփոխություններ: Սակայն այն ունի իր ժամանակաչափերը:

Ինչու են անհրաժեշտ target-ները

Շատերը գրում են, որ target-ները equivalent են system V -init-ի runlevel-ներին: Ես արմատապես համաձայն չեմ: Target-ները ավելի շատ են և հնարավոր է բաժանել փաթեթները խմբերով և, օրինակ, մի հրամանով սկսել ծառայությունների մի խումբ, կատարել լրացուցիչ գործողություններ: Ի վերջո, նրանց մոտ hierarchiya չկա, միայն կախվածություններ:

Target-ի օրինակ միացումը (կենսագրության հնարավորությունները) փոխադրումի փոխազդեցության սցենարի запуска:

Target-ի նկարագրություն:

cat installer.target
[Unit]
Description=Իմ տեղադրիչը
Requires=multi-user.target 
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target 
AllowIsolate=yes
Wants=installer.service

Այս target-ը կսկսվի, երբ multi-user.target-ը գործի մեջ լինի և կհիշեցնի installer.service-ին: Այս ընթացքում կարող է լինել մի քանի նման ծառայություններ:

cat installer.service
[Unit]
# նկարագրություն
Description=տեղադրողի փոխազդեցային երկխոսություն

[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-ը՝ target, որի նպատակն է համակարգը սահմանել, երբ սկսվում է: Systemd-ն գործելու է կախվածությունների երկխոսությամբ և կսկսի անհրաժեշտ ամեն ինչ:
Final.target-ը ընտրել հնարավոր է տարբեր եղանակներով, ես այդ նպատակով օգտագործել եմ բեռնման ընտրեց:

Վերջնական սկսումը նման է:

  1. Գործարկվում է բեռնիչը
  2. Բեռնիչը սկսում է ներբեռնել прошивка-ն, փոխանցելով final.target պարամետրը:
  3. Systemd-ն սկսում է համակարգը գործարկել: Ստիճանաբար գնում է installer.target-ին կամ work.target-ին basic.target-ի միջոցով, նրանց կախվածությունների համար (օրինակ, multi-user.target): Վերջիններս տեղափոխում են համակարգը աշխատանքային ռեժիմի:

Գործարկման համար ներբեռնում

Прошивка-ներ ստեղծելիս միշտ առաջանում է համակարգի վիճակի վերականգնման խնդիր: Այդ վիճակը ենթադրում է կոնֆիգուրացիոն ֆայլեր, տվյալների բազաների դմբփեր, ինտերֆեյսների կարգավորումներ և այլն:

Systemd-ն մեկ target-ում գործընթացները գործարկում է параллельно: Կախվածությունները պարզեցնում են սցենարների գործարկման հերթականությունը:

Ինչպես դա աշխատում է իմ նախագծում ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Համակարգը սկսվում է
  2. Միանում է settings_restore.service ծառայությունը: Այն ստուգում է settings.txt ֆայլի առկայությունը տվյալների բաժնում: Եթե այն բացակայում է, տեղը դրվում է բնօրինակ ֆայլը: Դրանից հետո տեղի է ունենում համակարգի կարգավորումների վերականգնում:
    • նետի գաղտնաբառի
    • hostname,
    • ժամային գոտի
    • լոկալ
    • Պարզել, թե արդյոք ամբողջ կրիչը օգտագործվում է։ Ձեռք բերված չափը փոքր է՝ հեշտությամբ պատճենելու և կրիչի վրա գրելու համար։ Սկզբնավորումից ստուգվում է՝ կա՞ դեռ չօգտագործված տարածք։ Եթե կա՝ սկավառակը վերաքարկվում է։
    • Machine-id-ի ստեղծումը MAC հասցեից։ Դա կարևոր է DHCP միջոցով նույն հասցեն ստանալու համար։
    • Անցանցային կարգավորումներ։
    • Գրառումների չափը սահմանափակվում է։
    • Պատրաստվում է աշխատելու արտաքին սկավառակը (եթե համապատասխան տարբերակը ակտիվացված է և սկավառակը նոր է)։
  3. Սկսվում է postgresq։
  4. Սկավառակը սկսվում է վերականգնման ծառայությունը։ Դա անհրաժեշտ է zabbix-ի և նրա տվյալների բազայի պատրաստման համար։
    • Ստուգվում է, կա արդյոք արդեն zabbix տվյալների բազա։ Եթե չկա՝ այն ստեղծվում է ելքի ներմուծների (որոնք գալիս են zabbix-ի հետ)։
    • Ստեղծվում է ժամացույցի գոտիների ցանկ (նրա համար անհրաժեշտ է երևակայելու web-հարթակում)։
    • Գտնվում է ընթացիկ IP-ն, որը ցուցաբերական է եղել (դիմումի ընդունում ժամանելու համար)։
  5. Ոչխանը փոխվում է՝ հայտնվում է Ready to work արտահայտությունը։
  6. Նրբությունն պատրաստ է աշխատելու։

Անշուշտ կարևոր են ծառայությունների ֆայլերը, հենց նրանք սահմանում են նրանց աշխատանքի մնումը։

[Unit]
Description=վերականգնել համակարգի կարգավորումները
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

Ինչպես տեսնում եք, ես սահմանել եմ կախվածություններ, որպեսզի իմ սցենարը առաջինը գործարկվի, հետո միայն ցանցը բարձրանա և սուբեկտային տվյալների բազան սկսվի։

Երկրորդ ծառայությունը (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-ի և իմ setting_restore-ի սկսվում է հետո։ Սակայն zabbix ծառայությունների սկսվելուց առաջ։

Ծառայություն ժամանակաչափի համար logrotate-ի։

Systemd կարող է փոխարինել CRON-ին։ Զգալիորեն։ Причем точность не до минуты, а до секунды (а вдруг понадобится). А можно создать монотонный таймер, вызываемый по таймауту от события.
Աκριβապես հաջորդականային ժամանակաչափ, որը հաշվում է ժամանակը մեքենայի սկսելուց հետո, ես էլ ստեղծել եմ։
Այս մեկի համար պետք է 2 ֆայլ։
logrotateTimer.service — հենց ծառայության նշումը։

[Unit]
Description=գործել logrotate

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

Բոլորը պարզ է՝ հրամանագրի նկարագիր։
Երկրորդ ֆայլը logrotateTimer.timer — սա հենց այն է, որը սահմանում է ժամանակաչափերի աշխատանքը։

[Unit]
Description=Գործել logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Ինչ կա այստեղ։

  • ժամանակաչափի նկարագիր։
  • Առաջին գործարկման ժամանակը, սկսելով համակարգի բարձրացումից։
  • փոփոխական ժամանակահատվածների հետագա գործարկել։
  • ժամանակաչափերի ծառայությունների կախվածությունը։ Ապրում, դա միշտ չէ, որ դա կանգնած է տողը ժամանակաչափում։

Ինտերակտիվ սցենար выключения-ի համար և իր փակիչ թակարդը։

Մյուս մշակման ընթացքում ինձ անհրաժեշտ էր ավելի բարդ տարբերակ մտածել մեքենան выключения-ի համար՝ իրենց փակիչը, որպեսզի կատարեմ բազմաթիվ գործողություններ։ Իհարկե, խորհուրդ է տրվում ստեղծել oneshot ծառայություն RemainAfterExit տարբերակով, բայց դա չի կարողացնել ստեղծել ինտերակտիվ սցենար։

Եվ հարցը հենց այն է, որ ExecOnStop տարբերակով մեկնարկված հրամանները կատարվում են TTY-ից դուրս որտեղ է։ Ներքև գրեք հրամանը tty և պահպանեք դրա ելքը։

Հետևաբար, ես իրականացնում եմ անջատումը իմ թիրախի միջոցով։ 100% ճշտությունը չկարծեմ, բայց դա աշխատում է։
Ինչպես դա արվել է (ընդհանուր գծերով):
Ստեղծեցի my_shutdown.target թիրախ, որը կախված չէր ոչ մեկից։
my_shutdown.target

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

Այս թիրախին անցնելուց (systemctl isolate my_shutdown.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

  • Այս սկրիպտի ներսում ես իրականացնում անհրաժեշտ գործողությունները։ Թիրախի մեջ կարող եք ավելացնել բազմաթիվ սկրիպտեր, Fleksibiliteti ու հարմարավետության համար:

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

Նշում։ Տեղադրելով /tmp/reboot և /tmp/shutdown ֆայլերը։ Թիրախը չի կարելի կանչել պարամետրերով։ Կարելի է միայն ծառայություն։

Բայց ես օգտագործում եմ թիրախ, որպեսզի ունենամ աշխատանքում ճկունություն և երաշխավորված միջոցառումների կարգատամ։

Այնուամենայնիվ, ամենահետաքրքիրն սկսվեց հետո։ Բարեն ամբողջ հեռացնել/վերաբեռնել պետք է։ Եվ այստեղ կա 2 տարբերակ:

  • Անհրաժեշտ է փոխարինել reboot, shutdown և այլ հրամանները (նաև համակարգում են systemctl-ի վրա) իմ սկրիպտով։ Սկրիպտի ներսում՝ անցեք my_shutdown.target։ Իսկ թիրախի ներսում սկրիպտերը ապա անմիջապես կանչում են systemctl․ օրինակ՝ systemctl reboot։
  • Այլընտրանքային, բայց ինձ չհավանեցնող տարբերակը։ Ընդունվել բոլոր ինտերֆեյսներում, որոնք չեն նշվում shutdown/reboot/այլ բաներ, այլ ուղղակի կանչում են systemctl isolate my_shutdown.target թիրախը։

Ես ընտրեցի առաջին տարբերակը։ Systemd-ում reboot(որպեսզի poweroff) համակարգմամբ են systemd-ի վրա:

ls -l \/sbin\/poweroff 
lrwxrwxrwx 1 root root 14 սեպ 30 18:23 \/sbin\/poweroff -> \/bin\/systemctl

Այսպիսով, դրանք կարող են փոխարինվել իմ սկրիպտերով։
reboot

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

Ընտանիք: habr.com

Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով 🔥 Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով | ProHoster