Systemd, etkileşimli komut dosyaları ve zamanlayıcılar

Systemd, etkileşimli komut dosyaları ve zamanlayıcılar

Giriş

Linux için geliştirme yaparken, sistem açıldığında veya kapatıldığında yürütülen etkileşimli komut dosyaları oluşturma görevi ortaya çıkar. Sistem V'de bu kolaydı, ancak systemd ile ayarlamalar yapılıyor. Ancak kendi zamanlayıcıları olabilir.

Neden hedeflere ihtiyacımız var?

Hedefin V-init sistemindeki çalışma seviyesinin bir analoğu olarak hizmet ettiği sıklıkla yazılır. Temelde katılmıyorum. Bunlardan daha fazlası var ve paketleri gruplara ayırabilir ve örneğin tek komutla bir grup hizmeti başlatabilir ve ek eylemler gerçekleştirebilirsiniz. Üstelik hiyerarşileri yok, yalnızca bağımlılıkları var.

Etkileşimli komut dosyasının çalıştırılmasıyla etkinleştirildiğinde hedef örneği (özelliğe genel bakış)

Hedefin kendisinin açıklaması:

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

Bu hedef, multi-user.target başlatıldığında ve installer.service'i çağırdığında başlayacaktır. Ancak bu tür birkaç hizmet olabilir.

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

Ve son olarak, yürütülen betiğin bir örneği:

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

En önemli şey, sistemin başlangıçta ulaşması gereken hedef olan final.target'ı seçmektir. Başlatma işlemi sırasında systemd bağımlılıkları gözden geçirecek ve ihtiyaç duyduğu her şeyi başlatacaktır.
Final.target seçmenin farklı yolları var, bunun için loader seçeneğini kullandım.

Son lansman şuna benzer:

  1. Önyükleyici başlıyor
  2. Önyükleyici, final.target parametresini ileterek ürün yazılımını başlatmaya başlar
  3. Systemd sistemi başlatmaya başlar. Bağımlılıkları (örneğin, çok kullanıcılı.target) aracılığıyla basic.target'ten sırayla installer.target veya work.target'e gider. İkincisi, sistemi istenen modda çalışmaya getirir

Ürün yazılımını başlatmaya hazırlama

Ürün yazılımı oluştururken görev her zaman sistem durumunu başlangıçta geri yüklemek ve kapatırken kaydetmekten kaynaklanır. Durum, yapılandırma dosyaları, veritabanı dökümleri, arayüz ayarları vb. anlamına gelir.

Systemd aynı hedefteki işlemleri paralel olarak çalıştırır. Komut dosyalarının çalışma sırasını belirlemenize olanak tanıyan bağımlılıklar vardır.

