systemd-analyze ile Linux Açılış Sürecini ve Servis Gecikmelerini Analiz Etme

Bir sistemi devreye aldığınızda boot süresinin 2 dakikayı geçtiğini fark ettiğinizde, ilk içgüdü genellikle “hangi servis bu kadar uzun sürüyor?” sorusunu sormak oluyor. Ben de yıllar önce böyle bir soruyla karşılaştığımda dmesg çıktısını satır satır okumaya çalışıyordum. Sonra systemd-analyze ile tanıştım ve o günden beri boot analizi konusunda hayatım çok daha kolaylaştı.

systemd-analyze, systemd tabanlı Linux dağıtımlarında (Ubuntu, Debian, RHEL, CentOS, Fedora ve benzerleri) açılış sürecini detaylı şekilde incelemenizi sağlayan yerleşik bir araç. Kurulum gerektirmiyor, ekstra bir şey yüklemeniz gerekmiyor; systemd ile birlikte geliyor. Ama çoğu sysadmin bu aracın gerçek kapasitesini bilmiyor ya da sadece systemd-analyze blame komutunu çalıştırıp geçiyor. Oysa bu araçla yapabilecekleriniz çok daha derin.

Temel Kullanım: Boot Süresini Ölçmek

En sade haliyle systemd-analyze komutu, son açılış işlemine ait üç temel metriği gösterir:

systemd-analyze

Çıktı şuna benzer bir şey olacak:

Startup finished in 3.258s (firmware) + 1.892s (loader) + 2.041s (kernel) + 8.723s (userspace) = 15.914s
graphical.target reached after 8.701s in userspace

Bu çıktıyı yorumlamak önemli. firmware süresi BIOS/UEFI’nin başlangıcından bootloader’a kadar geçen süreyi gösteriyor. loader GRUB gibi bootloader’ın çalışma süresi. kernel ise Linux çekirdeğinin kendi başlatma süreci. Bizim müdahale edebileceğimiz yer büyük oranda userspace kısmı; yani servisler, mount işlemleri ve systemd unit’lerinin başlatılması.

Bir bulut sunucusunda ya da minimal kurulumda firmware ve loader süreleri genellikle 1-2 saniyeyi geçmez. Ama userspace 30-40 saniyeye çıkıyorsa, orada araştırılacak bir şeyler var demektir.

Suçluyu Bulmak: systemd-analyze blame

İlk başvurulacak komut genellikle bu oluyor:

systemd-analyze blame

Bu komut, başlatılması en uzun süren servisleri sıradan büyüğe doğru listeler:

         12.345s NetworkManager-wait-online.service
          8.901s plymouth-quit-wait.service
          6.234s dev-sda1.device
          4.112s udisks2.service
          3.891s ModemManager.service
          2.654s accounts-daemon.service
          1.876s apt-daily.service
          1.234s thermald.service
          ...

Burada dikkat etmeniz gereken, bir servisin uzun sürmesinin her zaman sorun olmadığıdır. Bazı servisler paralel olarak başlar ve kritik yol üzerinde olmayabilir. blame size ham süreleri gösterir ama bağımlılık zincirini göstermez. Gerçek darboğazı anlamak için bir sonraki komuta geçmek gerekiyor.

Sık karşılaştığım bir senaryo şu: NetworkManager-wait-online.service neredeyse her zaman listenin başında çıkıyor. Bu servis, ağ bağlantısı kurulana kadar bekliyor. Bir masaüstü makinede belki mantıklı ama bir sunucuda çoğu zaman devre dışı bırakılabilir:

sudo systemctl disable NetworkManager-wait-online.service

Görsel Analiz: Critical Chain

blame komutunun eksik bıraktığı noktayı critical-chain alt komutu tamamlıyor. Bu komut, boot sürecindeki kritik yolu, yani en uzun süren bağımlılık zincirini gösteriyor:

systemd-analyze critical-chain

Çıktı şuna benzer:

The time when unit became active or started is printed after the "@" character.
The time the unit took to start is printed after the "+" character.

