Buggy systemd servisini SIGKILL üzerinden sonlandırmak için yapılandırma


20

Arka fon

systemdYeni bir hizmet için, foo_daemonbazen "kötü durum" durumuna giren ve SIGTERM(muhtemelen özel sinyal işleyicisi nedeniyle) ölmeyecek bir komut dosyası oluşturmam istendi . Bu, geliştiricilere, hizmeti şu şekilde başlatmaları / durdurmaları / yeniden başlatmaları talimatı verildiği için sorunludur:

  • systemctl start foo_daemon.service
  • systemctl stop foo_daemon.service
  • systemctl restart foo_daemon.service

Sorun

Bazen, foo_daemonkötü duruma geçme nedeniyle , onu zorla öldürmek zorundayız:

  • systemctl kill -s KILL foo_daemon.service

Soru

Komutumu nasıl ayarlayabilirim systemd, foo_daemonböylece bir kullanıcı hizmeti durdurmaya / yeniden başlatmaya çalıştığında systemd:

  • foo_daemonÜzerinden zarif bir kapatma girişiminde bulunun SIGTERM.
  • foo_daemonTamamlanması / kapatılması için 2 saniyeye kadar süre verin .
  • Süreci hala yaşıyorsa, foo_daemonüzerinden zorla kapatmaya çalışın SIGKILL(bu nedenle, PID'nin geri dönüştürülmesi ve yanlış PID'ye karşı systemdsorun oluşması riski yoktur SIGKILL). Test ettiğimiz cihaz hızlı bir şekilde sayısız işlemi gerçekleştiriyor / çatal kullanıyor; bu nedenle, PID geri dönüşümüyle ilgili bir soruna neden olan nadir ama çok gerçek bir endişe var.
  • Uygulamada, sadece PID geri dönüşümüyle ilgili paranoyaklığım varsa, sadece SIGKILL'PID'e geri dönüşümlü bir PID'yi öldürmekten endişe duymadan' işlemine karşı bir senaryo yayınlamam uygun olur .


2
İki saniyede 4 milyon PID'lerden üzerinde rulo hızla yeterince spawn süreçler, systemd bile gelmez bir döngü denetimi oturup "bu pid hala hayatta mı? Bu pid hala hayatta mı?" çünkü buna gerek yok; Acil çocuk süreçlerinin halen hayatta olup olmadığı hakkında zaten bilgilendirilmiştir (sıradan SIGCHLD ve waitpid () ile). Dolayısıyla, SIGTERM'den sonra sürecin sona erdiğini görürse, hizmeti o noktada 'inaktif' olarak işaretler - SIGKILL'i kontrol etmek, beklemek ve göndermekle hiç rahatsız olmaz.
Grawity

Yanıtlar:


26

systemd zaten bunu kutunun dışında destekliyor ve varsayılan olarak etkin .

Özelleştirmek isteyebileceğiniz tek şey, yapabileceğiniz zaman aşımı süresidir TimeoutStopSec=. Örneğin:

[Service]
TimeoutStopSec=2

Şimdi, systemd bir SIGTERM gönderecek, hizmetin çıkması için iki saniye bekleyecek ve eğer gelmezse, bir SIGKILL gönderecektir.

Hizmetiniz sistem farkında değilse, PID dosyasının yolunu belirtmeniz gerekebilir PIDFile=.

Sonunda, daemon'unuzun birçok süreci ortaya koyduğundan bahsettiniz. Bu durumda, ayarlamak isteyebilirsiniz KillMode=control-groupve systemd, gruptaki tüm işlemlere sinyal gönderir.


Teşekkür ederim. Son bir soru: Hizmetin sistem farkında olmadığını kabul edelim. Systemd'nin PID dosyasını oluşturması / yönetmesi için bu hizmet için systemd komut dosyasına ne ekleyebilirim? ? Biz genellikle systemctl başlangıç foo_dameon@1.service `yoluyla başlatmak böylece Ayrıca, hizmet böylece komut etkileyen PID dosya mantığını olur," şablon birimlerine yoluyla çok örnekli olabilir
Bulut

4
@DevNull systemd, PID dosyaları oluşturmaz veya yönetmez. Bunu yapmak için hiçbir sebep yok. Hizmetiniz kendi PID dosyasını oluşturmuyorsa, mümkünse ön planda çalışacak şekilde yapılandırın (arka plan oluşturma yerine) ve sistem Type=simplebiriminde ayarlayın.
Michael Hampton

1
Hizmetin bağımlıları Type=forkingvarsa, (hizmet uygun şekilde yazılmışsa), ne tür hazır olduğunda tam olarak 'hazır' olduğunda sistemi bildirme avantajına sahiptir. Daemonizing bir PID dosyası olmadan bile sorun değildir - systemd yine de ana süreci izler.
Grawity

1
@grawity Yeterince doğru ... hizmetlerin aslında hizmet vermeye hazır olmadan önce hizmet vermesi benim deneyimim olmasına rağmen. Sistem kullanan bir servis kullanan sistem Type=notifysistemi için en iyisidir ve birçok genel servis bunu zaten yapar. Ama muhtemelen bu eski hizmet değil. OP'nin durumunda, birçok süreci başlatan bir hizmeti var. Sistem dökümanları bu durum hakkında uyardı .
Michael Hampton

1

Kimse ihtiyaç duymadığından söz Type=oneshotettiğinden, zaman aşımı hatası nedeniyle ortaya çıkan tam bir örnek.

[Unit]
Description=timeout test

[Service]
Type=oneshot
TimeoutStartSec=2
ExecStart=/bin/sleep 10
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.