Sunucu & Performans

Usermin “Failed to open PID file” Hatası ve Çözümü (2026)

Usermin “Failed to open PID file” Hatası ve Çözümü (2026)

Kısa cevap: “Failed to open PID file” hatası burada PID dosyasının yokluğundan değil, güncel paketlerin Usermin’i --nofork + Type=simple ile başlatmasından kaynaklanır. Bu modda restart asenkron döner: Virtualmin “Login to Usermin”de Usermin’i yeniden başlatıp hemen PID dosyasını okumaya çalışır, ama dosya henüz yazılmamıştır → open() patlar. Çözüm, bir systemd drop-in override ile Usermin’i klasik forking moduna çevirmektir; restart senkron olur, yarış biter. Çözüm güvenli, geri alınabilir ve paket güncellemesinde ezilmez.

Virtualmin panelinde bir kullanıcının yanındaki Login to Usermin bağlantısına tıklıyorsunuz ve karşınıza şu çıkıyor:

hata mesajı
Failed to save user : Failed to open PID file

İlginç olan şu: Usermin’i komut satırından elle başlattığınızda her şey sorunsuz çalışıyor, ama systemctl ile yönetildiğinde bu hata geliyor. Bu yazıda hatanın gerçek sebebini — yanıltıcı ipuçlarını teker teker eleyerek — bulup kalıcı çözümü veriyoruz. Test ortamı AlmaLinux + Virtualmin, ancak mantık tüm modern systemd dağıtımları için geçerli.

Hatanın yanıltıcı yüzü

“Failed to open PID file” mesajı insanı doğrudan PID dosyasının kayıp veya bozuk olduğuna yönlendiriyor. Çoğu rehber de buradan başlayıp dosyayı silmenizi ya da izinleri düzeltmenizi söylüyor. Bizim vakamızda dosya gayet yerindeydi:

PID dosyası kontrolü
ls -la /var/usermin/miniserv.pid
# -rw-r--r-- 1 root root 8 ... /var/usermin/miniserv.pid

cat /var/usermin/miniserv.pid              # 1329556
systemctl show -p MainPID --value usermin  # 1329556

PID dosyası var, izinleri doğru (root:root, 644), içeriği systemd’nin gördüğü MainPID ile birebir aynı. Yani klasik “dosya yok / eski / yanlış yolda” senaryosu burada geçerli değil. Demek ki sorun başka yerde.

Şüphelileri elemek

Tahminle config değiştirmek yerine her olası nedeni tek tek doğrulayıp eledik. Bu adımlar sizin sunucunuzda da hızlı bir teşhis listesi olarak işe yarar.

1. Port çakışması

İlk testlerde hem elle başlatılmış hem systemd’nin başlattığı iki Usermin aynı anda koşuyordu. Bu, klasik bir restart döngüsü yaratıyor:

journalctl -u usermin
Failed to bind to port 20000 : Address already in use
Could not listen on any ports

İki Usermin aynı portu paylaşamaz; ikinci başlayan ölür ve systemd sonsuz restart döngüsüne girer. Çözüm tek kaynağa inmek:

tek kaynağa in
systemctl stop usermin
pkill -f 'usermin/miniserv.pl'
fuser -k 20000/tcp
ss -tlnp | grep ':20000'   # çıktı boş olmalı
systemctl start usermin

Bu temizlikten sonra port sorunu bitti — ama “Login to Usermin” hatası devam etti. Yani port çakışması gerçek sebep değil, ayrı bir belirtiydi.

2. SELinux

AlmaLinux’ta akla ilk gelen şüpheli. Doğrulama:

SELinux kontrolü
getenforce          # Disabled
ausearch -m avc -ts recent 2>/dev/null | grep -iE 'usermin|miniserv|pid'

SELinux kapalı, ilgili hiçbir AVC reddi yok. Eleme.

3. Webmin’in özel PID yolu

Webmin’in Usermin modülü farklı bir yola mı bakıyor?

modül config kontrolü
grep -i pid /etc/webmin/usermin/config   # boş

Özel bir pid_file= tanımı yok, usermin_dir=/etc/usermin doğru. Eleme. Üç en olası şüpheli de elendiğine göre, sorun dosyada değil, dosyanın ne zaman okunduğunda.

Gerçek sebep: kaydetme başarılı, “uygula” adımı başarısız

Hata mesajının tam metni ve geldiği URL önemli bir ipucu veriyor. Webmin log’unda:

webmin miniserv.log
/virtual-server/save_user.cgi?switch=Login%20to%20Usermin... : Failed to open PID file

Yani hata Usermin’in process’inden değil, Virtualmin’in (Webmin) process’inden geliyor. “Login to Usermin” şunu yapar:

  1. Kullanıcı için geçici bir oturum bilgisi yazar — bu adım başarılı olur.
  2. Sonra Usermin’e “config’ini yeniden oku” demek için onu yeniden başlatır ve PID dosyasından process’e ulaşmaya çalışır — patlayan adım budur.

Webmin kaynak kodunda bu hata, yeniden başlatma fonksiyonundan (web-lib-funcs.pl) gelir ve klasik olarak şu durumda görülür: Usermin yeniden başlatılırken PID dosyası tam o anda okunamaz. Kullanıcının kaydı zaten yazıldığı için değişiklik aslında kaydedilmiştir; sadece “Usermin’e haber verme” adımı başarısız olur. Peki dosya yerindeyse open() neden başarısız oluyor? Cevap zamanlamada.

Asıl mesele: --nofork + Type=simple restart’ı asenkron yapıyor

Güncel Webmin/Usermin paketleri systemd unit’ini şu şekilde başlatıyor:

systemctl cat usermin
ExecStart=/usr/libexec/usermin/miniserv.pl --nofork /etc/usermin/miniserv.conf
Type=simple

--nofork + Type=simple kombinasyonunda systemctl restart usermin komutu, yeni process portu bağlayıp PID dosyasını yazmadan geri döner. Bu, systemd’nin belgelenmiş davranışıdır: Type=simple‘da servis manager unit’i process fork() edilir edilmez (hatta execve() çağrılmadan önce) “başladı” sayar; hazır olmasını beklemez. Type=forking‘de ise manager, forklayan sürecin çıkmasını bekler ve PIDFile=‘dan ana process’i okur — yani başlatma senkrondur.

Virtualmin “Login to Usermin”de Usermin’i yeniden başlatıp hemen ardından PID dosyasını okumaya çalıştığında, dosya henüz yazılmamış o milisaniyelik boşluğa denk gelir → open() başarısız → “Failed to open PID file”.

Bu, Usermin’i elle başlattığınızda neden sorun olmadığını da tam olarak açıklıyor. Klasik forking (daemonize) başlatma senkrondur: ana process, portu bağlayıp PID dosyasını yazana kadar bekler, ancak ondan sonra geri döner. Virtualmin PID dosyasını okuduğunda dosya garantili oradadır. Manuel-vs-systemd farkının kaynağı bu zamanlama farkıdır — gizemli bir izin ya da modül sorunu değil.

Bunu canlı olarak da doğruladık. 0.4 saniye aralıkla PID’i izlerken “Login to Usermin”e bastığımızda Usermin temiz şekilde yeni bir PID’e geçti (ör. 1334966 → 1335781) — çift process yok, port çakışması yok, sadece tam bir restart. Restart temiz; sorun restart’ın çağırana asenkron dönmesiydi.

Bu hata neden bazen çıkıyor, bazen çıkmıyor?

Bu bir yarış olduğu için her sunucuda her zaman patlamaz — sadece yeni miniserv process’i PID dosyasını yazana kadar geçen süre, Virtualmin’in onu okumaya çalıştığı ana yetişemediğinde ortaya çıkar. Belirleyici olan, başlangıç penceresinin ne kadar genişlediğidir. Pencereyi genişleten şey de yeni Perl process’inin başlangıçta yavaşlamasıdır.

Swap baskısı

miniserv.pl bir Perl process’idir; başlarken Webmin/Usermin’in onlarca .pm modülünü diskten okuyup belleğe yükler. Sistem swap kullanıyorsa hem modüllerin page-in’i hem bellek tahsisi diske sayfalamayı tetikler. Normalde 50–100 ms süren başlangıç, swap baskısı altında yüzlerce milisaniyeye çıkabilir. Pencere bu kadar genişleyince yarış neredeyse her seferinde kaybedilir. Kaynak kısıtlı, swap yapan VPS’lerde bu hatayı sürekli görmenizin sebebi budur.

Güncelleme sonrası. Burada üç etken üst üste biner: paket dosyaları yeni yazıldığı için page cache soğuktur ve ilk okuma diskten yapılır (yavaş); dnf/apt işleminin kendisi o an disk ve belleği zaten yorar; ve paketin postinstall adımı tam bu yoğun anda daemon-reload + Usermin restart yapar. Topluluk kayıtlarında bu hatanın çoğunlukla “Configuring Usermin” anında bildirilmesi tesadüf değil — sistemin en çok churn ettiği, cache’in en soğuk olduğu an.

