Ubuntu’da Log Yönetimi: journalctl ve /var/log Kullanım Rehberi

Sunucunuzda bir şeyler ters gittiğinde, ilk içgüdünüz ne olur? Büyük ihtimalle logları açarsınız. Log yönetimi, bir sistem yöneticisinin en temel becerilerinden biridir ve Ubuntu’da bu işi iki ana araçla yaparsınız: modern systemd ekosisteminin bir parçası olan journalctl ve klasik metin tabanlı log dosyalarının yaşadığı /var/log dizini. Bu iki dünya bazen örtüşür, bazen ayrı çalışır, ama ikisini birlikte iyi anladığınızda sorun giderme süreçleriniz dramatik biçimde kısalır.

Loglar Neden Bu Kadar Önemli?

Bir production sunucusunda gece 2’de alarm geldiğini düşünün. Servis çökmüş, kullanıcılar bağlanamıyor. Elinizde log yoksa karanlıkta el yordamıyla çalışırsınız. Elinizde log var ama nasıl okuyacağınızı bilmiyorsanız, yine aynı sonuç. Log yönetimi sadece “dosyaları açıp bakmak” değildir; doğru araçlarla doğru sorguyu yazmak, geçmişe dönük olayları zaman damgasıyla takip etmek ve sistemin davranışını anlamlandırmaktır.

Ubuntu’da iki katmanlı bir log altyapısı vardır. systemd-journald, sistem açılışından itibaren tüm servislerin, kernel mesajlarının ve sistem olaylarının binary formatta tuttuğu bir veritabanı gibi çalışır. /var/log altındaki klasik log dosyaları ise hem eski araçların hem de bazı uygulamaların doğrudan yazdığı metin dosyalarıdır. İkisini de bilmeniz gerekir.

systemd Journal ve journalctl

Journal Nerede Saklanır?

Varsayılan Ubuntu kurulumunda journal logları /run/log/journal/ altında geçici olarak tutulur. Bu, sunucu yeniden başladığında logların kaybolduğu anlamına gelir. Eğer kalıcı log istiyorsanız:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

Bu işlemin ardından loglar /var/log/journal/ altında makine ID’sine göre organize edilmiş binary dosyalarda saklanır. journalctl --disk-usage komutuyla ne kadar yer kapladığını görebilirsiniz:

journalctl --disk-usage
# Archived and active journals take up 1.2G in the file system.

Temel journalctl Kullanımı

journalctl komutunu parametresiz çalıştırdığınızda tüm journal geçmişini görürsünüz, ama bu genellikle işe yaramaz çünkü binlerce satır karşınıza çıkar. Gerçek hayatta her zaman filtre kullanırsınız.

En sık kullandığım temel parametreler:

  • -f: Gerçek zamanlı log akışı (tail -f gibi)
  • -n [sayı]: Son N satırı gösterir
  • -u [servis]: Belirli bir servisin loglarını filtreler
  • -b: Sadece son boot’tan bu yana olan logları gösterir
  • -p [öncelik]: Log seviyesine göre filtreler (0-7 arası)
  • –since / –until: Zaman aralığına göre filtreler
  • -r: Ters sıralama (en yeni önce)
  • -e: Log sonuna atlar
  • –no-pager: Çıktıyı doğrudan terminale yazdırır, pipe için kullanışlı

Gerçek zamanlı bir servisin logunu izlemek için:

# Nginx loglarını gerçek zamanlı izle
sudo journalctl -u nginx -f

# Son 50 satırı göster ve takip et
sudo journalctl -u postgresql -n 50 -f

# Son boot'tan nginx logları
sudo journalctl -u nginx -b

Zaman Bazlı Filtreleme

Bir incident yaşandığında “dün gece 23:00 ile 01:00 arası ne oldu?” sorusunun cevabını bulmak için zaman filtresi hayat kurtarır:

# Belirli zaman aralığı
sudo journalctl --since "2024-01-15 22:00:00" --until "2024-01-16 02:00:00"

# Daha okunabilir format
sudo journalctl --since "yesterday" --until "today"
sudo journalctl --since "2 hours ago"
sudo journalctl --since "1 hour ago" -u nginx

# Son 30 dakika
sudo journalctl --since "30 min ago" -p err

