Bir Laravel kuyruk işçisini php artisan queue:work ile başlatıp SSH oturumunu kapattığınızda süreç ölür; sabaha kadar işlenmesi gereken e-postalar, bildirimler ve kuyruk işleri sessizce durur. Aynı sorun uzun süre çalışması gereken bir Python botunda, bir WebSocket sunucusunda ya da veri toplayan bir arka plan betiğinde de yaşanır. İşte tam bu boşluğu dolduran araç Supervisor'dır: Linux üzerinde arka plan süreçlerini bir "denetleyici" gibi ayakta tutar, çöktüklerinde otomatik yeniden başlatır ve loglarını tek bir yerde toplar.
Bu rehberde Supervisor'ın ne olduğunu, nasıl kurulacağını, program bloğunun command, autostart, autorestart ve numprocs gibi kritik yönergelerini, supervisorctl ile günlük yönetimi ve log dosyalarının nasıl okunacağını uygulamalı örneklerle ele alıyoruz. Ardından Laravel kuyruk işçisi ile Python worker senaryolarını gerçek yapılandırmalarla göstereceğiz ve Supervisor'ı systemd ile karşılaştıracağız. Süreçlerin işletim sistemi tarafından nasıl yönetildiğine dair temeli merak ediyorsanız systemd servis yönetimi yazımız iyi bir tamamlayıcı olacaktır.
Supervisor Nedir ve Ne İşe Yarar#
Supervisor, UNIX benzeri sistemlerde çalışan bir süreç kontrol (process control) sistemidir. Temelde iki parçadan oluşur: arka planda çalışan supervisord daemon'ı ve onu yönetmenizi sağlayan supervisorctl komut satırı istemcisi. Siz Supervisor'a "şu komutu çalıştır ve sürekli ayakta tut" dersiniz; o da süreci başlatır, izler ve beklenmedik bir şekilde sonlanırsa yeniden başlatır. Böylece terminalinizi kapatmanız, sunucunun yeniden başlaması veya uygulamanın çökmesi gibi durumlarda bile süreciniz kaldığı yerden devam eder.
Peki neden nohup, screen ya da basit bir & yeterli değil? Bu araçlar bir komutu arka plana atar ama onu izlemez. Süreç çökerse kimse yeniden başlatmaz; sunucu yeniden açıldığında hiçbiri geri gelmez ve logları düzenli tutmak size kalır. Supervisor ise süreci canlı tutmayı, açılışta otomatik başlatmayı, çıktısını dosyaya yönlendirmeyi ve aynı işten birden fazla kopya çalıştırmayı standart hale getirir. Özellikle PHP, Python, Ruby gibi kendi başına daemon olmayan yorumlanmış dillerin uzun süreli süreçlerinde Supervisor neredeyse fiili standart olmuştur; çünkü kurulumu basittir, yapılandırması okunaklıdır ve tek bir sunucuda onlarca süreci tek bir arayüzden yönetmenizi sağlar.
Supervisor Kurulumu#
Supervisor çoğu dağıtımın deposunda hazır bulunur; bu, kurulumun en kolay yoludur. Ubuntu ve Debian tabanlı sistemlerde apt ile kurabilirsiniz:
sudo apt update
sudo apt install -y supervisor
# Servisin durumunu kontrol edin
sudo systemctl status supervisor
AlmaLinux, Rocky Linux veya CentOS tarafında paket adı supervisor olup EPEL deposundan gelir:
sudo dnf install -y epel-release
sudo dnf install -y supervisor
# Açılışa ekleyin ve başlatın
sudo systemctl enable --now supervisord
Kurulumdan sonra Supervisor bir arka plan servisi olarak çalışmaya başlar ve kendisi zaten systemd tarafından yönetilir; yani sunucu yeniden başladığında Supervisor otomatik ayağa kalkar, o da kendisine bağladığınız tüm süreçleri geri getirir. Ana yapılandırma dosyası genellikle /etc/supervisor/supervisord.conf (Debian/Ubuntu) veya /etc/supervisord.conf (RHEL ailesi) konumundadır. Bu dosyanın sonundaki [include] bölümü, her uygulama için ayrı yapılandırma dosyaları eklemenizi sağlar:
[include]
files = /etc/supervisor/conf.d/*.conf
Bu yapı sayesinde supervisord.conf dosyasına dokunmadan, her uygulamanız için conf.d dizini altında bağımsız bir .conf dosyası oluşturursunuz. Bu, hem düzeni korur hem de bir uygulamanın yapılandırmasını değiştirirken diğerlerini etkileme riskini ortadan kaldırır.
Program Bloğu ve Temel Yönergeler#
Supervisor'da her yönetilen süreç bir [program:x] bloğuyla tanımlanır. Diyelim ki /var/www/bot altındaki bir Python betiğini sürekli çalışır tutmak istiyoruz. /etc/supervisor/conf.d/bot.conf dosyasını şöyle oluştururuz:
[program:bot]
command=/var/www/bot/venv/bin/python /var/www/bot/main.py
directory=/var/www/bot
user=www-data
autostart=true
autorestart=true
startsecs=5
startretries=3
stopwaitsecs=10
stdout_logfile=/var/log/supervisor/bot.log
stderr_logfile=/var/log/supervisor/bot-error.log
Buradaki yönergelerin her biri süreç davranışını doğrudan belirler. En kritik olanları tek tek açalım:
- command: Çalıştırılacak komutun tam yolu. Supervisor bir kabuk (shell) başlatmadığı için
cdgibi kabuk özelliklerini kullanamazsınız; komutu mutlak yolla yazın ve ortam gerektiren araçlarda (Python venv, belirli bir PHP sürümü) yorumlayıcının tam yolunu verin. - directory: Komut çalıştırılmadan önce geçilecek çalışma dizini. Uygulamanızın göreli yollar kullanması durumunda bu satır şarttır.
- user: Sürecin hangi kullanıcı kimliğiyle çalışacağı. Web uygulamalarını
rootyerinewww-datagibi yetkisiz bir kullanıcıyla çalıştırmak, güvenlik açısından en az yetki prensibinin gereğidir. - autostart:
trueisesupervisordbaşladığında (yani sunucu açılışında) süreç otomatik başlatılır. - autorestart: Sürecin çökmesi durumundaki davranış.
trueher çıkışta yeniden başlatır;unexpectedyalnızca beklenmeyen çıkış kodlarında başlatır;falsehiç başlatmaz. Uzun süreli işçilerde genellikletrueistenir. - startsecs: Sürecin "başarıyla başladı" sayılması için bu kadar saniye ayakta kalması gerekir. Hemen çöken bir süreç bu süreyi dolduramaz ve Supervisor onu FATAL olarak işaretler.
- startretries: Başlatma başarısız olursa kaç kez deneneceği. Bu sayı aşılırsa süreç FATAL durumuna geçer ve Supervisor pes eder.
Aynı işten birden fazla kopya çalıştırmak istediğinizde numprocs devreye girer. Örneğin dört paralel kuyruk işçisi için:
[program:worker]
command=/var/www/venv/bin/python /var/www/worker.py
numprocs=4
process_name=%(program_name)s_%(process_num)02d
autostart=true
autorestart=true
numprocs=4 Supervisor'a bu komutu dört ayrı süreç olarak çalıştırmasını söyler; process_name şablonu ise her kopyaya worker_00, worker_01 gibi benzersiz bir ad verir. Bu, çok çekirdekli bir sunucuda iş yükünü paralelleştirmenin en pratik yollarından biridir. Yapılandırmayı kaydettikten sonra Supervisor'a yeni tanımı okutmanız gerekir; bunu bir sonraki bölümde göreceğiz.
supervisorctl ile Süreçleri Yönetmek#
Yapılandırma dosyalarını oluşturduktan veya değiştirdikten sonra Supervisor'ın bunları fark etmesi için iki komut çalıştırırsınız: reread (yapılandırmaları yeniden okur) ve update (değişiklikleri uygular, yeni süreçleri başlatır):
sudo supervisorctl reread
sudo supervisorctl update
Günlük yönetim supervisorctl üzerinden yapılır. En sık kullanacağınız komutlar oldukça sezgiseldir:
# Tüm süreçlerin durumunu listele
sudo supervisorctl status
# Belirli bir süreci başlat / durdur / yeniden başlat
sudo supervisorctl start bot
sudo supervisorctl stop bot
sudo supervisorctl restart bot
# numprocs ile tanımlı bir grubun tümünü yönet
sudo supervisorctl restart worker:*
# Tüm süreçleri birden yeniden başlat
sudo supervisorctl restart all
status komutunun çıktısı size her sürecin durumunu, PID'sini ve ne kadar süredir çalıştığını gösterir:
bot RUNNING pid 2417, uptime 3:12:45
worker_00 RUNNING pid 2418, uptime 3:12:45
worker_01 RUNNING pid 2419, uptime 3:12:45
Argümansız çalıştırdığınızda supervisorctl, Supervisor'ın kendi etkileşimli kabuğuna girer; burada status, restart bot gibi komutları başına sudo supervisorctl yazmadan verebilir, help ile tüm komutları listeleyebilirsiniz. Önemli bir ayrım şudur: restart sürecin kendisini yeniden başlatır ama yapılandırma değişikliklerini okumaz. Bir .conf dosyasını düzenlediyseniz mutlaka önce reread ve update çalıştırın; yalnızca restart demek, süreci eski yapılandırmayla yeniden başlatmak anlamına gelir ve değişikliğiniz etkisiz kalır. Bu, systemd'deki daemon-reload mantığının Supervisor'daki karşılığıdır.
Log Dosyaları ve İzleme#
Supervisor, yönettiği her sürecin standart çıktısını (stdout) ve hata çıktısını (stderr) dosyalara yönlendirir. Program bloğunda stdout_logfile ve stderr_logfile belirtmezseniz Supervisor otomatik olarak AUTO modunda kendi log dizinine (genellikle /var/log/supervisor/) yazar; ancak üretimde bu yolları açıkça belirtmek, logları nerede arayacağınızı bilmeniz açısından çok daha sağlıklıdır. Bir sürecin loglarını canlı izlemenin en pratik yolu supervisorctl tail komutudur:
# Son log satırlarını göster
sudo supervisorctl tail bot
# Canlı takip et (Ctrl+C ile çık)
sudo supervisorctl tail -f bot
# Hata çıktısını izle
sudo supervisorctl tail -f bot stderr
Elbette log dosyalarını doğrudan da okuyabilirsiniz; tail -f /var/log/supervisor/bot.log klasik yöntemdir. Uzun süre çalışan süreçler zamanla büyük loglar üretir ve diski doldurabilir; Supervisor bunun için yerleşik bir döndürme (rotation) mekanizması sunar. logfile_maxbytes bir log dosyasının ulaşabileceği azami boyutu, logfile_backups ise kaç eski kopyanın saklanacağını belirler:
[program:worker]
command=/var/www/venv/bin/python /var/www/worker.py
stdout_logfile=/var/log/supervisor/worker.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
Bu yapılandırmada log dosyası 50 MB'a ulaştığında Supervisor onu döndürür ve en fazla on eski kopya tutar; böylece log yönetimi için ayrı bir logrotate kuralına ihtiyaç duymazsınız. Disk kullanımını kontrol altında tutmak, özellikle sık log üreten kuyruk işçilerinde göz ardı edilmemesi gereken bir konudur; aksi halde bir "no space left on device" hatası tüm süreçlerinizi bir gecede durdurabilir. Loglarınızı düzenli tutmak, ilerideki hata ayıklama süreçlerinizi de büyük ölçüde kolaylaştırır.
Laravel Kuyruk İşçisi ve Python Worker Örnekleri#
Supervisor'ın en yaygın kullanım alanı, hiç şüphesiz Laravel kuyruk işçileridir. Laravel'in resmi belgeleri bile kuyrukları üretimde çalıştırmak için Supervisor'ı önerir; çünkü queue:work süreci uzun çalıştıkça bellek biriktirir ve kod dağıtımından sonra yeniden başlatılması gerekir. Tipik bir Laravel kuyruk yapılandırması şöyle görünür:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/proje/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
directory=/var/www/proje
autostart=true
autorestart=true
user=www-data
numprocs=3
redirect_stderr=true
stdout_logfile=/var/log/supervisor/laravel-worker.log
stopwaitsecs=3600
Bu yapılandırmada birkaç ince nokta vardır. numprocs=3 üç paralel işçi çalıştırır; --max-time=3600 her işçinin bir saatte bir kendini nazikçe sonlandırmasını sağlar (Supervisor onu hemen geri başlatır), bu da bellek sızıntılarını temizler. --tries=3 başarısız bir işin en fazla üç kez denenmesini belirtir. En kritik satır ise stopwaitsecs=3600'dür: Supervisor bir işçiyi durdurmak istediğinde, işçinin o an işlediği görevi bitirmesi için bir saat bekler; bu değeri düşük tutarsanız çalışan bir görev yarıda kesilebilir. Kod dağıtımı sonrası işçilerin yeni kodu almasını sağlamak için php artisan queue:restart çalıştırırsınız; bu komut işçilere mevcut işi bitirince kapanma sinyali gönderir, Supervisor da onları yeni kodla geri başlatır.
Python tarafında da mantık aynıdır. Örneğin bir Celery işçisini ya da kendi yazdığınız uzun süreli bir kuyruk tüketicisini şöyle yönetebilirsiniz:
[program:celery]
command=/var/www/api/venv/bin/celery -A app.tasks worker --loglevel=info --concurrency=4
directory=/var/www/api
user=appuser
autostart=true
autorestart=true
startsecs=10
stopwaitsecs=600
stopasgroup=true
killasgroup=true
stdout_logfile=/var/log/supervisor/celery.log
redirect_stderr=true
Buradaki stopasgroup=true ve killasgroup=true yönergeleri, Celery gibi alt süreç (child process) oluşturan programlar için hayati önem taşır. Bu ayarlar olmadan Supervisor yalnızca ana süreci durdurur; alt süreçler "yetim" kalarak arka planda çalışmaya devam eder ve zamanla sunucunuzu tüketir. stopasgroup durdurma sinyalini tüm süreç grubuna gönderir, killasgroup ise zorla sonlandırmada aynısını yapar. Bir web arayüzü sunan Python uygulamalarında (Gunicorn, Uvicorn) benzer bir yapılandırma kullanır, ardından uygulamanın önüne bir ters vekil sunucu koyarsınız; bunun için Nginx kurulumu rehberimizdeki reverse proxy adımlarını izleyebilirsiniz.
Supervisor mı, systemd mi?#
Supervisor bir süreci ayakta tutmanın tek yolu değildir; Linux'un yerleşik başlatma sistemi systemd de aynı işi yapabilir. İkisi arasında seçim yaparken bağlamınıza bakmanız gerekir. Aşağıdaki tablo iki yaklaşımı karşılaştırır:
| Özellik | Supervisor | systemd |
|---|---|---|
| Kurulum | Ayrı paket gerektirir | İşletim sistemiyle gelir |
| Çoklu süreç (numprocs) | Tek satırda, yerleşik | Her kopya için ayrı unit/template |
| Yapılandırma dili | Basit INI blokları | Unit dosyası bölümleri |
| Log toplama | Dosyaya yerleşik + döndürme | journald üzerinden |
| Kök yetki gereksinimi | Kök olmadan da kurulabilir | Sistem servisi için kök gerekir |
| Süreç yönetimi arayüzü | supervisorctl (tek merkez) | systemctl (sistem geneli) |
| Alt süreç grupları | stopasgroup / killasgroup | KillMode ayarları |
Pratik tavsiyem şudur: aynı sunucuda çok sayıda benzer arka plan süreci (özellikle çoklu kuyruk işçisi) çalıştırıyor ve bunları tek bir sade arayüzden yönetmek istiyorsanız Supervisor çok konforludur; numprocs ile bir satırda ölçeklenmesi ve okunaklı yapılandırması ekip için büyük kolaylıktır. Buna karşılık ek bir bağımlılık taşımak istemiyor, süreçlerinizi işletim sistemiyle bütünleşik yönetmek ve logları journald ile merkezileştirmek istiyorsanız systemd yeterli, hatta daha temiz olabilir. İlginç bir ayrıntı, Supervisor'ın kendisinin de bir systemd servisi olarak çalışmasıdır; yani ikisi rakip değil, farklı soyutlama katmanlarıdır. Konuyu derinlemesine ele aldığımız systemd servis yönetimi yazımız, doğrudan systemd kullanmak isteyenler için iyi bir başlangıçtır.
Yaygın Sorunlar ve Çözümleri#
Supervisor ile en sık karşılaşılan durum, bir sürecin FATAL durumuna düşmesidir. supervisorctl status çıktısında FATAL görüyorsanız, süreç startretries sayısınca denenmesine rağmen startsecs süresini dolduramadan çökmüş demektir. İlk yapmanız gereken hata logunu okumaktır: sudo supervisorctl tail bot stderr ya da doğrudan stderr_logfile dosyasına bakın. Neredeyse her zaman gerçek neden oradadır; en yaygın hatalar command satırındaki yanlış yorumlayıcı yolu, çalışma dizini izinleri ya da eksik bir ortam değişkenidir. Sorunu çözdükten sonra sudo supervisorctl start bot ile yeniden başlatabilirsiniz.
İkinci sık hata, ortam değişkenleriyle ilgilidir. Supervisor süreçleri bir kabuk üzerinden başlatmadığı için, kabuk profilinizdeki (.bashrc, .profile) değişkenler otomatik olarak yüklenmez. Uygulamanız PATH, HOME ya da özel bir değişken bekliyorsa bunları program bloğunda açıkça tanımlamalısınız:
[program:api]
command=/var/www/api/venv/bin/python app.py
environment=HOME="/home/appuser",LANG="tr_TR.UTF-8",APP_ENV="production"
Bir diğer klasik tuzak, command satırında cd veya && gibi kabuk ifadeleri kullanmaya çalışmaktır; Supervisor bunları anlamaz. Birden fazla komut çalıştırmanız veya kabuk özellikleri kullanmanız gerekiyorsa, komutunuzu açıkça bash -c "..." ile sarmalayın ya da çalışma dizini için directory yönergesini kullanın. Son olarak, alt süreç oluşturan programlarda az önce bahsettiğimiz stopasgroup/killasgroup eksikliği, durdurulan süreçlerin arkasında yetim işlemler bırakır; bu tür programlarda bu iki satırı eklemeyi alışkanlık haline getirin. Sunucunuzda süreçlerin genel sağlığını ps, top veya htop gibi araçlarla düzenli izlemek de bu sorunları erken yakalamanıza yardımcı olur.
Sıkça Sorulan Sorular#
Supervisor ile nohup arasındaki fark nedir?#
nohup yalnızca bir komutu arka plana atar ve terminal kapandığında ölmesini engeller; ancak süreci izlemez, çöktüğünde yeniden başlatmaz ve sunucu yeniden açıldığında geri getirmez. Supervisor ise süreci sürekli denetler, beklenmedik çıkışlarda otomatik yeniden başlatır, açılışta ayağa kaldırır ve loglarını düzenli tutar. Kısacası nohup tek seferlik bir çözüm, Supervisor ise üretim ortamı için tasarlanmış kalıcı bir süreç yöneticisidir.
Yapılandırma dosyasını değiştirdim ama etkisi olmadı, neden?#
Çünkü restart komutu yalnızca süreci yeniden başlatır, yapılandırmayı yeniden okumaz. Bir .conf dosyasını düzenledikten sonra mutlaka önce sudo supervisorctl reread ile Supervisor'ın değişikliği fark etmesini sağlayın, ardından sudo supervisorctl update ile uygulayın. Bu ikili, systemd'deki daemon-reload komutunun karşılığıdır ve yalnızca restart demek çoğu zaman değişikliğin etkisiz kalmasına yol açar.
numprocs ile birden fazla süreç çalıştırınca hepsini nasıl yönetirim?#
numprocs ile tanımlı süreçler bir grup oluşturur ve process_name şablonu sayesinde worker_00, worker_01 gibi adlarla anılır. Grubun tamamını yönetmek için grup adının sonuna :* eklersiniz; örneğin sudo supervisorctl restart worker:* tüm işçileri birden yeniden başlatır. Tek bir kopyayı yönetmek isterseniz tam adını (worker:worker_01) belirtebilir, status ile de her kopyanın durumunu ayrı ayrı görebilirsiniz.
Supervisor süreci sürekli yeniden başlatıyor, bunu nasıl durdururum?#
Bu, sürecinizin başlar başlamaz çöktüğü ve Supervisor'ın onu ayakta tutmaya çalışırken döngüye girdiği anlamına gelir. Önce supervisorctl tail sürec stderr ile hata logunu okuyun; genellikle yanlış bir komut yolu, eksik ortam değişkeni ya da kullanımdaki bir port gibi bir başlangıç hatası görürsünüz. Kök nedeni çözmeden autorestart kapatmak sorunu gizler ama gidermez; doğru yaklaşım logdaki hatayı düzeltmek, gerekiyorsa startretries ve startsecs değerlerini gerçekçi ayarlamaktır.
Laravel kuyruk işçilerini kod dağıtımından sonra nasıl yenilerim?#
Kuyruk işçileri kodu bellekte tutar, bu yüzden yeni bir sürüm dağıttığınızda otomatik olarak güncellenmezler. php artisan queue:restart komutunu çalıştırdığınızda Laravel, tüm işçilere o anki işi bitirince nazikçe kapanmaları için bir sinyal gönderir; Supervisor da autorestart=true sayesinde onları yeni kodla anında geri başlatır. Bu yöntem çalışan bir görevi yarıda kesmediği için üretimde güvenlidir; asla işçileri kill ile zorla sonlandırmayın.
Supervisor'ı root olmadan kullanabilir miyim?#
Evet, Supervisor kök olmayan bir kullanıcıyla da çalıştırılabilir; bu, paylaşımlı ortamlarda veya izole edilmiş uygulama hesaplarında yararlıdır. Kendi supervisord.conf dosyanızı oluşturup soket ve log yollarını kullanıcının yazma izni olan dizinlere yönlendirir, ardından supervisord -c ~/supervisord.conf ile başlatırsınız. Ancak sistem geneli bir servis olarak açılışta otomatik başlaması ve www-data gibi kullanıcılar adına süreç çalıştırması için genellikle kök yetkisiyle kurulan sistem kurulumu tercih edilir.
Kapanış#
Supervisor, bir arka plan sürecini "SSH oturumu kapanınca ölen bir komut" olmaktan çıkarıp "sunucu 7/24 ayakta tuttuğu güvenilir bir servis" haline getiren pratik bir araçtır. Program bloğundaki birkaç satırla süreçlerinizi otomatik başlatabilir, çöktüklerinde kendiliğinden toparlanmalarını sağlayabilir, numprocs ile ölçekleyebilir ve tüm loglarını tek bir yerden izleyebilirsiniz. Özellikle Laravel kuyruk işçileri ve uzun süreli Python worker'ları için Supervisor, üretim ortamının sessiz ama vazgeçilmez bir bileşenidir.
Supervisor kurup kendi süreçlerinizi özgürce yönetmek için tam kök erişimine sahip bir sunucuya ihtiyacınız var. Clou.TR'nin VDS sunucuları ve sanal sunucu çözümleri size bu esnekliği sunar; kurulum ve yapılandırma yükünü üstlenmek istemiyorsanız sunucu yönetimi hizmetimiz ile Supervisor süreçlerinizi biz sizin adınıza kurup izleyelim. Uygulamalarınızı SSL ve WAF ile güvence altına alabilir, tüm sunucu paketlerimizi inceleyerek projeniz için en uygun altyapıyı seçebilirsiniz.