Systemd, skrip dan timer interaktif


Pendahuluan


Saat mengembangkan untuk linux, ada tugas membuat skrip interaktif yang dijalankan ketika sistem dihidupkan atau dimatikan. Dalam sistem V, ini dilakukan dengan mudah, tetapi dengan systemd membuat penyesuaian. Tapi itu bisa melakukan pengatur waktunya.


Kenapa kita butuh target


Sering ditulis bahwa target berfungsi sebagai analog runlevel dalam sistem V -init. Saya pada dasarnya tidak setuju. Ada lebih banyak dari mereka dan Anda dapat memisahkan paket ke dalam grup dan, misalnya, menjalankan grup layanan dengan satu tim dan melakukan tindakan tambahan. Selain itu, mereka tidak memiliki hierarki, hanya dependensi.


Contoh target saat startup (gambaran umum fitur) dengan peluncuran skrip interaktif


Deskripsi target 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 

Target ini akan mulai ketika multi-user.target diluncurkan dan memanggil installer.service. Selain itu, mungkin ada beberapa layanan seperti itu.


 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 dapat dieksekusi:


 #!/bin/bash #   tty3 chvt 3 echo "Install, y/n ?" read user_answer 

Yang paling penting adalah memilih final.target - target, yang harus dicapai sistem saat startup. Dalam proses memulai, systemd akan melalui dependensi dan menjalankan semua yang Anda butuhkan.
Ada beberapa cara untuk memilih final.target, saya menggunakan opsi bootloader untuk ini.


Peluncuran akhir terlihat seperti ini:


  1. Bootloader dimulai
  2. Bootloader memulai firmware dengan melewatkan parameter final.target
  3. Systemd memulai startup sistem. Ini berurutan ke installer.target atau work.target dari basic.target melalui dependensi mereka (misalnya, multi-user.target). Yang terakhir dan memimpin sistem untuk bekerja dalam mode yang diinginkan

Mempersiapkan firmware untuk diluncurkan


Saat membuat firmware, selalu ada tugas mengembalikan kondisi sistem saat startup dan menyimpannya ketika dimatikan. Status berarti file konfigurasi, kesedihan basis data, pengaturan antarmuka, dan sebagainya.


Systemd meluncurkan proses dalam satu target secara paralel. Ada dependensi yang memungkinkan Anda untuk menentukan urutan eksekusi skrip.


Cara kerjanya di proyek saya ( https://habr.com/en/post/477008/ https://github.com/skif-web/monitor )


  1. Sistem dimulai
  2. Layanan settings_restore.service dimulai dan memeriksa file settings.txt di bagian data. Jika tidak ada di sana, maka file referensi diletakkan di tempatnya. Selanjutnya, pengaturan sistem dipulihkan:
    • kata sandi admin
    • nama host
    • zona waktu
    • lokal
    • Menentukan apakah semua media digunakan. Secara default, ukuran gambar kecil - untuk kenyamanan penyalinan dan perekaman ke media. Saat startup, diperiksa apakah masih ada ruang yang tidak digunakan. Jika ada - disk dipartisi ulang.
    • Hasilkan id mesin dari alamat MAC. Ini penting untuk mendapatkan alamat yang sama melalui DHCP.
    • Pengaturan jaringan
    • Ukuran log terbatas
    • Drive eksternal disiapkan untuk bekerja (jika opsi yang sesuai diaktifkan dan drive baru)
  3. Jalankan postgresq
  4. layanan pemulihan dimulai. Diperlukan untuk menyiapkan zabbix sendiri dan databasenya:
    • Cek apakah sudah ada database zabbix. Jika tidak, itu dibuat dari menginisialisasi kesedihan (mereka disuplai dengan zabbix)
    • daftar zona waktu dibuat (diperlukan untuk menampilkannya di antarmuka web)
    • IP saat ini ditemukan, ditampilkan dalam masalah (undangan untuk memasuki konsol)
  5. Undangan berubah - frasa Siap bekerja muncul
  6. Firmware siap digunakan.

File layanan penting, merekalah yang mengatur urutan peluncurannya


 [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 membuat dependensi sehingga saya akan menjalankan skrip saya terlebih dahulu, dan hanya kemudian jaringan akan naik dan DBMS akan mulai.


Dan layanan kedua (mempersiapkan 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 

Ini sedikit lebih rumit. Peluncurannya juga di multi-user.target, tapi SETELAH menjalankan DBMS postgresql dan setting_restore saya. Tapi SEBELUM menjalankan layanan zabbix.


Layanan dengan timer untuk logrotate


Systemd dapat menggantikan CRON. Serius. Selain itu, akurasi tidak sampai satu menit, tetapi hingga satu detik (bagaimana jika diperlukan). Dan Anda dapat membuat timer monoton, yang disebut oleh timeout dari acara tersebut.
Itu adalah pengatur waktu yang monoton yang menghitung waktu dari awal mesin yang saya buat.
Ini akan membutuhkan 2 file
logrotateTimer.service - deskripsi sebenarnya dari layanan:


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

Sederhana - deskripsi perintah peluncuran.
File logrotateTimer.timer kedua adalah apa yang mengatur timer untuk bekerja:


 [Unit] Description=Run logrotate [Timer] OnBootSec=15min OnUnitActiveSec=15min [Install] WantedBy=timers.target 

Apa yang ada di sana:


  • deskripsi waktu
  • Pertama kali dimulai dari boot sistem
  • periode peluncuran lebih lanjut
  • Ketergantungan Layanan Timer. Sebenarnya, ini adalah garis dan membuat timer

Skrip interaktif tentang target shutdown dan custom shutdown


Dalam perkembangan lain, saya harus membuat versi yang lebih kompleks untuk mematikan mesin - melalui target saya sendiri, untuk melakukan banyak tindakan. Biasanya disarankan untuk membuat layanan oneshot dengan opsi RemainAfterExit, tetapi ini mencegah pembuatan skrip interaktif.


Tetapi kenyataannya adalah bahwa perintah yang diluncurkan oleh opsi ExecOnStop dieksekusi di luar TTY! Pemeriksaannya sederhana - masukkan perintah tty dan simpan hasilnya.


Karena itu, saya menerapkan shutdown melalui target saya. Saya tidak berpura-pura 100% benar, tetapi berhasil!
Cara melakukannya (secara umum):
Membuat target my_shutdown.target, yang tidak bergantung pada siapa pun:
my_shutdown.target


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

Saat beralih ke target ini (via systemctl mengisolasi my_shutdwn.target), ia meluncurkan layanan my_shutdown.service, yang tugasnya sederhana - untuk mengeksekusi 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 dapat menambahkan banyak skrip ke target, untuk fleksibilitas dan kenyamanan:

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 file / tmp / reboot dan / tmp / shutdown. Anda tidak dapat memanggil target dengan parameter. Anda hanya dapat melayani.


Tetapi saya menggunakan target untuk memiliki fleksibilitas dalam pekerjaan dan urutan tindakan yang dijamin.


Namun, hal yang paling menarik adalah nanti. Mesin harus dimatikan / dihidupkan ulang. Dan ada 2 opsi:


  • Ganti reboot, shutdown, dan perintah lain (mereka masih symlink pada systemctl) dengan skrip Anda sendiri. Di dalam skrip, buka my_shutdown.target. Dan skrip di dalam target kemudian langsung memanggil systemctl, misalnya, systemctl reboot
  • Sederhana, tapi saya tidak suka opsi. Di semua antarmuka, jangan panggil shutdown / reboot / yang lain, tapi langsung panggil target systemctl isolasikan my_shutdown.target

Saya memilih opsi pertama. Di systemd, reboot (seperti poweroff) adalah symlink pada systemd.


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

Karenanya, mereka dapat diganti dengan skrip Anda sendiri:
reboot


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

Source: https://habr.com/ru/post/id478846/


All Articles