Bu zaman ifadeleri son derece esnektir. “yesterday”, “today”, “now”, “1 hour ago”, “2 days ago” gibi insan okunabilir ifadelerin yanı sıra tam tarih-saat formatını da kabul eder.

Öncelik Seviyeleri ile Filtreleme

Log seviyeleri syslog standardını takip eder:

  • 0 (emerg): Sistem kullanılamaz
  • 1 (alert): Hemen müdahale gerekli
  • 2 (crit): Kritik durum
  • 3 (err): Hata
  • 4 (warning): Uyarı
  • 5 (notice): Normal ama önemli
  • 6 (info): Bilgilendirme
  • 7 (debug): Debug mesajları

Sadece hata ve üstünü görmek için:

# Hata seviyesi ve üstü (0-3 arası)
sudo journalctl -p err

# Sadece kritik ve üstü
sudo journalctl -p crit

# Son boot'tan hata ve üstü, son 100 satır
sudo journalctl -b -p err -n 100

# Belirli serviste warning ve üstü
sudo journalctl -u mysql -p warning --since "1 hour ago"

Birden Fazla Boot Arasında Gezinme

Sunucunuz birden fazla kez yeniden başladıysa ve kalıcı logging etkinleştirdiyseniz, önceki boot’ların loglarına da ulaşabilirsiniz:

# Tüm boot'ları listele
sudo journalctl --list-boots

# Çıktı şöyle görünür:
# -2 abc123... Mon 2024-01-13 10:00:00 UTC--Mon 2024-01-13 18:00:00 UTC
# -1 def456... Tue 2024-01-14 09:00:00 UTC--Tue 2024-01-14 23:59:00 UTC
#  0 ghi789... Wed 2024-01-15 08:00:00 UTC--Wed 2024-01-15 12:00:00 UTC

# Bir önceki boot logları
sudo journalctl -b -1

# İki boot öncesi sadece hata logları
sudo journalctl -b -2 -p err

Bu özellik özellikle “sunucu neden yeniden başladı?” sorusunu cevaplamak için muazzamdır. Sistem çökmeden hemen önceki kernel mesajlarına bakabilirsiniz.

Kernel Logları

Donanım sorunları, driver problemleri veya kernel paniklerini araştırırken:

# Sadece kernel mesajları
sudo journalctl -k

# Son boot kernel logları
sudo journalctl -k -b

# Kernel hatalarını gerçek zamanlı izle
sudo journalctl -k -f -p warning

Çıktıyı Formatlamak ve İşlemek

journalctl çıktısını pipe ile diğer araçlara geçirebilirsiniz. --no-pager bunu kolaylaştırır:

# Hataları grep ile filtrele
sudo journalctl -u nginx --no-pager | grep "upstream"

# JSON formatında çıktı al (otomatik işleme için)
sudo journalctl -u nginx -o json-pretty | head -50

# Belirli alanları göster
sudo journalctl -u sshd --output=short-precise

# Hata sayısını öğren
sudo journalctl -p err --since "24 hours ago" --no-pager | wc -l

JSON çıktısı özellikle log analizi araçlarına (Elasticsearch, Splunk gibi) veri gönderirken veya script yazarken çok işe yarar.

/var/log Dizini: Klasik Log Dosyaları

Temel Dosya ve Dizinler

/var/log altında onlarca dosya ve dizin bulursunuz. Hangisinin ne işe yaradığını bilmek, hangi dosyaya bakacağınızı hızlıca belirlemenizi sağlar:

  • /var/log/syslog: Genel sistem logları, çoğu servisin mesajları burada
  • /var/log/auth.log: Kimlik doğrulama, sudo kullanımı, SSH girişleri
  • /var/log/kern.log: Kernel mesajları
  • /var/log/dpkg.log: Paket yükleme/kaldırma geçmişi
  • /var/log/apt/: APT işlemleri
  • /var/log/nginx/: Nginx access ve error logları
  • /var/log/mysql/: MySQL/MariaDB logları
  • /var/log/ufw.log: UFW firewall logları
  • /var/log/fail2ban.log: Fail2ban aksiyonları
  • /var/log/cloud-init.log: Cloud instance ilk başlatma logları

Gerçek Dünya Senaryosu: SSH Brute Force Tespiti

