
Giriş
Linux üçün proqramlaşdırma zamanı, sistem açıldığında və ya söndükdə icra olunan interaktiv skriptlərin yaradılması məsələləri ortaya çıxır. System V-də bu asan idi, lakin systemd dəyişikliklər edir. Lakin, bunun öz zamanlayıcıları var.
Target-lərin məqsədi nədir
Tez-tez qeyd edirlər ki, target-lər system V -init-də runlevel-in analoqudur - buna tamamilə razı deyiləm. Onlar daha çoxdur və paketləri qruplara ayırmaq mümkündür və misal üçün, bir əmr ilə bir qrup xidməti başlada bilər, əlavə əməlləri icra edə bilər. Üstəlik, onların iyerarxiyası yoxdur, yalnız asılılıqlar mövcuddur.
Interaktiv skriptin icrası ilə açılış zamanı target-in nümunəsi (imkanların icmalı)
Target-in öz təsviri:
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.serviceBu target, multi-user.target işə düşdükdə işə salınacaq və installer.service-i çağıracaq. Bu zaman birdən çox xidmət ola bilər.
cat installer.service
[Unit]
# təsvir
Description=installer interaktiv dialoq
[Service]
# Digər xidmətlər açıldıqda bir dəfə işə salınacaq
Type=idle
# İcra komutları - skriptin çağırılması
ExecStart=\/usr\/bin\/installer.sh
# tty3 vasitəsilə istifadəçi ilə interaktiv əlaqə
StandardInput=tty
TTYPath=\/dev\/tty3
TTYReset=yes
TTYVHangup=yes
[Install]
WantedBy=installer.targetVə nəhayət, icra edilən skriptin misalı:
#!/bin/bash
# Переходим в tty3
chvt 3
echo "Install, y/n ?"
read user_answerƏn vacib olanı, final.target-i seçməkdir - sistemin başlatdıqda çatmalı olduğu target. Systemd açılış prosesində asılılıqları təqib edəcək və lazım olan hər şeyi işə salacaq.
Final.target-i müxtəlif yollarla seçmək olar, mən bunu yükləyici seçimi ilə etdim.
Tam başlatma belə görünür:
- Yükləyici başlayır
- Yükləyici final.target parametrini ötürərək firmware-ni başlamağa başlayır
- Systemd sistemi işə salmağa başlayır. İradəli olaraq, installer.target və ya work.target-ə basic.target-dan onların asılılıqları (məsələn, multi-user.target) vasitəsilə gedir. Sonlar sistemin lazım olan rejimdə işləməsi üçün gətirir.
Firmware-ni işə salmağa hazırlıq
Firmware yaradılarkən, sistemin başlanğıcında vəziyyətini bərpa etmək və onu söndürərkən saxlamaq məsələsi daima ortaya çıxır. Vəziyyətdən konfiqurasiya faylları, verilənlər bazası dump-ları, interfeyslərin tənzimləmələri və s. başa düşülür.
Systemd, bir target daxilində prosesləri paralel işə salır. Skriptlərin işə salınma sırasını müəyyənləşdirməyə imkan verən asılılıqlar var.
Bu, mənim layihəmdə belə işləyir ( )
- Sistem başlayır
- settings_restore.service xidməti işə düşür. O, məlumat bölməsində settings.txt faylının mövcudluğunu yoxlayır. Əgər yoxdursa, onun yerinə nümunə fayl qoyulur. Sonra sistemin tənzimləmələri bərpa olunur:
- administrator şifrəsi
- hostname,
- vaxt qurşağı
- lokal
- Təsdiq edilir ki, bütün daşıyıcıdan istifadə olunur. Varsayılan olaraq, görüntü ölçüsü kiçikdir — daşıyıcıya köçürmək və yazmaq üçün rahatlıq üçün. Başlanarkən, istifadə edilməmiş yerin olub-olmaması yoxlanılır. Əgər varsa, disk yenidən bölünür.
- MAC ünvanından machine-id yaradılması. Bu, DHCP vasitəsilə eyni ünvanı əldə etmək üçün vacibdir.
- Şəbəkə parametrləri
- Girişlərin ölçüsü məhdudlaşdırılır
- Xarici disk işə hazırlanır (əgər müvafiq seçim aktivdirsə və disk yenidirsə)
- postgresq işə salınır
- restore xidməti işə salınır. Bu, zabbix və onun verilənlər bazasının hazırlanması üçün lazımdır:
- zabbix verilənlər bazasının artıq olub-olmaması yoxlanılır. Əgər yoxdursa — ilkin dump-lardan yaradılır (zabbix ilə birlikdə gəlir)
- şəhər saatlarının siyahısı yaradılır (web-interfeysdə göstərilməsi üçün lazımdır)
- Hal-hazırda olan IP tapılır, o, issue-da (konsola daxil olmaq üçün dəvət) göstərilir
- Dəvət dəyişdirilir — "Ready to work" ifadəsi görünür
- Proqram təminatı işə hazırdır
Xidmətlərin faylları vacibdir, məhz onlar onların işə salınma ardılığını müəyyən edir
[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.targetGöründüyü kimi, mən asılılıqları təyin etdim ki, əvvəlcə mənim skriptim işləsin və yalnız sonra şəbəkə yüksəldilsin və DBMS başladılmalıdır.
Və ikinci xidmət (zabbixin hazırlanması)
#!/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.targetBurada bir az daha mürəkkəbdir. Eyni zamanda multi-user.target-da, amma postgresql verilənlər bazası və mənim setting_restore başladıldıqdan sonra. Amma zabbix xidmətlərinin başlamasından əvvəl.
logrotate üçün zamanlayıcı xidməti
Systemd CRON-u əvəz edə bilər. Ciddi şəkildə. Üstəlik dəqiqlik bir dəqiqəyə deyil, bir saniyəyə qədərdir (tələb oluna bilər). Həm də bir hadisədən sonra zaman aşımında çağırılan monotondan bir zamanlayıcı yarada bilərsiniz.
Mən də elə monotondan bir zamanlayıcı yaratdım ki, o, maşının işə salınmasından başlayaraq vaxtı sayır.
Bunun üçün 2 fayl lazımdır
logrotateTimer.service — xidmətin təsviri:
[Unit]
Description=run logrotate
[Service]
ExecStart=logrotate \/etc\/logrotate.conf
TimeoutSec=300Hər şey sadədir — icra komandası təsviri.
İkinci fayl logrotateTimer.timer — o, zamanlayıcıların işini müəyyən edir:
[Unit]
Description=Run logrotate
[Timer]
OnBootSec=15min
OnUnitActiveSec=15min
[Install]
WantedBy=timers.targetBurada nələr var:
- zamanlayıcının təsviri
- sistemin yüklənməsindən başlamaqla ilk işə salma vaxtı
- sonrakı işə salma dövrləri
- zamanlayıcı xidmətlərindən asılılıq. Faktiki olaraq, bu xətt zamanlayıcı yaradır
Söndürmə zamanı interaktiv skript və öz güdülməsini sönmə hədəfi
Başqa bir layihədə mən daha mürəkkəb bir maşını söndürmə variantı hazırlamalı oldum — öz güdümüm vasitəsilə, bir sıra fəaliyyətlər yerinə yetirmək üçün. Adətən, oneshot xidməti yaratmağı tövsiyə edirəm, RemainAfterExit seçimi ilə, amma bu, interaktiv skript yaratmağa imkan vermir.
Məsələ odur ki, ExecOnStop seçimi ilə icra edilən komandalar TTY xaricində icra edilir! Sadəcə yoxlayın — tty əmrini daxil edin və onun çıxışını yadda saxlayın.
Ona görə də, mən hədəfim vasitəsilə söndürməyi təmin etdim. 100% düzgünlük iddiasında deyiləm, amma bu işləyir!
Bu necə edildi (ümumi şəkildə):
Mən, heç kimdən asılı olmayan my_shutdown.target hədəfini yaratdım:
my_shutdown.target
[Unit]
Description=my shutdown
AllowIsolate=yes
Wants=my_shutdown.service Bu hədəfə keçdikdə (systemctl isolate my_shutdown.target vasitəsilə), o, my_shutdown.service xidmətini işə salır, onun vəzifəsi isə sadədir — my_shutdown.sh skriptini icra etmək:
[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- Bu skriptin içində mən lazım olan tədbirləri görürəm. Hədəfə bir çox skript əlavə etmək mümkündür, bu da daha çevik və rahat edir:
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/
$commandQeyd. /tmp/reboot və /tmp/shutdown fayllarının istifadəsi. Hədəfi parametrli çağırmaq olmaz. Yalnız xidmət çağırmaq mümkündür.
Amma mən, işdə çevikliyi və icraatların zəmanət olunmuş sırasını əldə etmək üçün hədəfdən istifadə edirəm.
Ancaq, ən maraqlısı sonra gəldi. Maşını mütləq söndürmək/yenidən başlatmaq lazımdır. Burada iki variant var:
- reboot, shutdown və digər komandaları (onlar da olsa sistemctl-in simli bağlantılarıdır) öz skriptimlə dəyişmək. Skriptin içində — my_shutdown.target-a keçmək. Hədəfdəki skriptlər isə sonra birbaşa systemctl-ı çağırır, məsələn, systemctl reboot.
- Daha sadə, amma mənim xoşuma gəlməyən variant. Bütün interfeyslərdə shutdown/reboot/digər çağırmalardan istifadə etmək əvəzinə, birbaşa my_shutdown.target hədəfini çağırmaq - systemctl isolate my_shutdown.target.
Mən birinci variantı seçdim. Systemd-da reboot (həmçinin poweroff) systemd-ın simli bağlantılarıdır.
ls -l \/sbin\/poweroff
lrwxrwxrwx 1 root root 14 sen 30 18:23 \/sbin\/poweroff -> \/bin\/systemctlOna görə də onları öz skriptlərimlə dəyişdirə bilərəm:
reboot
#!/bin/sh
touch /tmp/reboot
sudo systemctl isolate my_shutdown.target
fiMənbə: habr.com
