Rocky Linux’ta Servis Yönetimi ve systemd Kullanımı

Rocky Linux’a geçiş yapan ya da yeni başlayan sistem yöneticilerinin en çok kafasının karıştığı konulardan biri servis yönetimi oluyor. CentOS 7’den gelenler systemd’ye aşina olsa da, Rocky Linux’un getirdiği bazı nüanslar ve günlük operasyonlarda karşılaşılan durumlar pratikte farklı bir öğrenme eğrisi yaratıyor. Bu yazıda systemd’yi Rocky Linux özelinde ele alacağız, sadece teoride değil gerçek dünya senaryolarıyla birlikte.

systemd Nedir ve Neden Önemli?

systemd, modern Linux dağıtımlarının büyük çoğunluğunda kullanılan init sistemi ve servis yöneticisidir. Rocky Linux 8 ve 9’da systemd varsayılan olarak gelir ve sistem açılışından kapanışına kadar neredeyse her şeyi yönetir. Eski SysV init sistemine kıyasla paralel servis başlatma, bağımlılık yönetimi, merkezi log yönetimi ve çok daha fazlasını sunar.

Bir Rocky Linux sunucusunda systemd’nin sorumlu olduğu alanlar şunlardır:

  • Sistem başlangıcında servislerin doğru sırada ayağa kalkması
  • Servisler arası bağımlılıkların yönetimi
  • Servis çökmelerinde otomatik yeniden başlatma
  • journald aracılığıyla merkezi log toplama
  • cgroup’larla kaynak kısıtlamaları
  • Socket ve timer aktivasyonu

systemctl ile Temel Servis Operasyonları

Günlük hayatta en çok kullanacağınız araç systemctl‘dir. Temel komutları ezberlemek yerine anlamak çok daha işlevsel olacaktır.

# Servis durumunu kontrol etmek
systemctl status nginx

# Servisi başlatmak
systemctl start nginx

# Servisi durdurmak
systemctl stop nginx

# Servisi yeniden başlatmak (tam durdur/başlat döngüsü)
systemctl restart nginx

# Servisi yeniden yüklemek (konfig reload, genellikle kesintisiz)
systemctl reload nginx

# Sistem açılışında otomatik başlamasını sağlamak
systemctl enable nginx

# Sistem açılışında başlamasını engellemek
systemctl disable nginx

# Hem enable hem start yapmak (çok kullanışlı!)
systemctl enable --now nginx

# Hem disable hem stop yapmak
systemctl disable --now nginx

enable --now kombinasyonu benim en sevdiğim kısayollardan biridir. Yeni bir servis kurduğunuzda hem aktif et hem başlat demek için iki komut yazmak yerine bunu kullanın.

Servis Durumunu Anlamak

systemctl status çıktısını okumayı bilmek kritik öneme sahiptir. Bir sorun olduğunda bu çıktı size çok şey anlatır.

systemctl status postgresql-14

Çıktıda dikkat etmeniz gereken noktalar şunlardır:

  • Active: active (running): Servis çalışıyor
  • Active: inactive (dead): Servis durdurulmuş durumda
  • Active: failed: Servis hata verdi ve durdu
  • Loaded: enabled: Sistem açılışında başlayacak şekilde ayarlanmış
  • Loaded: disabled: Sistem açılışında başlamayacak

Servis Listelerini Yönetmek

Sunucunuzda hangi servislerin çalıştığını, hangilerinin başarısız olduğunu görmek için aşağıdaki komutları kullanabilirsiniz.

# Tüm aktif servisleri listele
systemctl list-units --type=service

# Sadece başarısız olan servisleri göster
systemctl list-units --type=service --state=failed

# Tüm servisleri (aktif, inaktif, başarısız) listele
systemctl list-units --type=service --all

# Enable edilmiş servisleri listele
systemctl list-unit-files --type=service --state=enabled

# Servisin enable durumunu hızlıca kontrol et
systemctl is-enabled nginx
systemctl is-active nginx

Bir sunucuyu devraldığınızda ilk yapacağınız şeylerden biri systemctl list-units --state=failed komutunu çalıştırmak olmalı. Sessiz sedasız başarısız olmuş servisler genellikle büyük problemlerin habercisidir.

Gerçek Dünya Senaryosu 1: Nginx Çalışmıyor, Ne Yapacaksın?

Gece 2’de telefonunuz çalıyor. Web sitesi erişilemiyor. Sunucuya bağlanıyorsunuz ve şu adımları izliyorsunuz:

# Önce durumu kontrol et
systemctl status nginx

# Detaylı log için journalctl kullan
journalctl -u nginx -n 50 --no-pager

# Son 1 saatteki logları göster
journalctl -u nginx --since "1 hour ago"

# Gerçek zamanlı log takibi
journalctl -u nginx -f

Diyelim ki status çıktısında “Address already in use” hatası gördünüz. Port 80 başka bir process tarafından kullanılıyor demektir.

# Hangi process portu kullanıyor?
ss -tlnp | grep :80

# Ya da
lsof -i :80

# Process'i öldür ve nginx'i başlat
kill -9 <PID>
systemctl start nginx

Bu senaryo, systemctl ve journalctl’i birlikte kullanmanın önemini gösteriyor. Sadece status komutuna bakmak yetmez, log’ları da incelemeniz gerekir.

journald ile Log Yönetimi

systemd’nin log sistemi olan journald, Rocky Linux’ta merkezi log yönetimini üstlenir. journalctl komutu bu logları sorgulamanızı sağlar.

# Tüm sistem loglarını göster
journalctl

# Belirli bir servise ait loglar
journalctl -u sshd

# Son N satırı göster
journalctl -n 100

# Belirli bir zaman aralığı
journalctl --since "2024-01-15 10:00:00" --until "2024-01-15 12:00:00"

# Sadece hata seviyesindeki loglar
journalctl -p err

# Kernel logları
journalctl -k

# Bir önceki boot'a ait loglar (çök-yeniden başla durumlarında çok işe yarar)
journalctl -b -1

# Disk kullanımını göster
journalctl --disk-usage

# Eski logları temizle (2 haftadan eski)
journalctl --vacuum-time=2weeks

Önemli not: Rocky Linux’ta journald logları varsayılan olarak /run/log/journal/ altında RAM’de tutulur ve yeniden başlatmada silinir. Kalıcı log tutmak için /etc/systemd/journald.conf dosyasında Storage=persistent ayarını yapmanız gerekir.

# Kalıcı log için
mkdir -p /var/log/journal
systemctl restart systemd-journald

Özel systemd Servis Dosyası Oluşturmak

Bu konu sistem yöneticilerinin gözünü en çok korkutan konulardan biridir ama aslında oldukça basittir. Kendi Python uygulamanızı, Go binary’nizi veya herhangi bir scripti systemd servisi olarak çalıştırmak istediğinizde buna ihtiyaç duyarsınız.

Örnek senaryo: Bir Python Flask uygulamasını servis olarak tanımlamak.

# Servis dosyası oluştur
vim /etc/systemd/system/myapp.service
[Unit]
Description=My Flask Application
After=network.target
Wants=postgresql.service
After=postgresql.service

[Service]
Type=simple
User=appuser
Group=appuser
WorkingDirectory=/opt/myapp
Environment="FLASK_ENV=production"
Environment="DATABASE_URL=postgresql://localhost/myapp"
ExecStart=/opt/myapp/venv/bin/python app.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
# Yeni servis dosyasını systemd'ye tanıt
systemctl daemon-reload

# Servisi başlat ve enable et
systemctl enable --now myapp

# Logları izle
journalctl -u myapp -f

Servis dosyasındaki önemli parametreleri açıklayalım:

  • After: Bu servis hangi servislerden sonra başlamalı
  • Wants: İsteğe bağlı bağımlılık (başlamazsa da devam eder)
  • Requires: Zorunlu bağımlılık (başlamazsa bu da başlamaz)
  • Type=simple: Process doğrudan çalışır, fork etmez
  • Type=forking: Daemon modunda fork eden eski tarz process’ler için
  • Type=oneshot: Bir kez çalışıp biten işler için (örn. script)
  • Restart=on-failure: Sadece hata durumunda yeniden başlat
  • Restart=always: Her durumda yeniden başlat
  • RestartSec=5: Yeniden başlatma öncesi bekleme süresi
  • WantedBy=multi-user.target: Normal çok kullanıcılı mod (sunucularda standart)

