Bagaimana flag layanan systemd yang siap, sehingga layanan lain dapat menunggu untuk itu siap sebelum mereka mulai?

8

Saya memiliki banyak layanan (katakanlah C0,, C1... C9) yang hanya akan dimulai setelah layanan Smenyelesaikan inisialisasi dan sepenuhnya berjalan dan siap untuk layanan lainnya. Bagaimana saya mengaturnya dengan systemd?

Dalam Memesan layanan dengan aktivasi jalur dan target dalam systemd diasumsikan bahwa layanan Smemiliki mekanisme untuk menulis semacam file flag. Asumsikan di sini, sebaliknya, bahwa saya memiliki kendali penuh atas program yang Sdijalankan layanan , dan dapat menambahkan mekanisme systemd ke dalamnya jika perlu.

JdeBP
sumber

Jawaban:

7

Seseorang tidak perlu membutuhkan ini.

Jika Clayanan perlu menunggu untuk Ssiap sehingga mereka dapat membuka koneksi soket untuk itu, maka orang tidak perlu melakukan ini sama sekali. Sebaliknya, seseorang dapat mengambil keuntungan dari pembukaan soket mendengarkan dini oleh manajer layanan.

Beberapa sistem, termasuk s6 Laurent Bercot , toolset nosh saya , dan systemd, memiliki cara di mana soket pendengaran dapat dibuka sejak dini, hal pertama dalam menyiapkan layanan. Mereka semua melibatkan sesuatu selain program layanan yang membuka soket pendengar, dan program layanan, ketika dipanggil, menerima soket pendengar sebagai deskriptor file yang sudah terbuka.

Dengan systemd, khususnya, seseorang menciptakan unit soket yang mendefinisikan soket pendengaran. systemd membuka unit soket dan mengaturnya sehingga subsistem jaringan kernel mendengarkan koneksi; dan meneruskannya ke layanan aktual sebagai deskriptor file terbuka ketika datang untuk menelurkan proses yang menangani koneksi ke soket. (Dapat melakukan ini dalam dua cara, sama seperti inetdbisa, tetapi diskusi tentang detail Accept=trueversus Accept=falselayanan berada di luar cakupan jawaban ini.)

Poin penting adalah bahwa seseorang tidak perlu memesan lebih dari itu. Kernel mengumpulkan koneksi klien dalam antrian sampai program layanan diinisialisasi, dan siap untuk menerimanya dan berbicara dengan klien.

Ketika seseorang melakukannya, protokol kesiapan adalah masalahnya.

systemd memiliki seperangkat protokol kesiapan yang dipahami, layanan dengan layanan tertentu dengan Type=pengaturan di unit layanan. Protokol kesiapan tertentu yang menarik di sini adalah notifyprotokol kesiapan. Dengan itu, systemd diberitahu untuk mengharapkan pesan dari layanan, dan ketika layanan siap mengirimkan pesan yang menandai kesiapan. systemd menunda aktivasi layanan lain hingga kesiapan ditandai.

Memanfaatkan ini melibatkan dua hal:

  • Memodifikasi kode Ssehingga ia memanggil sesuatu seperti notify_systemd()fungsi Pierre-Yves Ritschard atau fungsi Cameron T Norman notify_socket().
  • Menyiapkan unit layanan untuk layanan dengan Type=notifydan NotifyAccess=main.

The NotifyAccess=mainpembatasan (yang merupakan default) karena kebutuhan systemd tahu untuk mengabaikan pesan dari program nakal (atau hanya rusak plain), karena setiap proses pada sistem dapat mengirim pesan ke soket pemberitahuan systemd ini.

Seseorang menggunakan kode Pierre-Yves Ritschard atau Cameron T Norman untuk preferensi karena tidak mengecualikan kemungkinan memiliki mekanisme ini di UbuntuBSD, FreeBSD Debian, FreeBSD aktual, TrueOS, OpenBSD, dan sebagainya; yang dikecualikan oleh kode yang diberikan oleh systemd penulis.

Satu jebakan yang harus dihindari adalah systemd-notifyprogram. Ini memiliki beberapa masalah utama, tidak sedikit di antaranya adalah bahwa pesan yang dikirim dengannya akhirnya dapat dibuang tanpa diproses oleh systemd. Masalah yang paling utama dalam hal ini adalah bahwa itu tidak berjalan sebagai proses "utama" dari layanan, jadi kita harus membuka notifikasi kesiapan untuk layanan Suntuk setiap proses pada sistem dengan NotifyAccess=all.

Jebakan lain yang harus dihindari adalah berpikir bahwa forkingprotokol lebih sederhana. Bukan itu. Melakukannya dengan benar melibatkan tidak forking dan keluar dari orang tua sampai (untuk satu hal) semua utas pekerja program berjalan. Ini tidak cocok dengan bagaimana sebagian besar demon yang garpu sebenarnya.

Bacaan lebih lanjut

JdeBP
sumber
1
Menurut manusia systemd.service(5), NotifyAccess=allakan menerima pesan dari semua anggota kelompok kontrol layanan , yang tidak menyiratkan sembarang proses jahat pada sistem. Ini cukup aman untuk sebagian besar kasus penggunaan. Juga, kekhawatiran Anda tentang portabilitas ke sistem operasi lain tidak relevan dengan OP, karena kami sudah membahas topik Systemd di sini.
Amir
1

Mengacu pada halaman buku panduan untuk systemd.service(5), khususnya bagian tentang Tipe = , setiap jenis layanan memiliki cara yang berbeda untuk Systemd untuk menentukan bahwa ia siap untuk menawarkan fungsionalitas ke layanan lain:

  • Jika Type=simple, saluran komunikasinya harus dipasang sebelum daemon dijalankan (mis. Soket diatur oleh systemd, melalui aktivasi soket).

  • Jika Type=forking, proses induk diharapkan untuk keluar ketika start-up selesai dan semua saluran komunikasi diatur.

  • Jika Type=dbus, diharapkan bahwa daemon memperoleh nama pada bus D-Bus, di mana systemd akan melanjutkan dengan memulai unit tindak lanjut.

  • Jika Type=notify, diharapkan daemon tersebut mengirim pesan pemberitahuan melalui sd_notify(3)atau panggilan yang setara ketika telah selesai memulai. systemd akan melanjutkan dengan memulai unit tindak lanjut setelah pesan pemberitahuan ini telah dikirim.

Untuk opsi terakhir (mengirim pesan melalui sd_notify), Anda dapat menggunakan systemd-notifyutilitas, dan jangan lupa untuk memberinya akses NotifyAccess=all.

Karena Anda memiliki kendali atas layanan S, Anda bebas memilih opsi terbaik untuk kasus penggunaan Anda, atau hanya salah satu yang paling mudah diterapkan.

Amir
sumber
1

seperti ini:

Layanan

[Unit]
Description=My main Service

[Service]
Type=notify
ExecStart=/usr/bin/myBinary

Layanan C0

[Unit]
Description=Dependent service number 0
PartOf=S.service

C1.service

[Unit]
Description=Dependent service number 1
PartOf=S.service

Layanan C9

[Unit]
Description=Dependent service number 9
PartOf=S.service

Di mana / usr / bin / myBinary membuat panggilan sd_notify READY = 1 saat inisialisasi selesai.

Bergantung pada bagaimana Anda ingin ketergantungan untuk berperilaku, Anda bisa menggunakan PartOf, Membutuhkan, atau BindsTo atau yang lain .

code_monk
sumber