Sabah işe geldiniz, sunucunuzun auth.log’una bakıyorsunuz:

# Başarısız SSH girişlerini say ve IP'lere göre grupla
sudo grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -20

# Belirli bir IP'nin tüm aktivitesini gör
sudo grep "192.168.1.100" /var/log/auth.log | tail -50

# Başarılı girişleri kontrol et
sudo grep "Accepted password|Accepted publickey" /var/log/auth.log | tail -30

Bu tür sorguları düzenli çalıştırmak yerine fail2ban kurmanızı öneririm, ama logları elle incelemesini bilmek her zaman gereklidir.

Log Rotasyonu: logrotate

/var/log dolmaya başlarsa ciddi sorunlar çıkabilir. Disk dolduğunda uygulamalar yazamaz, crash eder. logrotate bu sorunu otomatik olarak çözer.

Mevcut konfigürasyona bakmak için:

cat /etc/logrotate.conf
ls /etc/logrotate.d/

Örnek bir uygulama için özel logrotate konfigürasyonu:

sudo nano /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}

Bu konfigürasyon logları günlük rotate eder, 14 gün saklar, sıkıştırır ve servisin reload edilmesini tetikler.

Manuel olarak test etmek için:

# Debug modunda çalıştır (gerçekte bir şey yapmaz)
sudo logrotate -d /etc/logrotate.d/nginx

# Zorla çalıştır
sudo logrotate -f /etc/logrotate.conf

journalctl Boyut Yönetimi

Journal dosyaları da büyüyebilir. /etc/systemd/journald.conf dosyasını düzenleyerek sınır koyabilirsiniz:

sudo nano /etc/systemd/journald.conf

Önemli parametreler:

  • SystemMaxUse: Toplam maksimum disk kullanımı (örn: 500M)
  • SystemKeepFree: Diskte bırakılacak minimum boş alan
  • MaxRetentionSec: Kaç saniyelik log saklanacak
  • MaxFileSec: Her journal dosyasının maksimum süresi

Konfigürasyon örneği:

[Journal]
SystemMaxUse=500M
SystemKeepFree=1G
MaxRetentionSec=1month
Compress=yes

Değişikliği uygulamak için:

sudo systemctl restart systemd-journald

Mevcut logları temizlemek için:

# 2 günden eski logları sil
sudo journalctl --vacuum-time=2d

# 500MB üzerini sil
sudo journalctl --vacuum-size=500M

# Sadece 3 boot bulundur
sudo journalctl --vacuum-files=3

Merkezi Log İzleme için Pratik Script

Birden fazla servisi izlemeniz gereken durumlarda bir izleme scripti yazabilirsiniz:

#!/bin/bash
# log-check.sh - Kritik servislerin son 1 saatteki hatalarını raporlar

SERVICES=("nginx" "postgresql" "redis" "ssh")
REPORT_FILE="/tmp/log-report-$(date +%Y%m%d-%H%M).txt"
ERROR_THRESHOLD=10

echo "=== Log Raporu - $(date) ===" > $REPORT_FILE
echo "" >> $REPORT_FILE

for service in "${SERVICES[@]}"; do
    ERROR_COUNT=$(journalctl -u $service --since "1 hour ago" -p err --no-pager 2>/dev/null | wc -l)
    
    echo "### $service servisi ###" >> $REPORT_FILE
    echo "Son 1 saatte hata sayısı: $ERROR_COUNT" >> $REPORT_FILE
    
    if [ "$ERROR_COUNT" -gt "$ERROR_THRESHOLD" ]; then
        echo "UYARI: Hata sayısı esik degeri asti!" >> $REPORT_FILE
        echo "Son hatalar:" >> $REPORT_FILE
        journalctl -u $service --since "1 hour ago" -p err --no-pager -n 5 >> $REPORT_FILE
    fi
    
    echo "" >> $REPORT_FILE
done

cat $REPORT_FILE

# Mail göndermek isterseniz:
# mail -s "Log Raporu $(date +%Y-%m-%d)" [email protected] < $REPORT_FILE

Bu scripti cron’a ekleyerek her saat çalıştırabilirsiniz:

chmod +x /usr/local/bin/log-check.sh
# Crontab'a ekle
echo "0 * * * * root /usr/local/bin/log-check.sh" | sudo tee -a /etc/cron.d/log-monitor

