Systemd, skrip dan pengatur waktu interaktif

Systemd, skrip dan pengatur waktu interaktif

pengenalan

Saat mengembangkan untuk Linux, muncul tugas membuat skrip interaktif yang dijalankan saat sistem dihidupkan atau dimatikan. Dalam sistem V hal ini mudah, tetapi dengan systemd hal ini membuat penyesuaian. Tapi ia bisa mempunyai pengatur waktunya sendiri.

Mengapa kita memerlukan target?

Sering ditulis bahwa target berfungsi sebagai analogi runlevel di sistem V -init. Saya pada dasarnya tidak setuju. Ada lebih banyak lagi dan Anda dapat membagi paket menjadi beberapa grup dan, misalnya, meluncurkan grup layanan dengan satu perintah dan melakukan tindakan tambahan. Selain itu, mereka tidak memiliki hierarki, hanya ketergantungan.

Contoh target saat diaktifkan (ikhtisar fitur) dengan menjalankan 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 dimulai ketika multi-user.target diluncurkan dan memanggil installer.service. Namun, 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 terakhir, contoh skrip yang sedang 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. Selama proses startup, systemd akan memeriksa dependensi dan meluncurkan semua yang dibutuhkan.
Ada berbagai cara untuk memilih final.target, saya menggunakan opsi loader untuk ini.

Peluncuran terakhir terlihat seperti ini:

  1. Bootloader dimulai
  2. Bootloader mulai meluncurkan firmware dengan meneruskan parameter final.target
  3. Systemd mulai memulai sistem. Secara berurutan masuk ke installer.target atau work.target dari basic.target melalui dependensinya (misalnya, multi-user.target). Yang terakhir membuat sistem bekerja dalam mode yang diinginkan

Mempersiapkan firmware untuk diluncurkan

Saat membuat firmware, tugas selalu muncul untuk memulihkan status sistem saat startup dan menyimpannya saat dimatikan. Status berarti file konfigurasi, dump database, pengaturan antarmuka, dll.

Systemd menjalankan proses dalam target yang sama secara paralel. Ada dependensi yang memungkinkan Anda menentukan urutan startup skrip.

Bagaimana cara kerjanya di proyek saya ( https://habr.com/ru/post/477008/ https://github.com/skif-web/monitor)

  1. Sistem dimulai
  2. Layanan settings_restore.service diluncurkan dan memeriksa keberadaan file settings.txt di bagian data. Jika tidak ada, maka file referensi ditempatkan di tempatnya. Selanjutnya, pengaturan sistem dipulihkan:
    • kata sandi administrator
    • nama host,
    • zona waktu
    • lokal
    • Menentukan apakah semua media digunakan. Secara default, ukuran gambar kecil - untuk kemudahan menyalin dan merekam ke media. Saat startup, ia memeriksa apakah masih ada ruang yang tidak terpakai. Jika ada, disk akan dipartisi ulang.
    • Menghasilkan id mesin dari alamat MAC. Ini penting untuk mendapatkan alamat yang sama melalui DHCP
    • Pengaturan jaringan
    • Membatasi ukuran log
    • Drive eksternal sedang dipersiapkan untuk bekerja (jika opsi yang sesuai diaktifkan dan drive masih baru)
  3. Mulai postgresq
  4. Layanan pemulihan dimulai. Diperlukan untuk mempersiapkan zabbix itu sendiri dan database-nya:
    • Mengecek apakah sudah ada database zabbix. Jika tidak, maka dibuat dari dump inisialisasi (disertakan dengan zabbix)
    • daftar zona waktu dibuat (diperlukan untuk menampilkannya di antarmuka web)
    • IP saat ini ditemukan, ditampilkan dalam masalah (undangan untuk masuk ke konsol)
  5. Undangan berubah - muncul kalimat Siap bekerja
  6. Firmware siap digunakan

File layanan itu 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 menginstal dependensi sehingga skrip saya berfungsi terlebih dahulu, dan baru kemudian jaringan akan naik dan DBMS akan mulai.

Dan servis kedua (persiapan 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 di sini, peluncurannya juga dalam multi-user.target, tetapi SETELAH memulai DBMS postgresql dan setting_restore saya. Namun SEBELUM memulai layanan zabbix.

Layanan pengatur waktu untuk logrotate

Systemd dapat menggantikan CRON. Dengan serius. Apalagi keakuratannya tidak sampai menit, tapi sampai detik (bagaimana jika diperlukan), atau Anda bisa membuat timer monoton yang disebut dengan timeout dari suatu event.
Itu adalah pengatur waktu 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 saja - deskripsi perintah peluncuran.
File kedua logrotateTimer.timer adalah tempat kerja pengatur waktu:

[Unit]
Description=Run logrotate

[Timer]
OnBootSec=15min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target

Apa disini:

  • deskripsi pengatur waktu
  • Waktu mulai pertama, dimulai dari boot sistem
  • periode peluncuran lebih lanjut
  • Ketergantungan pada layanan pengatur waktu Faktanya, string inilah yang membuat pengatur waktu

Skrip interaktif saat mematikan dan target mematikan Anda

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

Namun faktanya adalah perintah yang diluncurkan oleh opsi ExecOnStop dijalankan di luar TTY! Sangat mudah untuk memeriksanya - tempel perintah tty dan simpan hasilnya.

Oleh karena itu, saya menerapkan penutupan melalui target saya. Saya tidak mengklaim 100% benar, tapi berhasil!
Bagaimana hal itu dilakukan (secara umum):
Saya membuat target my_shutdown.target, yang tidak bergantung pada siapa pun:
my_shutdown.target

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

Ketika menuju ke target ini (melalui systemctl Isolate my_shutdwn.target), ia meluncurkan layanan my_shutdown.service, yang tugasnya sederhana - untuk menjalankan 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. Hanya layanan yang mungkin.

Tapi saya menggunakan target untuk memiliki fleksibilitas dalam pekerjaan dan urutan tindakan yang terjamin.

Namun, hal yang paling menarik terjadi belakangan. Mesin perlu dimatikan/di-restart. Dan ada 2 pilihan:

  • Ganti perintah reboot, shutdown dan lainnya (masih berupa symlink ke systemctl) dengan skrip Anda. Di dalam skrip, buka my_shutdown.target. Dan skrip yang ada di dalam target kemudian memanggil systemctl secara langsung, misalnya systemctl reboot
  • Pilihan yang lebih sederhana, tapi saya tidak menyukainya. Di semua antarmuka, jangan panggil shutdown/reboot/other, tapi langsung panggil target systemctl Isolate my_shutdown.target

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

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

Oleh karena itu, Anda dapat menggantinya dengan skrip Anda sendiri:
restart

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

Sumber: www.habr.com

Tambah komentar