graphical.target @8.701s
└─multi-user.target @8.700s
  └─postgresql.service @6.123s +2.577s
    └─network.target @6.119s
      └─NetworkManager.service @2.891s +3.228s
        └─dbus.service @2.887s +0.004s
          └─basic.target @2.881s
            └─sockets.target @2.880s

Bu ağaç yapısı çok değerli bilgi içeriyor. @ işaretinden sonraki süre o unit’in ne zaman aktif olduğunu, + işaretinden sonraki süre ise o unit’in başlaması için ne kadar zaman harcandığını gösteriyor.

Belirli bir servis için de kritik zinciri görebilirsiniz:

systemd-analyze critical-chain postgresql.service

Bu özellikle bir servisin neden geç başladığını anlamaya çalışırken inanılmaz faydalı. “PostgreSQL neden 30 saniye sonra hazır oluyor?” sorusunun cevabını bulmak için bu komutu kullanıyorum.

SVG ile Görsel Boot Grafiği

Terminalde çalışmak her zaman yeterli olmayabilir, özellikle bir rapor hazırlıyorsanız ya da bir meslektaşınıza göstermek istiyorsanız. systemd-analyze plot komutu tüm boot sürecini bir SVG dosyasına çıkarıyor:

systemd-analyze plot > /tmp/boot-analysis.svg

Bu dosyayı herhangi bir tarayıcıda açtığınızda, her servisin ne zaman başladığını ve ne kadar sürdüğünü gösteren renkli bir Gantt grafiği görüyorsunuz. Paralel başlayan servisler yan yana, birbirini bekleyen servisler sıralı görünüyor. Bu grafik, bağımlılık ilişkilerini ve gecikme noktalarını bir anda kavramanızı sağlıyor.

Özellikle müşterilere ya da yöneticilere “şu servis boot sürecini uzatıyor” diye anlatmak zorunda kaldığımda bu SVG grafiği çok işe yarıyor. Görsel materyalin etkisi tartışılmaz.

Systemd Unit Dosyalarını Doğrulamak

systemd-analyze verify komutu, bir unit dosyasında yazım hatası veya mantıksal hata olup olmadığını kontrol ediyor. Yeni bir servis yazarken ya da mevcut bir unit dosyasını düzenlerken her seferinde bu komutu çalıştırıyorum:

systemd-analyze verify /etc/systemd/system/myapp.service

Eğer bir sorun varsa açıklayıcı bir hata mesajı alıyorsunuz. Örneğin:

/etc/systemd/system/myapp.service:12: Unknown key name 'ExecRestart' in section 'Service'

Bu, ExecRestart diye bir direktif olmadığını, doğrusunun ExecReload olduğunu anlamanızı sağlıyor. systemctl start yapıp hata almak yerine önceden doğrulamak çok daha sağlıklı bir yaklaşım.

Birden fazla dosyayı aynı anda doğrulamak da mümkün:

systemd-analyze verify /etc/systemd/system/*.service

Güvenlik Skoru: Security

Bu özelliği çok az kişi biliyor ama bence en değerli olanlardan biri. systemd-analyze security komutu, servislerin systemd güvenlik sandbox özelliklerini ne kadar kullandığını analiz ediyor:

systemd-analyze security nginx.service

Çıktı oldukça detaylı:

  NAME                                                        DESCRIPTION                                                     EXPOSURE
✗ RootDirectory=/RootImage=                                   Service runs within the host's root directory                    0.1
✗ SupplementaryGroups=                                        Service runs with supplementary groups                           0.1
✓ RemoveIPC=                                                  Service cleans up IPC objects on exit
✗ User=/DynamicUser=                                         Service runs as root user                                        0.4
...

-> Overall exposure level for nginx.service: 9.2 UNSAFE

Daha düşük skor daha iyidir. 0-4 arası güvenli, 4-7 arası orta, 7-10 arası güvensiz anlamına geliyor. Bu çıktı size servisin hangi güvenlik özelliklerinden yararlanmadığını ve nasıl sertleştirebileceğinizi gösteriyor.

Örneğin bir internal uygulama servisi için şu direktifleri unit dosyasına eklemek güvenlik skorunu ciddi ölçüde düşürür:

systemd-analyze security --no-pager myapp.service 2>&1 | head -50
[Service]
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/myapp

Bu direktifleri ekledikten sonra verify ile doğrulayıp security ile tekrar skor alıyorum. Bir nevi güvenlik odaklı iteratif geliştirme süreci.

Gerçek Dünya Senaryosu: Yavaş Boot Eden Bir Uygulama Sunucusu

Bir e-ticaret şirketinde uygulama sunucuları her güncelleme sonrasında yeniden başlatılıyordu ve bu süreç 3-4 dakika alıyordu. Load balancer’dan geç kaldıklarında trafik diğer sunuculara yığılıyordu. Sorunu araştırmak için şu adımları izledim:

# İlk önce genel durumu gördüm
systemd-analyze

# Ardından suçluları listeledim
systemd-analyze blame | head -20

# Kritik zinciri inceledim
systemd-analyze critical-chain

# SVG grafiğini aldım
systemd-analyze plot > /tmp/boot-$(hostname)-$(date +%Y%m%d).svg

critical-chain çıktısında şunu gördüm: uygulama servisi, veritabanı bağlantısı için postgresql.service‘i bekliyordu, postgresql.service ise remote-fs.target‘ı bekliyordu, remote-fs.target da NFS mount işlemini bekliyordu. NFS sunucusunun cevap vermesi bazen 45-60 saniye alıyordu.

Çözüm birkaç katmanlıydı:

# NFS mount için timeout ayarı
# /etc/systemd/system/mnt-data.mount dosyasına
[Mount]
Options=defaults,timeo=5,retrans=2,soft

# Uygulama servisinin NFS'e olan sert bağımlılığını kırdık
# myapp.service dosyasında Requires= yerine Wants= kullandık
[Unit]
Wants=mnt-data.mount
After=mnt-data.mount

Bu değişikliklerden sonra boot süresi 3-4 dakikadan 40-45 saniyeye indi. Kritik bağımlılığı Requires yerine Wants ile tanımlamak, NFS mount başarısız olsa bile uygulamanın kendi error handling mekanizmasıyla devam etmesini sağladı.

Boot Sürelerini Karşılaştırmak: Time Komutunun Detayları

systemd-analyze time komutu systemd-analyze ile aynı sonucu vermekle birlikte, özellikle script içinde kullanım için daha temiz bir çıktı sunuyor:

systemd-analyze time

Son birkaç boot arasında karşılaştırma yapmak istiyorsanız, bu bilgileri journal üzerinden de çekebilirsiniz:

# Son 5 boot için kernel mesajlarına bak
journalctl --list-boots | head -5

# Belirli bir boot ID için analiz
journalctl -b -1 | grep "Startup finished"
# Bir önceki boot'un analizini yapmak için
systemd-analyze --system blame

Birden fazla sunucu üzerinde boot süresi karşılaştırması yapmak istediğinizde şu basit script işe yarıyor:

#!/bin/bash
# boot-compare.sh - Birden fazla sunucuda boot sürelerini karşılaştır

SERVERS=("web01" "web02" "web03" "db01")

for server in "${SERVERS[@]}"; do
    echo -n "$server: "
    ssh "$server" "systemd-analyze 2>/dev/null | grep 'Startup finished'" 2>/dev/null || echo "Bağlanılamadı"
done

Unit Bağımlılık Grafiğini Çıkarmak

Bazen bir servisin hangi servislerle bağlantılı olduğunu, hangi servislerin onu beklediğini görmek istiyorsunuz. systemd-analyze dot komutu GraphViz formatında bağımlılık grafiği üretiyor:

# Tüm servisler için bağımlılık grafiği (çok büyük olabilir)
systemd-analyze dot | dot -Tsvg -o /tmp/full-deps.svg

# Sadece belirli bir servis ve bağımlılıkları
systemd-analyze dot nginx.service | dot -Tsvg -o /tmp/nginx-deps.svg

# Belirli pattern'lere göre filtrele
systemd-analyze dot --to-pattern='*.target' | dot -Tsvg -o /tmp/targets.svg

Bu komut için sisteminizde graphviz paketinin kurulu olması gerekiyor:

# Debian/Ubuntu
sudo apt install graphviz

# RHEL/CentOS
sudo dnf install graphviz

Bağımlılık grafiği özellikle yeni bir ortamı devralırken ya da servis mimarisini dokümante ederken çok değerli. Hangi servisin neyi tetiklediğini, hangi target’ların hangi servisleri içerdiğini görsel olarak anlamak, uzun man page okumaktan çok daha hızlı bir kavrayış sağlıyor.

Systemd Condition ve Assert Hatalarını Tespit Etmek

Bazen bir servis başlamıyor ama systemctl status size net bir hata vermeyebiliyor. systemd-analyze bu durumda da yardımcı olabiliyor:

# Başlamayan servislerin condition durumunu kontrol et
systemd-analyze condition nginx.service

# Birden fazla servis için
systemd-analyze condition sshd.service NetworkManager.service

Çıktıda hangi ConditionPathExists, ConditionFileNotEmpty gibi koşulların başarısız olduğunu görebiliyorsunuz. Örneğin bir servis ConditionPathExists=/etc/myapp/config.yaml içeriyorsa ve bu dosya yoksa, servis başlamadan “skipped” olarak işaretleniyor. Bu durumu tespit etmek systemd-analyze condition ile saniyeler içinde mümkün.

Performans İpuçları ve Sık Karşılaşılan Sorunlar

Boot süresini kısaltmak için blame ve critical-chain analizinden sonra uyguladığım pratik adımlar şunlar:

  • plymouth-quit-wait.service: Grafik arayüzü olmayan sunucularda Plymouth gereksiz. sudo systemctl disable plymouth.service ile devre dışı bırakın.
  • ModemManager.service: Modem kullanmayan sunucularda kapatın. sudo systemctl disable ModemManager.service
  • apt-daily.service ve apt-daily-upgrade.service: Boot sırasında paket güncelleme kontrolü yapıyor. Bunu boot sonrası bir zamanlama ile erteleyebilirsiniz.
  • systemd-resolved: Bazı ortamlarda DNS çözümlemesi yavaş olabiliyor. /etc/resolv.conf ayarlarını doğrudan yapılandırmak daha hızlı sonuç verebilir.
  • Swap birimleri: Büyük swap dosyaları aktive edilirken zaman alabiliyor. SSD üzerinde swap kullanıyorsanız bu daha az sorun çıkarır.

Bunların yanı sıra systemd-analyze araçlarını düzenli olarak bir monitoring pipeline’a dahil etmek de faydalı. Her deployment sonrasında otomatik boot analizi alıp önceki değerlerle karşılaştırmak, beklenmedik performans regresyonlarını erkenden yakalamayı sağlıyor.

# Basit bir boot süresi log script'i
systemd-analyze >> /var/log/boot-times.log
echo "$(date) - $(systemd-analyze | grep Startup)" >> /var/log/boot-times.log

Sonuç

systemd-analyze tek bir araç gibi görünse de aslında içinde farklı amaçlara hizmet eden birçok alt komut barındırıyor. blame ile hızlı triage yapıyorsunuz, critical-chain ile gerçek darboğazı buluyorsunuz, plot ile görselleştiriyorsunuz, security ile güvenlik açıklarını tespit ediyorsunuz, verify ile unit dosyası hatalarını önceden yakalıyorsunuz.

Yıllar içinde edindiğim en önemli alışkanlıklardan biri: yeni bir Linux sistemi devreye aldığımda ya da mevcut bir sistemde boot süresinin uzadığını fark ettiğimde, ilk 5 dakikayı bu araçla geçiriyorum. Çoğu zaman sorunun kaynağını çok hızlı buluyor ve düzeltebiliyorum.

systemd-analyze sadece sorun giderme değil, sistem optimizasyonunun da temel taşlarından biri. Üstelik öğrenmesi zor değil, dene yanılma gerektirmiyor ve her systemd tabanlı sistemde hazır bulunuyor. Eğer bugüne kadar sadece blame kullandıysanız, critical-chain ve security alt komutlarını da araç setinize katmak için iyi bir zaman.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir