journalctl ile Sistem Loglarını Okuma ve Filtreleme

Sistem yöneticiliğinin en kritik becerilerinden biri log okumaktır. Bir servis neden çöktü, bir kullanıcı sisteme ne zaman giriş yaptı, bir kernel hatası tam olarak ne zaman başladı gibi soruların cevabı logların içinde gizlidir. Systemd ile birlikte hayatımıza giren journalctl, dağınık log dosyalarını tek bir çatı altında topladı ve bu dosyaları sorgulamayı inanılmaz derecede kolaylaştırdı. Ama çoğu sysadmin hala sadece journalctl -xe yazıp geçiyor, aracın gerçek gücünü kullanmıyor. Bu yazıda journalctl’ı gerçek anlamda verimli kullanmayı konuşacağız.

journald Nedir, Loglar Nerede Saklanır?

Systemd’nin log yönetim bileşeni olan systemd-journald, sistem açılışından itibaren kernel mesajlarını, servis çıktılarını, syslog mesajlarını ve audit kayıtlarını ikili (binary) formatta depolar. Bu loglar varsayılan olarak /run/log/journal/ dizininde tutulur ve sistem yeniden başlatıldığında kaybolur. Kalıcı log tutmak istiyorsanız /var/log/journal/ dizinini oluşturmanız yeterlidir.

# Kalıcı log dizinini oluşturmak için
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

Bu işlemden sonra loglar artık yeniden başlatmalar arasında korunacak. Özellikle production ortamlarında bu adımı atlamayın, bir sunucu çöküp yeniden ayağa kalktığında neden çöktüğünü anlamaya çalışırken logların kaybolmuş olduğunu görmek gerçekten can sıkıcı bir deneyimdir.

Log dosyalarının ne kadar yer kapladığını görmek için:

journalctl --disk-usage

Bu komutu çalıştırdığınızda şöyle bir çıktı görürsünüz: Archived and active journals take up 2.3G in the file system. Disk yönetimi açısından bu rakamı düzenli kontrol etmek iyi bir alışkanlıktır.

Temel Kullanım ve Önemli Parametreler

Parametrelere geçmeden önce şunu söyleyeyim: journalctl’ın çıktısı varsayılan olarak less ile açılır, yani q ile çıkabilir, / ile arama yapabilirsiniz. Bunu bilmeden Ctrl+C ile çıkmaya çalışan çok sysadmin gördüm.

Temel parametreler şu şekilde:

  • -n [sayı]: Son N satırı gösterir, varsayılan 10’dur
  • -f: Canlı log takibi yapar (tail -f gibi)
  • -r: Logları ters sırayla gösterir, en yeni üstte
  • -e: Çıktının sonuna atlar
  • -x: Hata mesajlarına açıklama ekler
  • -u [servis]: Belirli bir servisin loglarını gösterir
  • -b: Belirli bir önyükleme döneminin loglarını gösterir
  • -k: Sadece kernel mesajlarını gösterir
  • -p: Log önceliğine göre filtreler
  • –since / –until: Zaman aralığı belirler
  • -o: Çıktı formatını belirler
  • –no-pager: Sayfalam olmadan direkt çıktı verir
# Son 50 log satırını göster
journalctl -n 50

# Canlı log takibi
journalctl -f

# En yeni logları üstte göster
journalctl -r -n 20

Servis Bazlı Log Filtreleme

Günlük işlerin büyük çoğunluğunda belirli bir servisin loglarına bakmanız gerekir. Nginx düzgün çalışmıyor mu, PostgreSQL bağlantı hatası mı veriyor, SSH servisi garip davranışlar mı gösteriyor? Hepsinde aynı pattern geçerli.

# Nginx servisinin loglarını göster
journalctl -u nginx.service

# SSH servisinin son 100 satır logu
journalctl -u sshd.service -n 100

# Canlı olarak nginx loglarını takip et
journalctl -u nginx.service -f

# Birden fazla servisin loglarını aynı anda takip et
journalctl -u nginx.service -u php-fpm.service -f

Birden fazla servisin logunu aynı anda takip etme özelliği özellikle web uygulamalarında hata ayıklarken çok işe yarıyor. Nginx’te 502 hatası alıyorsunuz ve bunun nginx mi yoksa PHP-FPM kaynaklı mı olduğunu bulmaya çalışıyorsunuz, işte tam bu noktada iki servisi aynı anda izlemek işi çözüyor.

Zaman Bazlı Filtreleme

Log analizi yapmanın en kritik boyutu zamandır. “Dün gece 23:00’de sistem yavaşladı” diye bildirim geldiğinde o zaman aralığına odaklanabilmek çok değerlidir.

# Belirli bir tarihten itibaren logları göster
journalctl --since "2024-01-15 10:00:00"

