systemd-analyze ile Linux Açılış Süresi Optimizasyonu

Sunucunuzun açılışının dakikalar sürdüğünü fark ettiğinizde, ilk tepki genellikle “bir şeyler bozulmuş olmalı” olmaktadır. Oysa çoğu zaman sistem çalışıyor, sadece gereksiz yere yavaş açılıyor. Systemd’nin bize sunduğu systemd-analyze aracı, bu yavaşlığın tam olarak nerede yaşandığını tespit etmemizi ve somut adımlarla iyileştirmemizi sağlıyor. Bu yazıda, gerçek dünya senaryoları üzerinden açılış süresi optimizasyonunu adım adım ele alacağız.

systemd-analyze Nedir ve Neden Önemlidir

Systemd, modern Linux dağıtımlarının büyük çoğunluğunda init sistemi olarak kullanılıyor. Açılış sürecini paralel olarak yönetmesi, servis bağımlılıklarını akıllıca çözmesi ve kapsamlı loglama altyapısı ile sysadminlerin hayatını kolaylaştırıyor. Ancak zamanla sisteme eklenen servisler, yanlış yapılandırmalar veya gereksiz servisler açılış süresini ciddi şekilde uzatabilir.

systemd-analyze işte bu noktada devreye giriyor. Açılış sürecini milisaniye hassasiyetinde ölçüyor, hangi servisin ne kadar sürdüğünü gösteriyor ve kritik yolu (critical path) belirleyerek nereye odaklanmanız gerektiğini açıkça ortaya koyuyor.

Özellikle şu durumlarda bu araç hayat kurtarır:

  • Sunucu reboot sonrası hizmete geçme süresi SLA gereksinimlerini aşıyorsa
  • Yeni bir servis ekledikten sonra açılış belirgin şekilde yavaşladıysa
  • Container ortamlarında image başlatma sürelerini optimize etmeniz gerekiyorsa
  • Masaüstü sistemlerde kullanıcı deneyimini iyileştirmek istiyorsanız

Temel Kullanım: İlk Bakış

Herhangi bir parametre vermeden çalıştırdığınızda, systemd-analyze size üç temel metrik sunar:

systemd-analyze

Çıktı genellikle şu şekilde görünür:

Startup finished in 3.258s (kernel) + 12.431s (initrd) + 47.892s (userspace) = 1min 3.581s
graphical.target reached after 45.234s in userspace

Bu çıktıyı okurken dikkat etmeniz gereken noktalar:

  • kernel: Kernel’in yüklenip initrd’ye kontrolü devrettiği süre. Bu süre üzerinde çok az kontrolünüz var.
  • initrd: Initial RAM disk aşaması. Disk şifreleme, RAID veya LVM kullanıyorsanız burada zaman harcanabilir.
  • userspace: Systemd’nin devraldığı andan hedef target’a ulaşana kadar geçen süre. Optimizasyonun asıl yapılacağı alan burası.

Pratikte 1 dakikanın üzerinde bir değer gördüğünüzde alarm zillerinin çalması gerekir. Sağlıklı bir sunucu genellikle 20-30 saniyenin altında userspace süresine sahip olmalıdır.

blame: Suçlunun Peşinde

Açılışı en çok geciktiren servisleri bulmak için blame alt komutu kullanılır:

systemd-analyze blame
          34.218s NetworkManager-wait-online.service
          18.432s apt-daily-upgrade.service
           8.124s snapd.service
           5.891s plymouth-quit-wait.service
           4.234s dev-sda1.device
           3.128s systemd-udev-settle.service
           2.891s mysql.service
           1.456s docker.service
           0.923s ssh.service

Bu liste aldatıcı olabilir. Bir servisin uzun sürmesi, açılışı mutlaka o kadar uzattığı anlamına gelmez çünkü systemd paralel çalışır. Asıl kritik yolu belirlemek için farklı bir araca ihtiyacımız var.

critical-chain: Gerçek Darboğazı Bulmak

Kritik zincir, açılışı doğrudan geciktiren servis zincirini gösterir. Paralel çalışmayan, birbirini bekleyen servisler burada ortaya çıkar:

systemd-analyze critical-chain
The time when unit became active or started is printed after the "@" character.
The time the unit took to activate is printed after the "+" character.

graphical.target @45.234s
└─multi-user.target @45.233s
  └─docker.service @43.891s +1.456s
    └─network-online.target @43.889s
      └─NetworkManager-wait-online.service @9.671s +34.218s
        └─NetworkManager.service @9.234s +0.437s
          └─dbus.service @8.123s +1.111s
            └─basic.target @8.121s
              └─sockets.target @8.120s

