Systemd dan proses pemijahan

14

Biasanya tidak memposting di sini tapi saya ripping rambut saya lebih dari ini. Saya memiliki skrip Python yang bercabang saat diluncurkan, dan bertanggung jawab untuk memulai banyak proses lainnya. Skrip ini dulunya diluncurkan saat startup melalui sysvinit, tetapi baru-baru ini saya memutakhirkan ke Debian Jessie sehingga telah mengadaptasinya untuk diluncurkan melalui systemd.

Sayangnya, saya mengalami masalah yang tidak bisa saya selesaikan. Ketika Anda meluncurkan skrip secara langsung di shell pengguna, itu meluncurkan proses anak itu dengan benar, dan ketika skrip keluar proses anak menjadi yatim piatu dan terus berjalan.

Ketika diluncurkan Via systemd, jika proses induk keluar, anak-anak juga akan keluar (Ya, Layar yang mereka luncurkan mati dan muncul sebagai Mati ???)

Idealnya saya harus bisa memulai kembali skrip induk tanpa membunuh semua proses anak, apakah ada sesuatu yang saya lewatkan?

Terima kasih!

[Unit]
Description=Server commander
After=network.target

[Service]
User=serveruser
Type=forking
PIDFile=/var/Server/Server.pid

ExecStart=/var/Server/Server.py
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

Sunting: Mungkin relevan bagi saya untuk menunjukkan bahwa skrip Python pada dasarnya adalah 'pengontrol' untuk proses anaknya. Ini memulai dan menghentikan server di layar gnu seperti yang diminta dari server pusat. Biasanya selalu berjalan, itu tidak menelurkan layanan dan keluar. Namun ada beberapa kasus di mana saya ingin dapat memuat ulang skrip tanpa membunuh proses anak, bahkan jika itu berarti prosesnya menjadi yatim menjadi pid 1. Sebenarnya, bahkan tidak masalah jika skrip Python memulai proses sebagai proses induk, jika itu bahkan mungkin.

Penjelasan yang lebih baik tentang cara kerjanya:

  • Systemd memunculkan / Server.py
  • Server.py memetik dan menulis file pid untuk Systemd
  • Server.py kemudian memunculkan proses server di layar gnu berdasarkan instruksinya
  • Server.py terus berjalan untuk melakukan restart yang diminta dari server

Ketika meluncurkan tanpa Systemd, Server.py dapat di-restart dan layar gnu yang diluncurkan tidak terpengaruh. Saat meluncurkan dengan Systemd, ketika Server.py dimatikan, alih-alih proses layar tersebut menjadi yatim piatu ke pid 1, mereka terbunuh.

Bottswana
sumber
1
Sulit untuk memberikan solusi tanpa memiliki Server.pykode dan deskripsi bagaimana garpu layanan diluncurkan (jika mereka bercabang). Namun, secara umum, ini adalah masalah ketidakcocokan protokol kesiapan .
intelfx
BTW, ExecStop=itu tidak diperlukan. tindakan standar systemd saat berhenti adalah mematikan proses. Anda mungkin ingin melihat dokumentasi untuk KillMode=direktif.
intelfx
1
Dan, akhirnya ... Jika tidak ada protokol kesiapan yang cocok (salah satu simpleatau forking, sebenarnya), pilihan terakhir adalah Type=oneshot, RemainAfterExit=yesdan KillMode=control-group.
intelfx
@intelfx Pada dasarnya skrip Python meluncurkan server di layar menggunakan Subprocess.call. Ini lebih rumit dari itu karena skrip menerima perintah dari tempat lain mengatakan itu layar mana untuk memulai dan mana yang tidak. Layar mana yang tersedia juga dinamis maka mengapa mereka tidak bisa menjadi layanan systemd dengan hak mereka sendiri. Idealnya saya tidak ingin systemd memperlakukan layar ini sebagai bagian dari layanan sama sekali, tetapi saat ini mereka dibuang di grup proses yang sama dan mati bersama master jika dimulainya kembali.
Bottswana
Firasat saya adalah bahwa systemd tidak "menangani" proses kontrol seperti itu (itu hanya mencari PID saat mulai, tidak mengenali yang kemudian ...): |
rogerdpack

Jawaban:

9

Saya berhasil memperbaikinya hanya dengan mengatur KillMode untuk memproses alih-alih grup kontrol (default). Terima kasih semuanya

Bottswana
sumber
Itu tampaknya seperti pekerjaan di sekitar lebih dari perbaikan, lihat jawaban lain ... jika Anda melakukan ini dan melakukan "systemctl stop" maka itu tidak akan membunuh proses anak mereka masih akan berjalan [?] di luar pengawasan systemctl?
rogerdpack
5

Saya memiliki skrip Python yang bercabang saat diluncurkan, dan bertanggung jawab untuk memulai banyak proses lainnya.