Projemde nasıl çalışıyor ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Sistem başlıyor
  2. Settings_restore.service hizmeti başlatılır. Veri bölümünde settings.txt dosyasının varlığını kontrol eder. Orada değilse, yerine bir referans dosyası yerleştirilir. Daha sonra sistem ayarları geri yüklenir:
    • yönetici şifresi
    • ana bilgisayar adı,
    • saat dilimi
    • yerel ayar
    • Tüm medyanın kullanılıp kullanılmadığını belirler. Ortama kopyalama ve kaydetme kolaylığı için, varsayılan olarak görüntü boyutu küçüktür. Başlangıçta hala kullanılmayan alan olup olmadığını kontrol eder. Varsa, disk yeniden bölümlendirilir.
    • MAC adresinden makine kimliği oluşturuluyor. Bu, aynı adresi DHCP aracılığıyla elde etmek için önemlidir.
    • Ağ ayarları
    • Günlüklerin boyutunu sınırlar
    • Harici sürücü çalışmaya hazırlanıyor (ilgili seçenek etkinse ve sürücü yeniyse)
  3. Postgreq'i başlat
  4. Geri yükleme hizmeti başlar. Zabbix'in kendisini ve veritabanını hazırlamak gerekir:
    • Zaten bir zabbix veritabanının olup olmadığını kontrol eder. Değilse, başlatma dökümlerinden oluşturulur (zabbix'e dahildir)
    • saat dilimlerinin bir listesi oluşturulur (bunları web arayüzünde görüntülemek için gereklidir)
    • Geçerli IP bulunur, sorunda görüntülenir (konsolda oturum açma daveti)
  5. Davet değişir - Çalışmaya hazır ifadesi görünür
  6. Ürün yazılımı kullanıma hazır

Hizmet dosyaları önemlidir, başlatılma sırasını belirleyen dosyalardır

[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

Gördüğünüz gibi, betiğimin ilk önce çalışması için bağımlılıklar kurdum ve ancak o zaman ağ açılacak ve DBMS başlayacaktı.

Ve ikinci servis (zabbix hazırlığı)

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

Burada durum biraz daha karmaşık. Başlatma da multi-user.target'ta, ancak postgresql DBMS'yi ve setup_restore'umu başlattıktan SONRA. Ancak zabbix hizmetlerini başlatmadan ÖNCE.

Logrotate için zamanlayıcı hizmeti

Systemd, CRON'un yerini alabilir. Cidden. Üstelik doğruluk dakikaya göre değil, saniyeye kadardır (ya gerekiyorsa) Veya bir olaydan zaman aşımı olarak adlandırılan monoton bir zamanlayıcı oluşturabilirsiniz.
Yarattığım makinenin başlangıcından itibaren zamanı sayan monoton zamanlayıcıydı.
Bu 2 dosya gerektirecektir
logrotateTimer.service - hizmetin gerçek açıklaması:

[Unit]
Description=run logrotate

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

Çok basit; başlatma komutunun açıklaması.
İkinci dosya logrotateTimer.timer, zamanlayıcıların çalıştığı yerdir:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Burada ne var:

  • zamanlayıcı açıklaması
  • Sistem önyüklemesinden başlayarak ilk başlangıç ​​zamanı
  • daha fazla lansman dönemi
  • Zamanlayıcı hizmetine bağımlılık Aslında zamanlayıcıyı yapan dize budur.

Kapatma sırasında etkileşimli komut dosyası ve kapatma hedefiniz

Başka bir geliştirmede, birçok eylemi gerçekleştirmek için makineyi kendi hedefim aracılığıyla kapatmanın daha karmaşık bir versiyonunu yapmak zorunda kaldım. Genellikle RemainAfterExit seçeneğiyle tek seferlik bir hizmet oluşturmanız önerilir ancak bu, etkileşimli bir komut dosyası oluşturmanızı engeller.

Ancak gerçek şu ki ExecOnStop seçeneği tarafından başlatılan komutlar TTY dışında yürütülür! Kontrol etmesi kolaydır; tty komutunu yapıştırın ve çıktısını kaydedin.

Bu nedenle kapatmayı hedefim üzerinden gerçekleştirdim. %100 doğru olduğunu iddia etmiyorum ama işe yarıyor!
Nasıl yapıldı (genel anlamda):
Kimseye bağlı olmayan bir my_shutdown.target hedefi oluşturdum:
my_shutdown.target

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

Bu hedefe giderken (systemctl isulate my_shutdwn.target aracılığıyla), görevi basit olan my_shutdown.sh betiğini yürütmek için my_shutdown.service hizmetini başlattı:

[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 scriptin içerisinde gerekli işlemleri gerçekleştiriyorum. Esneklik ve rahatlık için hedefe birçok komut dosyası ekleyebilirsiniz:

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

Not. /tmp/reboot ve /tmp/shutdown dosyalarını kullanma. Hedefi parametrelerle çağıramazsınız. Yalnızca servis mümkündür.

Ancak hedefi işte esnekliğe ve garantili bir eylem sırasına sahip olmak için kullanıyorum.

Ancak en ilginç şey daha sonra geldi. Makinenin kapatılması/yeniden başlatılması gerekiyor. Ve 2 seçenek var:

  • Yeniden başlatma, kapatma ve diğer komutları (bunlar hala systemctl'nin sembolik bağlantılarıdır) betiğinizle değiştirin. Betiğin içinde my_shutdown.target'a gidin. Ve hedefin içindeki komut dosyaları daha sonra doğrudan systemctl'yi çağırır; örneğin, systemctl yeniden başlatma
  • Daha basit bir seçenek ama hoşuma gitmedi. Tüm arayüzlerde, kapatma/yeniden başlatma/diğer'i çağırmayın, ancak doğrudan hedef systemctl isulate my_shutdown.target'ı arayın.

İlk seçeneği seçtim. Systemd'de yeniden başlatma (poweroff gibi) systemd'ye olan sembolik bağlantılardır.

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

Bu nedenle bunları kendi komut dosyalarınızla değiştirebilirsiniz:
reboot

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

Kaynak: habr.com

DDoS korumalı siteler, VPS VDS sunucuları için güvenilir hosting satın alın 🔥 DDoS korumalı, güvenilir VPS ve VDS sunucu barındırma hizmeti satın alın | ProHoster