# Belirli bir tarih aralığındaki loglar
journalctl --since "2024-01-15 23:00:00" --until "2024-01-16 01:00:00"

# Görece zaman ifadeleri kullanma
journalctl --since "1 hour ago"
journalctl --since "yesterday"
journalctl --since "today"

# Servis + zaman kombinasyonu
journalctl -u postgresql.service --since "2 hours ago" --until "1 hour ago"

Görece zaman ifadeleri pratikte çok kullanışlı. “Son 2 saatte ne oldu” diye bakarken --since "2 hours ago" yazmak, tarih hesaplamak zorunda kalmaktan çok daha pratik.

Boot Bazlı Log Filtreleme

Sunucunuzun yeniden başlatılmasından önceki logları incelemek istediğinizde boot filtreleme devreye giriyor. Kalıcı log tutuyorsanız bu özellik altın değerinde.

# Mevcut önyükleme döneminin logları
journalctl -b

# Bir önceki önyüklemenin logları
journalctl -b -1

# İki önyükleme öncesinin logları
journalctl -b -2

# Tüm önyükleme dönemlerini listele
journalctl --list-boots

--list-boots çıktısı şuna benzer bir şey verir:

-3 abc123def456 Mon 2024-01-13 08:00:00 UTC--Mon 2024-01-13 18:30:00 UTC
-2 def456abc789 Tue 2024-01-14 09:00:00 UTC--Tue 2024-01-14 23:00:00 UTC
-1 789abc123def Wed 2024-01-15 10:00:00 UTC--Wed 2024-01-15 22:45:00 UTC
 0 123def456abc Thu 2024-01-16 08:30:00 UTC--present

“Sunucu neden yeniden başlatıldı?” sorusunun cevabını aramak için bu listeyi kullanabilirsiniz. Daha sonra o boot ID’sini kullanarak spesifik önyüklemenin loglarına bakabilirsiniz.

Log Önceliğine Göre Filtreleme

Syslog severity seviyelerini biliyorsunuzdur. journalctl bunları tam destekliyor ve sadece hataları veya kritik mesajları süzgeçlemek için oldukça kullanışlı.

Öncelik seviyeleri düşükten yükseğe doğru şu şekilde sıralanır:

  • 0 – emerg: Sistem kullanılamaz
  • 1 – alert: Acil müdahale gerekiyor
  • 2 – crit: Kritik durumlar
  • 3 – err: Hata durumları
  • 4 – warning: Uyarı mesajları
  • 5 – notice: Normal ama önemli mesajlar
  • 6 – info: Bilgi mesajları
  • 7 – debug: Debug mesajları
# Sadece hata ve üzeri mesajları göster
journalctl -p err

# Warning ve üzeri mesajlar
journalctl -p warning

# Belirli bir aralıktaki öncelikler (warning'den err'e kadar)
journalctl -p warning..err

# Servis + öncelik kombinasyonu
journalctl -u nginx.service -p err --since "today"

Özellikle sabah işe geldiğinizde journalctl -p err --since "yesterday" ile gece ne gibi hatalar oluştuğuna bakmak güzel bir alışkanlık. Büyük sistemlerde bunu otomatik raporlamaya dahil etmek mantıklı.

Çıktı Formatları ve Grep ile Birlikte Kullanım

journalctl’ın farklı çıktı formatları var ve bunları ne zaman kullanacağını bilmek işleri kolaylaştırıyor.

# JSON formatında çıktı (log analiz araçlarıyla entegrasyon için)
journalctl -u nginx.service -o json

# Her satır bir JSON objesi (pipe ile kullanım için ideal)
journalctl -u nginx.service -o json-pretty

# Kısa format (tarih kısmı kısaltılmış)
journalctl -o short

# Verbose format (tüm metadata)
journalctl -o verbose

# Mesaj ve timestamp içeren sade format
journalctl -o cat

grep ile kombinasyon yaparken --no-pager kullanmayı unutmayın:

# Belirli bir IP adresini arayın
journalctl -u nginx.service --no-pager | grep "192.168.1.100"

# Hata mesajlarında belirli bir keyword arama
journalctl -p err --no-pager --since "today" | grep -i "database"

# JSON çıktısını jq ile işleme
journalctl -u sshd.service -o json --no-pager | jq '.MESSAGE' | head -20

jq ile JSON çıktısını işlemek özellikle log analizi scriptleri yazarken çok işe yarıyor. Belirli field’ları çekip istatistik çıkarmak, anomali tespiti yapmak gibi işler için JSON format ideal.

Gerçek Dünya Senaryo 1: Servis Çöküş Analizi

Sabah işe geldiniz, bir microservis gece defalarca çökmüş ve yeniden başlamış. Ne yaparsınız?