Gerçek Dünya Senaryosu: Servis Çökmesi Analizi

Bir uygulama servisiniz sürekli çöküyor. Nasıl analiz edersiniz?

# Servisin durumuna bak
sudo systemctl status myapp

# Son 50 satır log
sudo journalctl -u myapp -n 50 -r

# Servisin tüm crash geçmişi
sudo journalctl -u myapp -p err --no-pager

# Tam zaman damgasıyla (mikrosaniye hassasiyetinde)
sudo journalctl -u myapp -o short-precise | tail -30

# Servis crash öncesi 5 dakika
# Önce son crash zamanını bul
CRASH_TIME=$(sudo journalctl -u myapp --no-pager | grep -i "failed|crash|killed" | tail -1 | awk '{print $1, $2, $3}')
echo "Son crash zamanı: $CRASH_TIME"

# O zamandan 10 dakika öncesine bak
sudo journalctl -u myapp --until "$CRASH_TIME" --since "10 min before $CRASH_TIME"

OOM (Out of Memory) killer devreye girdiyse kernel loglarında bunu görebilirsiniz:

sudo journalctl -k | grep -i "oom|killed process|out of memory"

Uzak Sunuculardan Log Toplama

Birden fazla sunucunuzu varsa, her birine tek tek bağlanmak yerine merkezi bir yaklaşım benimseyebilirsiniz. Hızlı ve pratik bir çözüm olarak SSH üzerinden uzak journal çekme:

# Uzak sunucunun son 1 saatlik kritik logları
ssh user@remote-server "sudo journalctl -p err --since '1 hour ago' --no-pager"

# Birden fazla sunucu için döngü
for server in web1 web2 web3; do
    echo "=== $server ==="
    ssh deploy@$server "sudo journalctl -u nginx -p err --since '30 min ago' --no-pager" 2>/dev/null
done

Daha ciddi bir merkezi log altyapısı için Loki + Grafana veya ELK Stack’e bakmanızı öneririm, ama bu başlı başına ayrı bir konu.

İpuçları ve Sık Yapılan Hatalar

journalctl’ı root olmadan kullanmak: Normal kullanıcılar sistem loglarının tamamını göremez. adm veya systemd-journal grubuna ekleyin:

sudo usermod -aG systemd-journal username

Logları başka bir sisteme kopyalamak: Binary journal dosyalarını doğrudan kopyalayıp okuyabilirsiniz:

# Uzak sunucudan journal kopyala
scp -r user@server:/var/log/journal/[machine-id]/ /tmp/remote-journal/
sudo journalctl --directory=/tmp/remote-journal/

Syslog ile journal arasındaki köprü: Bazı eski uygulamalar sadece syslog’a yazar. rsyslog bu verileri hem /var/log/syslog‘a hem de journald’a iletebilir. Ubuntu’da bu köprü varsayılan olarak kurulu gelir.

Log seviyesi karmaşası: Bir uygulamanın “error” olarak işaretlediği şey, systemd’nin log seviyesiyle aynı olmayabilir. Uygulama kaynaklı hataları ararken sadece -p err ile yetinmeyip metin bazlı grep de kullanın.

Sonuç

Log yönetimi, sysadmin işinin belki de en az glamorlu ama en kritik parçasıdır. journalctl‘ın güçlü filtreleme yetenekleri ile /var/log altındaki klasik metin dosyalarını bir arada kullanmayı öğrendiğinizde, sorun giderme süreçleriniz gerçekten farklı bir boyuta geçer. Gece 2’deki alarm sizi daha az korkutur.

Pratik önerim şu: Her gün işe başlarken sudo journalctl -p err -b ile günün hatalarına hızlıca göz atın. Kritik servisleriniz için zaman bazlı monitoring scriptleri yazın. Log rotasyonunu düzgün yapılandırın ki disk dolması gibi aptalca ama can sıkıcı sorunlarla uğraşmayın. Ve en önemlisi, logları sadece bir şeyler patladığında okumayın, düzenli bakın ki anormallikler göze çarpsın.

Bir sonraki yazıda Graylog veya Loki ile merkezi log yönetimine geçişi inceleyeceğiz. O zamana kadar, loglar temiz kalsın.

Yorum yapın