Gerçek Dünya Senaryosu 2: Servis Sürekli Çöküyor

Bir servisin sürekli yeniden başladığını fark ettiniz. Bu durumda systemd’nin “rate limiting” mekanizmasına takılabilirsiniz.

# Servis durumunu kontrol et
systemctl status myapp

# "start-limit-hit" hatası görürseniz reset yapın
systemctl reset-failed myapp
systemctl start myapp

# Neden çöktüğünü anlamak için logları inceleyin
journalctl -u myapp -p err --since "30 minutes ago"

Rate limiting’i geçici olarak devre dışı bırakmak isterseniz servis dosyasına şunu ekleyebilirsiniz:

[Service]
StartLimitIntervalSec=0

Ama bunu production’da kalıcı çözüm olarak kullanmayın. Asıl problemi çözmeniz gerekir.

systemd Timer’ları: Cron’un Modern Alternatifi

Rocky Linux’ta cron yerine systemd timer’larını kullanmak giderek yaygınlaşıyor. Timer’lar daha esnek zamanlama, bağımlılık yönetimi ve journald üzerinden merkezi log sunuyor.

Örnek: Her gece yedekleme işi için timer.

# Önce service dosyasını oluştur
vim /etc/systemd/system/backup.service
[Unit]
Description=Nightly Database Backup
After=postgresql.service

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup-db.sh
StandardOutput=journal
StandardError=journal
# Timer dosyasını oluştur
vim /etc/systemd/system/backup.timer
[Unit]
Description=Run Database Backup Nightly

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target
# Timer'ı enable et ve başlat (service'i değil!)
systemctl enable --now backup.timer

# Aktif timer'ları listele
systemctl list-timers

# Timer'ın ne zaman çalışacağını gör
systemctl status backup.timer

Persistent=true ayarı çok önemlidir. Sunucu kapalıyken zamanı geçen görev, sunucu açıldığında hemen çalışır. Cron’da bu davranışı elde etmek için ek konfigürasyon gerekirdi.

systemd ile Kaynak Yönetimi

systemd, cgroup’lar aracılığıyla servislere kaynak limiti koymanızı sağlar. Production ortamında bir servisin kontrolden çıkıp tüm CPU’yu veya RAM’i yemesini engellemek için çok işe yarar.

# Servis dosyasına kaynak limitleri ekle
vim /etc/systemd/system/myapp.service
[Service]
# CPU kullanımını sınırla (1 CPU çekirdeğinin %50'si)
CPUQuota=50%

# Bellek limitini ayarla
MemoryLimit=512M

# Ya da modern sözdizimi (Rocky Linux 9 önerilir)
MemoryMax=512M
MemorySwapMax=0

# IO limiti
IOWeight=50
# Değişikliği uygula
systemctl daemon-reload
systemctl restart myapp

# Kaynak kullanımını gerçek zamanlı izle
systemctl status myapp
# Ya da daha detaylı
systemd-cgtop

Override dosyaları sayesinde paket güncellemelerinde kayıp yaşamadan orijinal servis dosyalarını değiştirmeden konfigürasyon ekleyebilirsiniz:

# Doğru yol: drop-in override dosyası oluştur
systemctl edit nginx

# Bu komut /etc/systemd/system/nginx.service.d/override.conf dosyasını açar
# Buraya sadece değiştirmek istediğiniz kısımları ekleyin

Önemli systemd Hedefleri (Targets)

Rocky Linux’ta runlevel kavramının yerini target’lar almıştır.

  • multi-user.target: Eski runlevel 3, network var, grafik arayüz yok (sunucu standardı)
  • graphical.target: Eski runlevel 5, grafik arayüz dahil
  • rescue.target: Tek kullanıcı modu, minimal servisler
  • emergency.target: Acil durum, sadece root shell
# Mevcut default target'ı göster
systemctl get-default

# Default target'ı değiştir
systemctl set-default multi-user.target

# Geçici olarak rescue mode'a geç
systemctl isolate rescue.target

# Sistemi yeniden başlat
systemctl reboot

# Sistemi kapat
systemctl poweroff

# Sistemi askıya al
systemctl suspend

Gerçek Dünya Senaryosu 3: Sistem Açılışında Servis Sıralama Sorunu

Sık karşılaşılan bir sorun: Uygulama servisi database’den önce başlıyor ve hata veriyor. Bunun çözümü servis dosyasında bağımlılıkları doğru tanımlamakla ilgilidir.

[Unit]
Description=My Application
# Ağ hazır olduktan sonra başla
After=network-online.target
Wants=network-online.target

# PostgreSQL başladıktan sonra başla
After=postgresql-14.service
# PostgreSQL çalışmak zorunda, başlamazsa bu da başlamasın
Requires=postgresql-14.service

[Service]
Type=simple
ExecStart=/opt/myapp/bin/start.sh
# Servis başarıyla başladığını bildirene kadar bekle
ExecStartPost=/bin/sleep 2
Restart=on-failure
RestartSec=10

Burada After ve Requires arasındaki fark kritiktir. After sadece sıralamayı belirler, Requires ise zorunlu bağımlılık kurar. İkisini birlikte kullanmak genellikle doğru yaklaşımdır.

systemd-analyze ile Sistem Başlangıcını Optimize Etmek

Rocky Linux sunucunuzu kurup başlatma süresinin çok uzun olduğunu fark ettiniz. systemd-analyze bu konuda çok yardımcı olur.

# Toplam boot süresini göster
systemd-analyze

# Her servisin başlatma süresini göster (en yavaştan başlar)
systemd-analyze blame

# Kritik zinciri göster
systemd-analyze critical-chain

# SVG olarak boot grafiği oluştur
systemd-analyze plot > boot.svg

# Servis dosyasını syntax açısından doğrula
systemd-analyze verify /etc/systemd/system/myapp.service

systemd-analyze blame çıktısında uzun süren servisleri tespit edip disable edebilir ya da After ilişkilerini optimize edebilirsiniz.

Sık Yapılan Hatalar ve Çözümleri

Yıllar içinde gördüğüm en yaygın hataları ve çözümlerini paylaşayım:

daemon-reload unutmak: Servis dosyasını değiştirdikten sonra systemctl daemon-reload çalıştırmayı unutmak en klasik hatadır. Değişiklik görünmez ve eski konfigürasyonla çalışmaya devam eder.

Yanlış Type seçimi: Daemon fork eden bir uygulama için Type=simple kullanmak, servis başlar gibi görünür ama child process yönetimi bozulur. Uygulamanızın nasıl çalıştığını anlayıp doğru type’ı seçin.

ExecStart’ta shell özellikleri kullanmak: Servis dosyasında ExecStart=/bin/bash -c "command1 && command2" yerine mümkünse ayrı bir script dosyası oluşturun. Hata ayıklaması çok daha kolay olur.

Environment değişkenlerini yanlış tanımlamak: ExecStart‘tan önce EnvironmentFile kullanarak değişkenleri ayrı bir dosyadan okumak hem güvenli hem de yönetilebilirdir.

# /etc/systemd/system/myapp.service içinde
[Service]
EnvironmentFile=/etc/myapp/environment
ExecStart=/opt/myapp/bin/server

Sonuç

systemd, Rocky Linux’ta servis yönetiminin tam merkezindedir ve ne kadar iyi anlarsanız o kadar etkili bir sistem yöneticisi olursunuz. Temel systemctl komutlarından başlayarak özel servis dosyaları yazmaya, timer’larla cron’un ötesine geçmeye ve kaynak limitleriyle servisleri disipline etmeye kadar uzanan bu bilgi seti, günlük operasyonlarda size büyük zaman kazandırır.

Özellikle vurgulayacağım pratik noktalar şunlardır: Sorun anında önce systemctl status, ardından journalctl -u servis -n 100 alışkanlığını edinin. Özel servis yazarken mutlaka systemd-analyze verify ile doğrulayın. Paket servisleri düzenlerken doğrudan dosyayı değil systemctl edit ile override kullanın. Ve her zaman daemon-reload yapmayı unutmayın.

Rocky Linux, kurumsal ortamlar için mükemmel bir platform ve systemd’yi iyi bilmek bu platformda güvenilir, öngörülebilir bir altyapı kurmanın temel taşlarından biridir.

Yorum yapın