Systemd, skrip interaktif dan pemasa

Systemd, skrip interaktif dan pemasa

Pengenalan

Apabila membangun untuk Linux, tugas mencipta skrip interaktif yang dilaksanakan apabila sistem dihidupkan atau ditutup timbul. Dalam sistem V ini adalah mudah, tetapi dengan systemd ia membuat pelarasan. Tetapi ia boleh mempunyai pemasa sendiri.

Mengapa kita memerlukan sasaran?

Selalunya ditulis bahawa sasaran berfungsi sebagai analog runlevel dalam sistem V -init. Saya pada asasnya tidak bersetuju. Terdapat lebih banyak daripada mereka dan anda boleh membahagikan pakej kepada kumpulan dan, sebagai contoh, melancarkan kumpulan perkhidmatan dengan satu arahan dan melakukan tindakan tambahan. Selain itu, mereka tidak mempunyai hierarki, hanya bergantung.

Contoh sasaran apabila didayakan (gambaran keseluruhan ciri) dengan menjalankan skrip interaktif

Penerangan mengenai sasaran itu sendiri:

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

Sasaran ini akan bermula apabila multi-user.target dilancarkan dan memanggil installer.service. Walau bagaimanapun, mungkin terdapat beberapa perkhidmatan sedemikian.

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

Dan akhirnya, contoh skrip yang dilaksanakan:

#!/bin/bash
# ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ Π² tty3
chvt 3
echo "Install, y/n ?"
read user_answer

Perkara yang paling penting ialah memilih final.target - sasaran yang sistem harus sampai pada permulaan. Semasa proses permulaan, systemd akan melalui kebergantungan dan melancarkan semua yang diperlukan.
Terdapat pelbagai cara untuk memilih final.target, saya menggunakan pilihan pemuat untuk ini.

Pelancaran terakhir kelihatan seperti ini:

  1. Pemuat but bermula
  2. Pemuat but mula melancarkan perisian tegar dengan melepasi parameter final.target
  3. Systemd mula memulakan sistem. Secara berurutan pergi ke installer.target atau work.target dari basic.target melalui kebergantungan mereka (contohnya, multi-user.target). Yang terakhir membawa sistem untuk berfungsi dalam mod yang dikehendaki

Menyediakan perisian tegar untuk pelancaran

Apabila mencipta perisian tegar, tugas sentiasa timbul untuk memulihkan keadaan sistem pada permulaan dan menyimpannya apabila ditutup. State bermaksud fail konfigurasi, longgokan pangkalan data, tetapan antara muka, dsb.

Systemd menjalankan proses dalam sasaran yang sama secara selari. Terdapat kebergantungan yang membolehkan anda menentukan urutan permulaan skrip.

Bagaimanakah ia berfungsi dalam projek saya ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Sistem bermula
  2. Perkhidmatan settings_restore.service dilancarkan. Ia menyemak kehadiran fail settings.txt dalam bahagian data. Jika ia tidak ada, maka fail rujukan diletakkan di tempatnya. Seterusnya, tetapan sistem dipulihkan:
    • kata laluan pentadbir
    • nama hos,
    • Zon masa
    • setempat
    • Menentukan sama ada semua media sedang digunakan. Secara lalai, saiz imej adalah kecil - untuk memudahkan penyalinan dan rakaman ke media. Pada permulaan, ia menyemak untuk melihat sama ada masih terdapat ruang yang tidak digunakan. Jika ada, cakera dipartisi semula.
    • Menjana id mesin daripada alamat MAC. Ini penting untuk mendapatkan alamat yang sama melalui DHCP
    • Tetapan rangkaian
    • Hadkan saiz kayu balak
    • Pemacu luaran sedang disediakan untuk berfungsi (jika pilihan yang sepadan didayakan dan pemacu baharu)
  3. Mulakan postgresq
  4. Perkhidmatan pemulihan bermula. Ia diperlukan untuk menyediakan zabbix sendiri dan pangkalan datanya:
    • Menyemak sama ada sudah ada pangkalan data zabbix. Jika tidak, ia dicipta daripada pembuangan permulaan (disertakan dengan zabbix)
    • senarai zon waktu dibuat (diperlukan untuk memaparkannya dalam antara muka web)
    • IP semasa ditemui, ia dipaparkan dalam isu (jemputan untuk log masuk ke konsol)
  5. Jemputan berubah - frasa Sedia untuk bekerja muncul
  6. Perisian tegar sedia untuk digunakan