Bu çıktıda net olarak görüyoruz: NetworkManager-wait-online.service 34 saniye bekliyor ve docker ardından başlıyor. Bu klasik bir sorun ve çözümü oldukça basit.

Belirli bir servisin kritik zincirini incelemek için:

systemd-analyze critical-chain mysql.service

SVG ile Görsel Analiz

Metin tabanlı çıktılar yeterli gelmiyorsa, açılış sürecini görsel olarak incelemek için SVG çıktısı alabilirsiniz. Bu özellikle karmaşık bağımlılık yapılarını anlamada çok işe yarıyor:

systemd-analyze plot > boot-analysis.svg

Dosyayı bir tarayıcıda açtığınızda, her servisin ne zaman başladığını ve ne kadar sürdüğünü yatay çubuklar halinde görebilirsiniz. Paralel çalışan servisler aynı zaman diliminde görünürken, birbirini bekleyenler sıralanmış şekilde görünür.

Eğer bir remote sunucudaysanız ve dosyayı yerel makinenize almak istiyorsanız:

scp user@sunucu:/tmp/boot-analysis.svg ~/Desktop/

Gerçek Dünya Senaryosu 1: NetworkManager-wait-online Sorunu

Bu, muhtemelen en sık karşılaşılan açılış gecikme sebebidir. NetworkManager-wait-online.service, sistemin bir ağ bağlantısı kurulana kadar beklemesini sağlar. Pek çok durumda bu bekleme gereksizdir.

Önce durumu kontrol edelim:

systemctl status NetworkManager-wait-online.service
systemctl is-enabled NetworkManager-wait-online.service

Eğer sisteminizdeki servisler network bağlantısına gerçekten ihtiyaç duymuyorsa veya bağlantı olmadan da başlayabiliyorsa, bu servisi devre dışı bırakabilirsiniz:

sudo systemctl disable NetworkManager-wait-online.service

Ancak bazı senaryolarda bu servise gerçekten ihtiyaç vardır. Örneğin NFS mount noktaları, ağ üzerinden erişilen veritabanları veya belirli monitoring araçları. Bu durumda servisi devre dışı bırakmak yerine sadece açılışı geciktirmemesini sağlayabiliriz:

sudo systemctl edit NetworkManager-wait-online.service

Açılan editörde şunları ekleyin:

[Service]
TimeoutStartSec=10

Bu sayede servis en fazla 10 saniye bekler ve vazgeçer, sisteminiz ilerler.

Gerçek Dünya Senaryosu 2: Gereksiz Servisleri Devre Dışı Bırakma

Bir Ubuntu sunucusunda masaüstü paketlerinin kurulu kalması, sunucu ortamında hiç kullanılmayacak servislerin çalışmasına neden olur. Benzer şekilde, test amaçlı kurulan uygulamaların servisleri temizlenmez.

Etkin olan tüm servisleri listelemek için:

systemctl list-units --type=service --state=active

Açılışta etkin olan ama şu an çalışmayan servisleri görmek için:

systemctl list-unit-files --type=service --state=enabled

Snap kullanmayan bir sunucuda snapd servislerini devre dışı bırakmak ciddi tasarruf sağlar:

sudo systemctl disable snapd.service
sudo systemctl disable snapd.socket
sudo systemctl disable snapd.seeded.service

Bluetooth kullanmayan bir sunucuda:

sudo systemctl disable bluetooth.service

Fiziksel ekran olmayan bir sunucuda plymouth (önyükleme ekranı animasyonu):

sudo systemctl disable plymouth-quit-wait.service
sudo systemctl disable plymouth-read-write.service

Her birini devre dışı bıraktıktan sonra mutlaka test edin ve systemd-analyze blame ile iyileşmeyi ölçün.

Servis Bağımlılıklarını Analiz Etme

Bir servisin neden yavaş başladığını anlamak için bağımlılık ağacını incelemek gerekir. systemd-analyze bunu da kolaylaştırıyor:

systemd-analyze dot mysql.service | dot -Tsvg > mysql-deps.svg

Bu komut graphviz paketini gerektirir. Yüklü değilse:

sudo apt install graphviz
# veya
sudo dnf install graphviz

Sadece belirli bir hedefin bağımlılıklarını görmek için:

systemd-analyze dot --to-pattern='multi-user.target' --from-pattern='*.service' | dot -Tsvg > deps.svg

Gerçek Dünya Senaryosu 3: Kendi Servisinizi Optimize Etme

Bir web uygulaması için yazdığınız systemd servis dosyasının açılışı yavaşlattığını fark ettiniz. Önce mevcut durumu analiz edelim:

systemd-analyze critical-chain myapp.service

Servis dosyanız şu an şöyle görünüyor:

[Unit]
Description=My Web Application
After=network.target mysql.service

[Service]
Type=simple
ExecStart=/usr/bin/myapp
User=myapp

[Install]
WantedBy=multi-user.target

Burada After=network.target yerine After=network-online.target kullanmak gereksiz yere tüm ağın hazır olmasını beklemenize neden olabilir. Eğer uygulamanız sadece lokal MySQL’e bağlanıyorsa:

[Unit]
Description=My Web Application
After=mysql.service
Wants=mysql.service

[Service]
Type=notify
ExecStart=/usr/bin/myapp
User=myapp
Restart=on-failure

[Install]
WantedBy=multi-user.target

Type=notify kullanmak, uygulamanızın systemd’ye “hazırım” sinyali göndermesini sağlar ve diğer bağımlı servisler gereksiz yere beklemez. Eğer uygulamanız sd_notify protokolünü desteklemiyorsa Type=simple kullanın ama bağımlılıkları minimize edin.

Değişiklikten sonra yeniden yükleyin ve test edin:

sudo systemctl daemon-reload
sudo systemctl restart myapp.service
systemd-analyze critical-chain myapp.service

systemd-analyze verify: Konfigürasyon Doğrulama

Servis dosyalarınızda hata olup olmadığını açılış yapmadan kontrol edebilirsiniz:

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

Bu komut yaygın hataları, eksik bağımlılıkları ve yanlış direktifleri raporlar. Özellikle yeni servis dosyaları yazdıktan sonra çalıştırma alışkanlığı edinmek, production ortamında sürprizlerin önüne geçer.

Tüm etkin servis dosyalarını toplu olarak doğrulamak için:

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

Açılış Hedeflerini Anlamak

Systemd farklı “target” seviyeleri kullanır ve her biri farklı servis setlerini aktive eder. Sunucunuzun hangi target ile açıldığını bilmek, gereksiz servislerin neden aktif olduğunu anlamanıza yardımcı olur:

systemctl get-default

Bir sunucu için genellikle graphical.target yerine multi-user.target yeterlidir:

sudo systemctl set-default multi-user.target

Bu değişiklik, X11 ve masaüstü ortamı ile ilgili tüm servislerin açılışta yüklenmesini engeller. Grafik arayüz gerektirmeyen bir sunucuda bu tek adım bile 5-10 saniyelik kazanım sağlayabilir.

Hangi target’ların aktif olduğunu görmek için:

systemctl list-units --type=target

systemd-analyze security: Güvenlik Puanlaması

systemd-analyze sadece performansla sınırlı değil. Servislerinizin güvenlik yapılandırmasını da değerlendiriyor:

systemd-analyze security nginx.service
  NAME                                                        DESCRIPTION                              EXPOSURE
✗ PrivateNetwork=                                             Service has access to the host network   0.5
✗ UserOrDynamicUser=                                         Service runs as root user                0.4
✓ NoNewPrivileges=                                           Service cannot acquire new privileges
...
Overall exposure level for nginx.service: 7.2 MEDIUM

Bu bilgi doğrudan açılış süresiyle ilgili olmasa da, servislerin sandbox ayarlarını optimize etmek hem güvenliği artırır hem de bazı durumlarda performansı iyileştirir.

Kalıcı Boot Süresi Takibi

Açılış sürelerini zaman içinde takip etmek için verileri kayıt altına almak iyi bir pratiktir. Basit bir script ile bunu otomatize edebilirsiniz:

#!/bin/bash
# /usr/local/bin/log-boot-time.sh

LOGFILE="/var/log/boot-times.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
BOOT_TIME=$(systemd-analyze | grep "Startup finished" | sed 's/Startup finished in //')

echo "$DATE - $BOOT_TIME" >> $LOGFILE

Bu scripti açılışta çalıştırmak için bir servis dosyası:

[Unit]
Description=Log Boot Time
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/log-boot-time.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
sudo chmod +x /usr/local/bin/log-boot-time.sh
sudo systemctl enable log-boot-time.service

Birkaç reboot sonrası log dosyanıza bakarak trend analizi yapabilirsiniz.

Gerçek Dünya Senaryosu 4: Mastodon/Rails Uygulaması Örneği

Büyük bir Ruby on Rails uygulaması çalıştıran bir sunucuda açılış süresi sorunuyla karşılaştığınızı düşünelim. blame çıktısında şunu gördünüz:

45.234s mastodon-web.service
43.891s mastodon-sidekiq.service

Her iki servis de birbirine bağlı değil ama sıralı başlıyor. Mevcut servis dosyasını inceleyelim:

systemctl cat mastodon-web.service

Sorun şu ki her iki servis de After=redis.service postgresql.service içeriyor ve bu servisler sırayla başlıyor. Asıl sorun Type=forking kullanılması ve fork işleminin uzun sürmesi. Bunu şu şekilde düzeltebiliriz:

[Unit]
Description=Mastodon Web Service
After=redis.service postgresql.service
Wants=redis.service postgresql.service

[Service]
Type=simple
ExecStart=/home/mastodon/live/bin/puma -C /home/mastodon/live/config/puma.rb
ExecReload=/bin/kill -SIGUSR1 $MAINPID
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Restart=always

[Install]
WantedBy=multi-user.target

Ayrıca mastodon-web ve mastodon-sidekiq servislerinin paralel başlamasını sağlamak için ortak bir bağımlılıkları varsa ve birbirlerine bağımlı değillerse, After= direktifini ona göre ayarlamak paralel başlatmayı mümkün kılar.

Systemd Journal ile Açılış Sorunlarını Debuglamak

systemd-analyze ile tespit ettiğiniz sorunları daha derinlemesine incelemek için journal’ı kullanın:

journalctl -b 0 --priority=err

Belirli bir servisin açılış sırasındaki loglarını görmek için:

journalctl -b 0 -u NetworkManager-wait-online.service

Önceki boot’ların loglarını karşılaştırmak için:

journalctl -b -1 -u mysql.service
journalctl -b 0 -u mysql.service

-b 0 en son boot’u, -b -1 bir öncekini temsil eder.

Optimizasyon Sonuçlarını Ölçmek

Yaptığınız değişikliklerin etkisini ölçmek için sistematik bir yaklaşım benimsemek gerekir. Her optimizasyon adımından sonra reboot yapıp ölçüm alın:

# Optimizasyon öncesi ölçüm
systemd-analyze > /tmp/before.txt
systemd-analyze blame >> /tmp/before.txt

# Değişiklikleri yap, reboot yap, sonra:
systemd-analyze > /tmp/after.txt
systemd-analyze blame >> /tmp/after.txt

# Karşılaştır
diff /tmp/before.txt /tmp/after.txt

Tek bir reboot ölçümüne güvenmeyin. Birkaç reboot’un ortalamasını alın çünkü disk cache, DHCP yanıt süresi gibi faktörler ölçümleri etkileyebilir.

Sık Yapılan Hatalar ve Dikkat Edilecekler

Optimizasyon yaparken bazı tuzaklara düşmemek önemli:

  • Bağımlılıkları görmezden gelmek: Bir servisi devre dışı bırakmadan önce başka hangi servislerin ona bağımlı olduğunu kontrol edin: systemctl list-dependencies --reverse servis.service
  • Production’da doğrudan denemek: Değişiklikleri önce test ortamında yapın. Bir servisi yanlışlıkla devre dışı bırakmak kritik bir sistemi çökertebilir.
  • Sadece blame listesine odaklanmak: Uzun süren bir servis mutlaka sorun değildir. Critical-chain analizi olmadan karar vermeyin.
  • Systemd’yi güncel tutmamak: Yeni sürümler performans iyileştirmeleri ve bug fix’ler içerir: apt show systemd | grep Version

Sonuç

systemd-analyze, Linux sistem yöneticilerinin araç çantasında bulunması gereken güçlü bir araç. Açılış süresini optimize etmek tek seferlik bir işlem değil, sistemin yaşam döngüsü boyunca sürdürülmesi gereken bir pratik. Yeni servis kurduğunuzda, sistem güncellemesi yaptığınızda veya yapılandırma değişikliği gerçekleştirdiğinizde systemd-analyze blame ve critical-chain çıktılarını kontrol etmek alışkanlık haline gelmelidir.

Pratik özet olarak şu adımları takip edin: önce systemd-analyze ile genel süreyi görün, blame ile en uzun süren servisleri listeleyin, critical-chain ile gerçek darboğazı tespit edin, gereksiz servisleri devre dışı bırakın, kendi servis dosyalarınızı Type ve After direktifleri açısından optimize edin ve her adımı ölçerek ilerleyin. 60 saniyenin üzerinde açılan bir sunucuyu bu yöntemlerle kolaylıkla 20 saniyenin altına çekebilirsiniz.

Küçük sistemlerde birkaç saniyelik kazanım önemsiz görünebilir ama büyük ölçekli ortamlarda veya sık reboot gerektiren senaryolarda bu fark hem operasyonel maliyet hem de kullanıcı deneyimi açısından son derece önemlidir.

Yorum yapın