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.