Bunun tersi de geçerli: hızlı diskli, boşta, sıcak-cache bir sunucuda yeni process pencereden çok önce hazır olur ve yarış hiç tetiklenmez. “Bende neden bazen oluyor bazen olmuyor?” sorusunun cevabı budur — sorun config’inizde değil, o anki sistem yükünde. İşte forking override’ın bu değişkenlerden bağımsız çözmesinin sebebi de tam burada: senkron restart, process başlangıcı ne kadar yavaş olursa olsun PID dosyası yazılana kadar bekler. Swap, soğuk cache, anlık yük — hiçbiri artık önemli değildir, çünkü yarış penceresi tamamen kapanır.

Kalıcı çözüm: forking moduna geçen systemd override

Çözüm, Usermin’i klasik forking moduna çevirmek. Böylece restart senkron olur ve Virtualmin PID dosyasını okuduğunda dosya hazır olur. Bu aslında Usermin’in orijinal systemd şablonundaki davranışın (Type=forking + PIDFile=) geri getirilmesidir. Unit dosyasının kendisine dokunmuyoruz — paket güncellemesinde ezilmemesi için drop-in override kullanıyoruz:

usermin forking override
mkdir -p /etc/systemd/system/usermin.service.d

cat > /etc/systemd/system/usermin.service.d/override.conf << 'EOF'
[Service]
Type=forking
PIDFile=/var/usermin/miniserv.pid
ExecStart=
ExecStart=/usr/libexec/usermin/miniserv.pl /etc/usermin/miniserv.conf
EOF

# Temiz başlangıç
systemctl stop usermin
pkill -f 'usermin/miniserv.pl'
rm -f /var/usermin/miniserv.pid
fuser -k 20000/tcp 2>/dev/null

systemctl daemon-reload
systemctl start usermin
sleep 1
systemctl status usermin --no-pager
cat /var/usermin/miniserv.pid    # dolu olmalı

Burada iki ince nokta var:

  • Boş ExecStart= satırı zorunlu. systemd’de bir drop-in içinde mevcut bir direktifi sıfırlamanın yolu önce onu boş atamaktır. Bu satır, unit dosyasındaki --nofork‘lu orijinal komutu siler; ikinci satır da --nofork olmadan aynı komutu tanımlar.
  • Tüm bu süreç hâlâ %100 systemd yönetiminde. “Forking moduna geçmek” elle başlatmak değildir; miniserv yine systemd’nin cgroup’u içinde, systemd loglamasıyla çalışır. Tek değişen, başlatmanın senkron tamamlanmasıdır.

Override sonrası systemctl status stabil “active (running)” gösteriyorsa ve PID dosyası doluysa, panelden Login to Usermin‘i tekrar deneyin. Hata gitmiş olmalı.

Yollarınızı doğrulayın

Yukarıdaki yollar test sunucumuza (AlmaLinux + Virtualmin) ait. Dağıtımınızda farklı olabilir; uygulamadan önce systemctl cat usermin | grep ExecStart ile miniserv yolunu ve grep pidfile /etc/usermin/miniserv.conf ile PID dosyasının gerçek yolunu teyit edip override.conf‘taki PIDFile= / ExecStart= satırlarını buna göre güncelleyin.

Geri almak isterseniz

Override tamamen geri alınabilir. Eski davranışa dönmek için:

override’ı kaldır
rm /etc/systemd/system/usermin.service.d/override.conf
systemctl daemon-reload
systemctl restart usermin

Yaygın bir yanılgı: “reinstall düzeltti”

Teşhis sürecinde sık rastlanan bir nokta var. Webmin güncellemesinin ardından dnf reinstall usermin yapıp Usermin’i elle başlatınca sorun “düzelmiş” gibi görünür. Ama bu kök sebebi çözmez: reinstall, paketi aynı systemd unit’iyle (yine --nofork + Type=simple) geri kurar — yani asenkron restart yarışı olduğu gibi kalır. O an işleri “çalışır” yapan şey reinstall değil, hemen ardından yapılan manuel başlatmadır; manuel başlatma senkron olduğu için yarış oluşmaz. systemd yönetimine dönüldüğünde hata tekrar ortaya çıkar.