# Önce servisin son durumuna bakın
systemctl status uygulama.service

# Sonra son önyüklemeden itibaren servis loglarını inceleyin
journalctl -u uygulama.service -b

# Sadece hataları filtrele
journalctl -u uygulama.service -p err -b

# Servisin kaç kez yeniden başladığını anlamak için
journalctl -u uygulama.service -b | grep -i "started|stopped|failed"

# Çöküş anındaki tam context için zaman bazlı inceleme
journalctl -u uygulama.service --since "2024-01-16 02:00:00" --until "2024-01-16 03:00:00"

Bu senaryo özelinde journal metadata field’larını da kullanabilirsiniz. Systemd her log girişine servisin PID’ini, UID’ini, GID’ini ve daha fazlasını ekler. Bunları filtrelemede kullanmak mümkün.

Gerçek Dünya Senaryo 2: SSH Brute Force Tespiti

Güvenlik olaylarında journalctl’ı etkin kullanmak hayat kurtarıyor. Bir sunucuda şüpheli SSH aktivitesi var mı diye bakalım.

# Başarısız SSH giriş denemelerini listele
journalctl -u sshd.service --no-pager | grep "Failed password"

# Son 24 saatteki başarısız girişleri say
journalctl -u sshd.service --since "yesterday" --no-pager | grep "Failed password" | wc -l

# Hangi IP adreslerinden deneme gelmiş
journalctl -u sshd.service --since "yesterday" --no-pager | grep "Failed password" | awk '{print $11}' | sort | uniq -c | sort -rn | head -20

# Başarılı SSH girişlerini de kontrol et
journalctl -u sshd.service --since "yesterday" --no-pager | grep "Accepted"

Bu tür analizleri düzenli yapıyorsanız fail2ban ya da benzeri araçlarla entegre etmeyi düşünün. Ama hızlı bir durumsal farkındalık için journalctl + grep + awk kombinasyonu çok güçlü.

Gerçek Dünya Senaryo 3: Disk ve Kernel Sorunları

Kernel seviyesindeki sorunlara, disk hatalarına veya donanım uyarılarına bakmak için:

# Sadece kernel mesajları
journalctl -k

# Kernel mesajlarında disk hataları ara
journalctl -k --no-pager | grep -i "error|fail|warn" | grep -i "sda|nvme|disk"

# Bu önyüklemede kernel mesajları
journalctl -k -b

# OOM (Out of Memory) killer olayları
journalctl -k --no-pager | grep -i "oom|out of memory|killed process"

# Hardware error mesajları
journalctl -k -p err --since "1 week ago" --no-pager

OOM killer olayları özellikle memory leak olan uygulamaları tespit etmede çok değerli. Hangi process öldürüldü, ne zaman, hangi memory kullanımıyla; bunların hepsi kernel loglarında yazıyor.

Alan (Field) Bazlı Filtreleme

journald her log girişini bir dizi field ile saklar ve bu field’lara göre filtreleme yapabilirsiniz. Bu biraz daha ileri düzey ama gerçekten güçlü bir özellik.

# Belirli bir PID'in loglarını görüntüle
journalctl _PID=1234

# Belirli bir kullanıcının oluşturduğu loglar
journalctl _UID=1000

# Belirli bir executable'ın logları
journalctl _EXE=/usr/sbin/sshd

# Birden fazla field ile filtreleme (AND mantığı)
journalctl _SYSTEMD_UNIT=nginx.service _PID=5678

# Kullanılabilir field'ları listele
journalctl -o verbose | head -50

Bu field’ları öğrenmenin en iyi yolu journalctl -o verbose ile bir log girişinin tam yapısını incelemek. Her girişte onlarca metadata field var ve bunların hepsine göre filtreleme yapabilirsiniz.

Log Boyutu Yönetimi

Production ortamlarında journal boyutunu kontrol altında tutmak önemli. /etc/systemd/journald.conf dosyası bu ayarları barındırıyor.

Önemli konfigürasyon parametreleri:

  • SystemMaxUse: Kalıcı logların maksimum disk kullanımı
  • SystemKeepFree: Disk üzerinde boş bırakılacak minimum alan
  • RuntimeMaxUse: /run altındaki geçici logların maksimum boyutu
  • MaxRetentionSec: Logların maksimum saklama süresi
  • MaxFileSec: Tek bir log dosyasının maksimum boyutu
# Mevcut disk kullanımını kontrol et
journalctl --disk-usage

# Belirli bir süre öncesindeki logları temizle
sudo journalctl --vacuum-time=2weeks

# Belirli bir boyutun üzerindeki logları temizle
sudo journalctl --vacuum-size=1G

# Belirli sayıda boot geçmişi dışındakileri temizle
sudo journalctl --vacuum-files=5

--vacuum-time=2weeks parametresi özellikle düzenli olarak çalıştırmak üzere bir cron job’a ya da systemd timer’a eklenebilir. 2 haftadan eski logları tutmak çoğu senaryoda mantıklı bir denge noktası.

Cursor Kullanımı ve İleri Düzey Sorgular

Büyük log kümelerinde belirli bir noktadan devam etmek ya da log akışını programatik olarak işlemek istediğinizde cursor mekanizması devreye giriyor.

# Son log girişinin cursor'ını göster
journalctl -n 1 -o export | grep __CURSOR

# Belirli bir cursor'dan itibaren logları oku
journalctl --after-cursor="s=abc123..."

# Cursor'ı kaydet ve sonra devam et (script'lerde kullanışlı)
CURSOR=$(journalctl -n 1 -o export | grep ^__CURSOR | cut -d= -f2-)
# ... bir süre bekle ...
journalctl --after-cursor="$CURSOR" --no-pager

Bu özellik özellikle log collector scriptleri yazarken işe yarıyor. İşlediğiniz son log girişinin cursor’ını bir dosyaya kaydedip, script her çalıştığında kaldığı yerden devam edebilirsiniz. Elasticsearch ya da başka bir log yönetim sistemine log gönderiyor ve duplicate girişlerden kaçınmak istiyorsanız bu mekanizma tam aradığınız şey.

journalctl Çıktısını Diğer Araçlarla Entegre Etme

Gerçek dünya ortamlarında journalctl tek başına yeterli olmayabiliyor. Merkezi log yönetimi, görselleştirme ya da alerting için başka araçlarla entegrasyon gerekiyor.

# Logları syslog formatında başka bir sisteme gönder
journalctl -f -o json | nc logserver.internal 5140

# Belirli bir zaman aralığındaki logları dosyaya export et
journalctl --since "2024-01-15" --until "2024-01-16" -o json > /tmp/gunluk_loglar.json

# systemd-cat ile kendi script'inizin çıktısını journal'a yazın
echo "Yedekleme tamamlandi" | systemd-cat -t backup-script -p info

# Script içinden journal'a log yaz
systemd-cat -t "myapp" -p err echo "Kritik hata olustu"

systemd-cat özellikle custom script’lerinizin çıktılarını merkezi log sistemine dahil etmek için harika. Artık script log dosyaları ayrı yerlerde dağılıp durmak yerine tüm sistem loglarıyla birlikte journald’da toplanıyor.

Performans İpuçları

Büyük log dosyalarında yavaş çalışan sorgular can sıkıcı olabiliyor. Birkaç pratik ipucu:

  • --no-pager kullanımı pipe işlemlerinde gereksiz buffer’lamayı önler
  • Zaman aralığı belirlemek büyük log kümelerinde sorgu hızını dramatik artırır
  • _SYSTEMD_UNIT gibi indexed field’lara göre filtreleme, grep ile metin aramasından çok daha hızlıdır
  • journalctl -q ile informational mesajları bastırıp sadece gerçek içeriğe odaklanabilirsiniz
# Hızlı ve verimli sorgu örneği
journalctl _SYSTEMD_UNIT=nginx.service --since "1 hour ago" -p err --no-pager -q

# Yavaş olan (büyük veri setlerinde kaçının)
journalctl --no-pager | grep nginx | grep error

İkinci yaklaşım tüm journal içeriğini okuyup pipe’layarak grep’e veriyor, bu büyük log dosyalarında ciddi yavaşlık yaratır. Her zaman journalctl’ın kendi filtreleme mekanizmalarını tercih edin.

Sonuç

journalctl, düzgün kullanıldığında sistem yönetiminin en güçlü araçlarından biri haline geliyor. Temel journalctl -xe kullanımından zaman bazlı filtrelemeye, boot analizi’nden field bazlı sorgulara kadar her seviyede farklı yetenekler sunuyor.

Pratikte en çok işe yarayan workflow şu şekilde: Önce systemctl status ile genel duruma bakın, sonra -u ile ilgili servisin loglarına odaklanın, -p err ile gürültüyü azaltın ve --since ile zaman aralığı belirleyerek ilgili kısma yakınlaşın. Bu dört adım problem tespitinin büyük çoğunluğunu karşılıyor.

Kalıcı log tutmayı mutlaka aktif edin, log boyutunu yönetin ve kritik sistemler için düzenli hata raporu almayı alışkanlık haline getirin. journalctl’ı bir araç olarak değil, sistem sağlığını sürekli takip ettiğiniz bir pencere olarak düşünün. Logları reaktif değil proaktif okuduğunuzda, sorunları kullanıcılardan önce siz fark edersiniz.

Yorum yapın