Sistem yönetimi dünyasında “makine neden farklı bir modda açıldı?” ya da “bu servis neden boot sırasında başlamıyor?” gibi sorularla karşılaşmayan sysadmin yok gibidir. Systemd’nin hedef (target) sistemi, tam da bu soruların cevabını barındıran yerdir. Eski SysVinit döneminin runlevel kavramını hem daha esnek hem de daha okunabilir bir yapıya taşıyan bu sistem, günümüz Linux dağıtımlarının temel taşlarından biri haline gelmiştir.
Runlevel’dan Target’a: Kavramsal Dönüşüm
Eski günlerde /etc/inittab dosyasını açıp runlevel değiştirmek zorunda kaldığınızı hatırlıyorsanız, systemd targets size tanıdık ama çok daha güçlü bir yapı sunuyor. Runlevel’lar 0’dan 6’ya kadar numaralandırılmış sabit çalışma modlarıydı. Systemd ile bu anlayış tamamen değişti.
Target’lar, belirli bir sistem durumuna ulaşmak için gereken servislerin, mount noktalarının ve diğer unit’lerin gruplandığı mantıksal koleksiyonlardır. Bir target aktifleştirildiğinde, ona bağımlı olan tüm unit’ler sırayla devreye girer.
Runlevel ile target arasındaki eşleşmeye bakacak olursak:
- Runlevel 0 karşılığı:
poweroff.target - Runlevel 1 karşılığı:
rescue.target - Runlevel 2, 3, 4 karşılığı:
multi-user.target - Runlevel 5 karşılığı:
graphical.target - Runlevel 6 karşılığı:
reboot.target
Bu eşleştirme sadece geriye dönük uyumluluk için değil, aynı zamanda zihinsel modeli oturtmak için de faydalıdır.
Temel Target’ları Tanımak
Systemd ile birlikte gelen önemli target’ları iyi anlamak, sorun giderme ve sistem yapılandırma süreçlerinde hayat kurtarır.
poweroff.target: Sistemi kapatır. Tüm servisleri durdurur, dosya sistemlerini unmount eder.
rescue.target: Tek kullanıcılı kurtarma modu. Ağ servisleri çalışmaz, sadece root erişimi mevcut olur. Sistem kurtarma işlemlerinde kullanılır.
emergency.target: Rescue’dan bile daha minimalist. Sadece root dosya sistemi read-only olarak mount edilir. Ciddi sistem problemlerinde kullanılır.
sysinit.target: Temel sistem başlatma işlemleri burada tamamlanır. Swap alanının aktifleştirilmesi, dosya sistemlerinin kontrol edilmesi gibi görevler bu aşamada yapılır.
basic.target: Temel servisler devrede. Socket’ler, timer’lar ve benzeri temel bileşenler hazır.
multi-user.target: Çok kullanıcılı metin tabanlı çalışma modu. Sunucularda genellikle varsayılan hedef budur.
graphical.target: Grafik arayüz dahil tam çalışma modu. Desktop ortamları için kullanılır.
network.target: Ağ yapılandırmasının tamamlandığını işaret eden target. Ağa bağımlı servisler genellikle bu target’ın ardından başlar.
network-online.target: Ağın fiziksel olarak hazır olmasının ötesinde, gerçekten çevrimiçi olduğunu garanti eden target. Bu iki target arasındaki farkı karıştırmak ciddi servis başlatma sorunlarına yol açabilir.
Mevcut Target Durumunu İnceleme
Önce sistemin mevcut durumuna bakalım. Hangi target aktif, hangileri yüklü?
# Aktif olan target'ı görmek için
systemctl get-default
# Tüm aktif unit'leri listele
systemctl list-units --type=target
# Tüm target'ları (aktif ve inaktif) listele
systemctl list-units --type=target --all
# Belirli bir target hakkında detaylı bilgi
systemctl status multi-user.target
systemctl list-units --type=target komutunun çıktısı size hem aktif hem de başarısız durumları gösterir. Bir target’ın “active” durumda olması, ona bağlı tüm zorunlu unit’lerin başarıyla başladığı anlamına gelir.
# Target bağımlılık ağacını görmek için
systemctl list-dependencies graphical.target
# Tersine bağımlılık: hangi unit'ler bu target'a bağımlı?
systemctl list-dependencies graphical.target --reverse
Bu komutların çıktısı, sistem boot sürecini anlamak için gerçekten değerli. graphical.target‘a baktığınızda, onun multi-user.target‘a, onun da basic.target‘a bağımlı olduğunu görürsünüz. Hiyerarşik yapı son derece nettir.
Varsayılan Boot Target’ını Değiştirme
Bu en sık kullanılan target yönetimi işlemlerinden biridir. Bir sunucuya grafik arayüz kurulmuş ama server olarak kullanılıyorsa, gereksiz yere grafik servisleri ayağa kaldırmak kaynak israfıdır.
# Mevcut varsayılan target'ı kontrol et
systemctl get-default
# Varsayılanı multi-user olarak değiştir (sunucular için ideal)
sudo systemctl set-default multi-user.target
# Grafik arayüze geri dönmek için
sudo systemctl set-default graphical.target
# Değişikliği doğrula
systemctl get-default
set-default komutu aslında arka planda /etc/systemd/system/default.target adında bir symlink oluşturur ya da günceller. Bunu doğrudan inceleyebilirsiniz:
ls -la /etc/systemd/system/default.target
# Çıktı örneği:
# /etc/systemd/system/default.target -> /lib/systemd/system/multi-user.target
Bu symlink mekanizması systemd’nin genel felsefesiyle uyumludur: her şey dosya sistemi üzerinden izlenebilir ve değiştirilebilir olmalıdır.
Çalışma Anında Target Değiştirme
Sistemi yeniden başlatmadan target değiştirmek mümkün. Bu özellikle test senaryolarında veya acil durumda son derece kullanışlıdır.
# Hemen multi-user moduna geç (grafik oturumları kapanır)
sudo systemctl isolate multi-user.target
# Rescue moduna geç (dikkatli kullanın, servisler durur)
sudo systemctl isolate rescue.target
# Grafik moduna geri dön
sudo systemctl isolate graphical.target
Önemli uyarı: isolate komutu hedef target’ın AllowIsolate=yes parametresine sahip olmasını gerektirir. Her target izole edilemez. Örneğin network.target‘ı izole etmeye çalışırsanız hata alırsınız. Bu güvenlik mekanizması, yanlışlıkla sistemi kilitleyebilecek işlemlerin önüne geçer.
Hangi target’ların izole edilebildiğini şöyle kontrol edebilirsiniz:
# Target'ın unit dosyasını inceleyerek AllowIsolate değerini gör
systemctl cat rescue.target
Özel Target Oluşturma: Gerçek Dünya Senaryosu
İşte burada systemd’nin gerçek gücü ortaya çıkıyor. Kendi özel target’larınızı oluşturabilirsiniz. Bunu ne zaman yaparsınız?
Senaryo: Bir üretim ortamında “maintenance mode” diye adlandırdığınız özel bir mod istiyorsunuz. Bu modda veritabanı ve web sunucusu çalışmamalı ama SSH erişimi ve monitoring agent devrede olmalı. Tam olarak böyle bir target oluşturalım.
# Önce target dosyasını oluşturalım
sudo nano /etc/systemd/system/maintenance.target
Dosyanın içeriği:
[Unit]
Description=Bakim Modu
Documentation=man:systemd.special(7)
Requires=sysinit.target
After=sysinit.target
AllowIsolate=yes
Şimdi bu target aktifleştirildiğinde çalışmasını istediğimiz servislerin bu target’ı “isteyen” (wanted by) yapılandırmasını ekleyelim:
# SSH servisinin maintenance modunda da çalışmasını sağla
sudo mkdir -p /etc/systemd/system/maintenance.target.wants
sudo ln -sf /lib/systemd/system/ssh.service
/etc/systemd/system/maintenance.target.wants/ssh.service
# Systemd'ye yeni yapılandırmayı bildir
sudo systemctl daemon-reload
# Bakım moduna geç
sudo systemctl isolate maintenance.target
# Durumu kontrol et
systemctl status
Bu senaryo, özellikle otomatik deployment pipeline’larında son derece kullanışlıdır. Deploy sırasında bakım moduna geçip, işlem tamamlandıktan sonra normal moda dönebilirsiniz.
Boot Sürecinde Target Geçici Olarak Değiştirme
Bazen sistemi kalıcı olarak değiştirmek değil, sadece bir kez farklı bir target ile başlatmak istersiniz. Bu özellikle sorun giderme senaryolarında çok değerlidir.
GRUB ekranında boot parametrelerine erişip şu şekilde geçici target belirtebilirsiniz:
Kernel parametrelerine systemd.unit=rescue.target eklemek yeterlidir. Örneğin emergency mode için:
systemd.unit=emergency.target
Ya da doğrudan rescue:
systemd.unit=rescue.target
Bu değişiklik sadece o boot için geçerlidir. Bir sonraki açılışta sistem yine varsayılan target’ı kullanır.
Komut satırından da bir sonraki boot için target belirtebilirsiniz:
# Bir sonraki boot için rescue modunu ayarla
sudo systemctl rescue
# Ya da emergency modunu
sudo systemctl emergency
Ancak dikkat: bu komutlar sistemi hemen o moda almaya çalışır, sadece bir sonraki boot için değil. Emergency ve rescue komutları mevcut oturumu etkiler.
Target Unit Dosyası Anatomisi
Bir target unit dosyasının yapısını daha derinden anlayalım. multi-user.target dosyasına bakalım:
# Sistem target dosyasını görüntüle
systemctl cat multi-user.target
Tipik bir target unit dosyası şu bölümleri içerir:
[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yes
Bu direktiflerin anlamları:
- Description: Target’ın okunabilir açıklaması
- Requires: Bu target çalışmadan önce mutlaka aktif olması gereken unit’ler. Eğer bu unit başlamazsa, target da başlamaz.
- Wants: Requires’a benzer ama daha gevşek. İlgili unit başlamazsa target yine de devam eder.
- After: Sıralama direktifi. Bu target, listelenen unit’lerden sonra başlar.
- Conflicts: Bu target aktifken çalışmaması gereken unit’ler.
- AllowIsolate: Bu target’ın
systemctl isolateile kullanılıp kullanılamayacağı.
Requires ile Wants arasındaki fark sysadmin’lerin sık karıştırdığı bir konudur. Kendi servisinizi bir target’a eklerken hangisini kullanacağınızı düşünmek gerekir. Kritik bir servis için Requires, opsiyonel bir servis için Wants kullanın.
Servis ile Target İlişkisi Kurma
Kendi yazdığınız ya da kurduğunuz bir servisi belirli bir target’a bağlamak için servis unit dosyasında [Install] bölümünü doğru yapılandırmanız gerekir.
# Örnek servis dosyası
sudo nano /etc/systemd/system/myapp.service
[Unit]
Description=My Application Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/myapp
Restart=on-failure
User=myapp
[Install]
WantedBy=multi-user.target
WantedBy=multi-user.target direktifi, systemctl enable myapp.service komutunu çalıştırdığınızda /etc/systemd/system/multi-user.target.wants/ dizininde symlink oluşturulmasını sağlar. Bu symlink mekanizması sayesinde target aktifleştiğinde servis otomatik olarak başlatılır.
# Servisi etkinleştir ve hemen başlat
sudo systemctl enable --now myapp.service
# Symlink'in oluşturulduğunu doğrula
ls -la /etc/systemd/system/multi-user.target.wants/myapp.service
Sorun Giderme: Boot Sürecinde Target Analizi
Target yönetiminin en kritik kullanım alanlarından biri boot sorunlarını tespit etmektir. Sistem beklenenden daha yavaş açılıyorsa ya da bir target’a ulaşamıyorsa şu araçları kullanın:
# Boot sürecinin zaman analizini görüntüle
systemd-analyze
# Her unit'in boot süresini göster
systemd-analyze blame
# Kritik path'i görüntüle (en uzun süren zincir)
systemd-analyze critical-chain
# Belirli bir target'ın kritik path'ini incele
systemd-analyze critical-chain multi-user.target
# Görsel SVG çıktısı oluştur (browser ile açılabilir)
systemd-analyze plot > boot-analysis.svg
systemd-analyze critical-chain multi-user.target komutu size şuna benzer bir çıktı verir:
multi-user.target @15.234s
└─myapp.service @14.891s +0.342s
└─network-online.target @14.543s
└─NetworkManager-wait-online.service @5.123s +9.420s
└─NetworkManager.service @4.987s +0.135s
└─network.target @4.956s
Bu çıktıdan NetworkManager-wait-online.service‘in boot süresinin büyük bölümünü tükettiğini görebilirsiniz. Eğer servisiniz gerçekten tam ağ bağlantısına ihtiyaç duymuyorsa, network-online.target yerine network.target kullanmayı düşünebilirsiniz.
Gerçek Dünya Senaryosu: Sunucu Kurtarma
Hafta sonunda gelen bir çağrı: üretim sunucusu boot sırasında takılıyor. SSH erişimi yok. Ne yaparsınız?
GRUB ekranına erişip kernel parametrelerine systemd.unit=emergency.target ekleyerek sistemi emergency mode’da başlatın. Bu mod çok minimal: root filesystem read-only mount edilmiş, neredeyse hiçbir servis yok.
# Emergency modda root filesystem'i read-write olarak yeniden mount et
mount -o remount,rw /
# Journalctl ile son hataları incele
journalctl -xb
# Hangi servis sorun çıkarıyor?
systemctl list-units --failed
# Sorunlu servisi devre dışı bırak
systemctl disable problemservis.service
# Normal boot için target'ı ayarla ve yeniden başlat
systemctl set-default multi-user.target
reboot
Bu prosedür, systemd’nin target hiyerarşisini ne kadar pratik bir kurtarma mekanizmasına dönüştürdüğünü gösteriyor.
Target Maskeleme ve Engelleme
Bazen bir target’ın kesinlikle aktifleştirilmemesini isteyebilirsiniz. mask komutu tam da bu iş için:
# Bir target'ı maskele (başlatılmasını tamamen engelle)
sudo systemctl mask graphical.target
# Maskelemeyi kaldır
sudo systemctl unmask graphical.target
# Maskelenen unit'leri listele
systemctl list-units --type=target --all | grep masked
Maskeleme, /dev/null‘a symlink oluşturarak çalışır. Böylece herhangi bir bağımlılık zinciri bu target’ı aktifleştirmeye çalışsa bile başarısız olur. Bu, özellikle güvenlik açısından hassas ortamlarda grafik arayüzün veya gereksiz servislerin kesinlikle çalışmamasını garantilemek için kullanılır.
Target’ların Systemd Slice ve Scope ile İlişkisi
İleri düzey kullanımda target’lar, systemd’nin kaynak yönetimi mekanizmaları olan slice’lar ile birlikte kullanılabilir. Örneğin özel bir target altındaki servislerin CPU ve memory kullanımını sınırlamak isteyebilirsiniz:
# Bir target'ın kaynak kullanımını sorgula
systemctl show multi-user.target -p MemoryCurrent,CPUUsageNSec
# Belirli bir target kapsamında servis başlatma
systemd-run --unit=testjob --slice=test.slice /usr/bin/testscript
Bu konu başlı başına bir yazı konusu olsa da, target’ların sadece servis gruplama değil, kaynak yönetimi planlamasında da temel referans noktası olduğunu bilmek önemlidir.
İyi Uygulamalar ve Kaçınılması Gereken Hatalar
Gerçek dünya deneyiminden gelen birkaç önemli nokta:
/lib/systemd/system/dizinini düzenleme: Sistem tarafından sağlanan dosyalar bu dizindedir. Her zaman/etc/systemd/system/altında override oluşturun. Paket güncellemeleri/libaltındaki dosyaları değiştirebilir ama/etcaltındakiler korunur.
network.targetilenetwork-online.targetkarışıklığı: Ağa gerçekten ihtiyaç duyan servislernetwork-online.targetkullanmalı. Ancak bu target bazen boot süresini önemli ölçüde uzatır. Servisinizin gerçekten tam ağ bağlantısına ihtiyacı olup olmadığını değerlendirin.
daemon-reloadunutmak: Her target veya servis dosyası değişikliğinden sonrasystemctl daemon-reloadçalıştırmayı alışkanlık haline getirin. Aksi halde systemd eski yapılandırmayı kullanmaya devam eder.
isolatekomutunu dikkatli kullanmak: Özellikle uzak bağlantı üzerinden çalışırkenrescue.targetveyaemergency.target‘a isolate yapmak SSH bağlantınızı kesebilir.
- Target bağımlılıklarını belgelemek: Özel target’lar oluşturduğunuzda bağımlılık ilişkilerini mutlaka belgeleyin. Birkaç ay sonra o target’ı neden oluşturduğunuzu hatırlamak istemezsiniz.
# Yapılandırma doğrulama - yazmadan önce kontrol edin
systemd-analyze verify /etc/systemd/system/maintenance.target
# Herhangi bir unit dosyasındaki syntax hatalarını bul
systemd-analyze verify /etc/systemd/system/myapp.service
systemd-analyze verify komutu canlı sisteme etki etmeden unit dosyalarınızdaki sorunları tespit eder. Production ortamında değişiklik yapmadan önce bu komutu çalıştırmak iyi bir pratiktir.
Sonuç
Systemd target yönetimi, ilk bakışta karmaşık görünse de altında son derece mantıklı ve tutarlı bir felsefe yatıyor. Runlevel kavramını tanıyorsanız geçiş zaten kolaydır, tanımıyorsanız da sıfırdan öğrenmek için target sistemi çok daha sezgisel bir başlangıç noktası sunuyor.
Günlük sysadmin işlerinde en çok kullanacağınız komutlar systemctl get-default, systemctl set-default ve systemd-analyze ailesinden gelecek. Sorun giderme senaryolarında ise emergency ve rescue target’larını nasıl kullanacağınızı bilmek, saatler sürebilecek çökme analizlerini dakikalara indirebilir.
Özel target oluşturma konusuna başlangıçta ihtiyaç duymayabilirsiniz ama karmaşıklaşan ortamlarda deployment, bakım ve test modları için kendi target’larınızı tasarlamak sisteminizi çok daha yönetilebilir kılar. Symlink tabanlı wants mekanizmasını anladıktan sonra, “bu servis neden başlamıyor?” sorusunun cevabını her zaman doğru yerde arayacaksınız: /etc/systemd/system/*.target.wants/ dizinlerinde.
Son olarak şunu söyleyelim: systemd hakkında tartışmalar Linux topluluğunda hiç bitmez, ama target sistemi tartışmanın en az kısmını alan ve en çok değer katan bileşenlerden biridir. Bunu iyi öğrenmek, hem sorun giderme hızınızı hem de sistem tasarımı kalitenizi doğrudan etkiler.