Fail perkhidmatan adalah penting, ia adalah yang menetapkan urutan pelancaran mereka

[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

Seperti yang anda lihat, saya memasang kebergantungan supaya skrip saya mula-mula berfungsi, dan kemudian rangkaian akan meningkat dan DBMS akan bermula.

Dan perkhidmatan kedua (penyediaan 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

Ia lebih rumit sedikit di sini. Pelancaran juga dalam multi-user.target, tetapi SELEPAS memulakan DBMS postgresql dan setting_restore saya. Tetapi SEBELUM memulakan perkhidmatan zabbix.

Perkhidmatan pemasa untuk logrotate

Systemd boleh menggantikan CRON. Serius. Lebih-lebih lagi, ketepatan bukan sehingga minit, tetapi sehingga detik (bagaimana jika ia diperlukan). Atau anda boleh mencipta pemasa membosankan, dipanggil oleh tamat masa daripada acara.
Ia adalah pemasa membosankan yang mengira masa dari permulaan mesin yang saya cipta.
Ini memerlukan 2 fail
logrotateTimer.service - penerangan sebenar perkhidmatan:

[Unit]
Description=run logrotate

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

Ia mudah - penerangan tentang arahan pelancaran.
Fail kedua logrotateTimer.timer ialah tempat pemasa berfungsi:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Apa yang ada di sini:

  • penerangan pemasa
  • Masa mula pertama, bermula dari boot sistem
  • tempoh pelancaran selanjutnya
  • Kebergantungan pada perkhidmatan pemasa. Sebenarnya, ini adalah rentetan yang membuat pemasa

Skrip interaktif apabila ditutup dan sasaran penutupan anda

Dalam perkembangan lain, saya terpaksa melakukan versi yang lebih kompleks untuk mematikan mesin - melalui sasaran saya sendiri, untuk melakukan banyak tindakan. Ia biasanya disyorkan untuk membuat perkhidmatan oneshot dengan pilihan RemainAfterExit, tetapi ini menghalang anda daripada mencipta skrip interaktif.

Tetapi hakikatnya ialah arahan yang dilancarkan oleh pilihan ExecOnStop dilaksanakan di luar TTY! Ia mudah untuk menyemak - tampal arahan tty dan simpan outputnya.

Oleh itu, saya melaksanakan penutupan melalui sasaran saya. Saya tidak mendakwa 100% betul, tetapi ia berkesan!
Bagaimana ia dilakukan (dalam istilah umum):
Saya mencipta sasaran my_shutdown.target, yang tidak bergantung kepada sesiapa:
my_shutdown.target

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

Apabila pergi ke sasaran ini (melalui systemctl isolate my_shutdwn.target), ia melancarkan perkhidmatan my_shutdown.service, yang tugasnya mudah - untuk melaksanakan skrip 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

  • Di dalam skrip ini saya melakukan tindakan yang diperlukan. Anda boleh menambah banyak skrip pada sasaran untuk fleksibiliti dan kemudahan:

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

Catatan. Menggunakan fail /tmp/reboot dan /tmp/shutdown. Anda tidak boleh memanggil sasaran dengan parameter. Hanya perkhidmatan yang boleh dilakukan.

Tetapi saya menggunakan sasaran untuk mempunyai fleksibiliti dalam kerja dan susunan tindakan yang terjamin.

Walau bagaimanapun, perkara yang paling menarik datang kemudian. Mesin perlu dimatikan/dimulakan semula. Dan ada 2 pilihan:

  • Gantikan but semula, penutupan dan perintah lain (ia masih merupakan symlinks ke systemctl) dengan skrip anda. Di dalam skrip, pergi ke my_shutdown.target. Dan skrip di dalam sasaran kemudian memanggil systemctl secara langsung, sebagai contoh, but semula systemctl
  • Pilihan yang lebih mudah, tetapi saya tidak menyukainya. Dalam semua antara muka, jangan panggil shutdown/reboot/lain-lain, tetapi terus panggil systemctl target isolate my_shutdown.target

Saya memilih pilihan pertama. Dalam systemd, but semula (seperti poweroff) ialah pautan sym kepada systemd.

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

Oleh itu, anda boleh menggantikannya dengan skrip anda sendiri:
reboot

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

Sumber: www.habr.com

Tambah komen