Yang menunjukkan bahwa Anda salah melakukannya. Lebih dalam sebentar lagi.

ketika skrip keluar proses anak menjadi yatim piatu dan terus berjalan.

Ini bukan perilaku demon yang benar. Jika proses "utama" - dalam hal ini anak yang telah Anda garpu, sejak Anda tentukan Type=forking- keluar, systemd menganggap layanan telah dinonaktifkan dan menghentikan proses lain yang masih berjalan (dalam kelompok kontrol) untuk merapikan .

Terkadang konversi dari rcskrip System 5 ke systemd tidak mudah, karena cara yang tepat untuk melakukan hal-hal di bawah systemd sangat berbeda. Cara yang tepat untuk melakukan (misalnya) OpenVPN, atau OpenStack, atau OSSEC HIDS di systemd tidak sama dengan yang akan dilakukan dengan rcskrip. Fakta bahwa Anda memiliki skrip yang bercabang-cabang, lalu menelurkan seluruh proses cucu, kemudian keluar dengan mengharapkan cucu-cucu itu terus berjalan menunjukkan bahwa Anda sedang melakukan jenis kengerian yang sama ossec-control, walaupun dengan dua tingkat percabangan yang kurang. Jika Anda menemukan diri Anda menulis skrip "master" yang memeriksa tanda "aktifkan" dan menjalankan proses anak untuk bagian "diaktifkan" dari sistem Anda, maka Anda membuat kesalahan yang sama dengan yang menghebohkan ossec-control.

Tidak ada mekanisme buatan sendiri yang diperlukan dengan systemd. Sudah merupakan manajer layanan. Per /unix//a/200365/5132 , cara yang benar untuk melakukan ini dalam systemd adalah tidak memiliki satu layanan yang memunculkan beberapa upaya aneh dan membingungkan untuk memiliki "sub-layanan". Ini adalah untuk memiliki setiap proses anak sebagai layanan systemd sepenuhnya matang dalam haknya sendiri. Kemudian seseorang mengaktifkan dan menonaktifkan, dan memulai dan menghentikan, berbagai bagian sistem menggunakan kontrol sistem normal. Seperti yang Anda lihat dalam kasus OSSEC HIDS, unit layanan template sederhana mencakup hampir semua (satu pengecualian adalah di /ubuntu//a/624871/43344 ) layanan, memungkinkan seseorang untuk melakukan hal-hal seperti systemctl enable [email protected]mengaktifkan opsi opsionalagentlessdlayanan, tanpa perlu sama sekali untuk mekanisme "skrip master" yang menghebohkan yang diperlukan dengan Sistem 5 rc.

Ada banyak kasus, tidak mungkin ekstrem seperti OSSEC HIDS, di mana pemikiran ulang seperti itu diperlukan. MTS seperti exim dan sendmail adalah dua. Seseorang mungkin memiliki rcskrip tunggal yang menghasilkan runner antrian, sebuah SMTP Submission dæmon, dan SMTP Relay dæmon, dengan sekelompok variabel ad hoc shell dalam file konfigurasi untuk mengontrol apa yang dijalankan. Tetapi cara yang tepat untuk melakukan ini dengan systemd adalah memiliki tiga unit layanan yang tepat (dua di antaranya memiliki unit soket terkait ) dan sama sekali tidak ada hal-hal khusus, hanya mekanisme biasa dari manajer layanan.

JdeBP
sumber
Saya menghargai umpan balik ini. Sementara saya setuju memiliki layanan subset masuk akal, itu dilakukan dengan Python karena alasan yang saya tidak bisa masuki. Satu-satunya solusi saya adalah menemukan cara untuk membuat metode ini berfungsi. Terimakasih Meskipun. Saya ingin melakukannya dengan benar.
Bottswana
Layanan sub yang diluncurkan skrip hanyalah server yang berjalan di layar gnu sebagai pengguna tertentu. Server ini banyak berubah, ada yang ditambahkan, ada yang dihapus dan ini dikendalikan di tempat lain, sehingga mereka tidak bisa benar-benar menjadi layanan aktual di systemd, karena itu menambah banyak kerumitan, dan tidak dapat dikelola secara terpusat. Juga skrip yang sama juga digunakan pada server non systemd.
Bottswana
systemd memiliki fasilitas eksplisit untuk memungkinkan layanan ditambahkan dan dihapus tanpa memerlukan akses root. "Juga digunakan pada layanan non-systemd" adalah satu-satunya argumen di atas yang tidak dapat diperbaiki dengan menambahkan lebih banyak systemd ... well, bisa dibilang, bahkan orang juga bisa. :)
Charles Duffy
0

Anda bisa saja tidur dengan orang tua, dan menunggu systemd membunuhnya pada waktu berhenti.

Craig Hicks
sumber