Reinstall’ın gerçekten faydalı olduğu tek durum, önceki port çakışması/restart döngüsü install state’i bozmuşsa (eski PID artığı, yarım güncellemeden bozuk izinler) temiz bir başlangıç sağlamasıdır. Bu durumda bile arkasından mutlaka forking override uygulanmalıdır; aksi halde sorun geri döner. Yani sıralama şudur: gerekiyorsa reinstall → ardından forking override → kalıcı çözüm.

Sıkça sorulan sorular

“Failed to open PID file” hatasının gerçek sebebi nedir?

PID dosyasının kaybolması değil, bir zamanlama yarışıdır. Güncel Usermin --nofork + Type=simple ile başlatılır; bu modda restart, yeni process PID dosyasını yazmadan geri döner. Virtualmin “Login to Usermin”de Usermin’i restart edip hemen PID dosyasını okumaya çalışınca o kısa boşluğa denk gelir ve open() başarısız olur.

Neden elle başlatınca çalışıyor, systemd ile başlatınca çalışmıyor?

Elle (klasik forking) başlatma senkrondur: ana process PID dosyasını yazana kadar bekler, sonra döner. --nofork + Type=simple ise asenkrondur: systemd process’i spawn ettiği an “başladı” sayar. Fark izin ya da modül değil, tam olarak bu zamanlama farkıdır.

systemd drop-in override paket güncellemesinde silinir mi?

Hayır. Override /etc/systemd/system/usermin.service.d/override.conf altında, paketin unit dosyasından ayrı durur. Paket güncellemesi unit dosyasını yenilese bile drop-in korunur ve etkisini sürdürür. Çözümün paket-güncellemesine dayanıklı olmasının sebebi budur.

Forking moduna geçmek Usermin’i systemd dışına mı çıkarır?

Hayır. Süreç %100 systemd yönetiminde kalır; miniserv yine systemd’nin cgroup’u içinde ve systemd loglamasıyla çalışır. Tek değişen, başlatmanın senkron tamamlanması ve PIDFile= ile systemd’nin doğru process’i izlemesidir.

dnf reinstall usermin sorunu çözer mi?

Kalıcı olarak çözmez. Reinstall paketi aynı --nofork + Type=simple unit’iyle geri kurar; yarış olduğu gibi kalır. O an “çalışır” görünmesinin sebebi, ardından yapılan manuel (senkron) başlatmadır. systemd’ye dönüldüğünde hata döner. Kalıcı çözüm forking override’dır.

Özet

“Failed to open PID file” hatası burada PID dosyasının yokluğundan değil, --nofork + Type=simple ile yapılan asenkron restart ile Virtualmin’in PID dosyasını okuma adımı arasındaki zamanlama yarışından kaynaklanıyor. Usermin’i bir systemd drop-in ile forking moduna çevirmek restart’ı senkron yapar, yarışı ortadan kaldırır ve “Login to Usermin”i kalıcı olarak çalışır hale getirir. Çözüm güvenli, geri alınabilir ve paket güncellemesinde ezilmez. Bu tür servis-disiplini konularında sunucunuzu baştan doğru kurmak isterseniz Webmin nedir ve ne işe yarar ile Virtualmin/Webmin sunucu sıkılaştırma yazılarımız iyi bir başlangıç.

İlgili yazı

Aynı “systemd ile servis disiplini” temasında, ClamAV daemon’ının az RAM’li bir sunucuyu OOM ile nasıl çökerttiğini ve cgroup limitiyle nasıl izole ettiğimizi de inceledik: ClamAV neden sunucunuzu çökertir? OOM vaka analizi.

Webmin/Virtualmin sunucunuzda takıldınız mı?

systemd, servis restart’ları ve panel hataları çoğu zaman böyle sinsi zamanlama sorunlarından çıkar. Bizimle iletişime geçin; kurulumunuzu inceleyip kalıcı bir çözüm çıkaralım. Sürekli bakım tarafını da bakım hizmetimizde üstleniyoruz.

Digital Kernel Software

Digital Kernel Software

WordPress tema geliştirme, hosting ve sunucu performansı üzerine yazıyoruz. İstanbul / Türkiye.

Projeniz mi var?

Okuduğunuzu
projenize uygulayalım

WordPress, hosting ve performans tarafında yazdıklarımızı sizin işinizde hayata geçirelim. Net konuşuruz — pazarlama dili değil, uygulanabilir çözüm.