Apache rotatelogs ve logrotate ile Log Yönetimi

Bir web sunucusu yönetiyorsanız ve log dosyalarınızın disk alanını yuttuğunu fark ettiyseniz, bu yazı tam size göre. Apache access ve error logları özellikle yüksek trafikli sitelerde inanılmaz hızla büyüyebiliyor. Gece yarısı “disk full” alarmıyla uyanmak istemiyorsanız, log yönetimini düzgün kurmak şart. Bu yazıda Apache’nin kendi aracı olan rotatelogs ile sisteme entegre logrotate araçlarını karşılaştırmalı olarak ele alacağız ve her ikisini de production ortamında nasıl kullanacağınızı göstereceğiz.

Log Yönetimi Neden Bu Kadar Önemli?

Basit bir örnek verelim: Günde 100.000 istek alan bir Apache sunucusunda access log yaklaşık 20-50 MB büyüyebiliyor. Bu, ayda 600 MB ile 1.5 GB arasında demek. Error logları da cabası. 6 ay sonra tek bir log dosyasının 10 GB’a ulaştığını gören sysadmin’lerin sayısı hiç de az değil.

Büyük log dosyalarının getirdiği sorunlar sadece disk dolması değil:

  • tail -f veya grep gibi komutlar 10 GB dosyada dakikalar sürebiliyor
  • Log analiz araçları (AWStats, GoAccess) devasa dosyaları işleyemiyor
  • Backup süreçleri yavaşlıyor
  • İncident sırasında hızlı log araması yapılamıyor

Çözüm: Logları düzenli olarak döndürmek (rotate), sıkıştırmak ve belirli bir süre sonra silmek.

rotatelogs: Apache’nin Yerleşik Log Döndürme Aracı

rotatelogs, Apache ile birlikte gelen ve pipe (|) mekanizmasıyla çalışan bir araçtır. Apache’nin CustomLog veya ErrorLog direktifine doğrudan bağlanır, yani log döndürme işlemi Apache sürecinin içinde gerçekleşir.

rotatelogs Temel Kullanımı

Apache yapılandırma dosyanızda (httpd.conf veya sanal host konfigürasyonu) şu şekilde kullanılır:

# /etc/apache2/sites-available/example.conf veya /etc/httpd/conf.d/example.conf

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/html

    # Zaman bazlı rotasyon: Her 24 saatte bir (86400 saniye)
    CustomLog "|/usr/bin/rotatelogs /var/log/apache2/access_%Y%m%d.log 86400" combined

    # Error log da rotate edilebilir
    ErrorLog "|/usr/bin/rotatelogs /var/log/apache2/error_%Y%m%d.log 86400"
</VirtualHost>

Bu yapılandırmada %Y%m%d format string’i sayesinde loglar access_20240115.log gibi isimlendirilir. Her gün gece yarısı otomatik olarak yeni bir dosya oluşturulur.

rotatelogs Parametre Referansı

-l: UTC yerine yerel saat kullanır. Timezone farkından kaynaklanan karışıklıkları önler, Türkiye’deki sunucularda mutlaka kullanın.

-L link: Belirtilen path’e sembolik link oluşturur, böylece “en güncel log” her zaman sabit bir isimde erişilebilir olur.

-n sayı: Tutulacak maksimum dosya sayısını belirler. Bu sayıyı aştığında eski dosyalar silinir.

-f: Başlangıçta hemen dosya oluşturur, ilk log satırı gelene kadar beklemez.

-D: Log dizini yoksa otomatik oluşturur.

-e: Logları hem dosyaya yazar hem de stdout’a yönlendirir.

-t: Rotate sırasında dosyayı kesmek (truncate) yerine yeni dosya oluşturur. Varsayılan davranış zaten budur ama bazı sürümlerde fark yaratabilir.

Boyut Bazlı Rotasyon

Zaman yerine boyut bazlı da çalışabilirsiniz. Özellikle trafiği çok değişken olan siteler için faydalı:

# 100 MB'a ulaşınca rotate et (104857600 byte = 100 MB)
CustomLog "|/usr/bin/rotatelogs -l /var/log/apache2/access_%Y%m%d_%H%M%S.log 104857600" combined

Sembolik Link ile Kombinasyon

Production ortamında çok kullanışlı bir yapılandırma:

# -L parametresi ile her zaman güncel loga sabit bir path üzerinden erişim
CustomLog "|/usr/bin/rotatelogs -l -L /var/log/apache2/access.log /var/log/apache2/access_%Y%m%d.log 86400" combined
ErrorLog "|/usr/bin/rotatelogs -l -L /var/log/apache2/error.log /var/log/apache2/error_%Y%m%d.log 86400"

Artık monitoring araçlarınız veya tail -f komutunuz hep /var/log/apache2/access.log‘u takip edebilir. Rotate olduğunda bu sembolik link otomatik yeni dosyaya işaret eder.

Dosya Sayısını Sınırlama

# Son 7 günün logunu tut, eskileri sil
CustomLog "|/usr/bin/rotatelogs -l -n 7 /var/log/apache2/access_%Y%m%d.log 86400" combined

Bu yapılandırmayla disk dolma riskini tamamen ortadan kaldırırsınız. 7 günlük log tutulur, daha eskisi otomatik silinir.

logrotate: Sistem Geneli Log Yönetimi

logrotate, Apache’ye özgü değil, sistem genelinde tüm log dosyalarını yönetmek için kullanılan bir araçtır. Cron veya systemd timer aracılığıyla düzenli çalışır. Apache log yönetiminde rotatelogs‘a göre daha fazla esneklik sunar çünkü sıkıştırma, e-posta bildirimi, özel scriptler gibi özellikler içerir.

logrotate’in Çalışma Mantığı

logrotate varsayılan olarak /etc/logrotate.conf ana konfigürasyonunu okur ve /etc/logrotate.d/ dizinindeki tüm dosyaları işler. Apache için genellikle /etc/logrotate.d/apache2 (Debian/Ubuntu) veya /etc/logrotate.d/httpd (RHEL/CentOS) dosyası mevcuttur.

Varsayılan Apache logrotate Konfigürasyonu

Çoğu sistemde gelen varsayılan konfigurasyon şu şekildedir:

# /etc/logrotate.d/apache2 (Debian/Ubuntu)
/var/log/apache2/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 640 root adm
    sharedscripts
    postrotate
        if invoke-rc.d apache2 status > /dev/null 2>&1; then 
            invoke-rc.d apache2 reload > /dev/null 2>&1; 
        fi
    endscript
    prerotate
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then 
            run-parts /etc/logrotate.d/httpd-prerotate; 
        fi
    endscript
}

Özelleştirilmiş logrotate Konfigürasyonu

Gerçek bir production senaryosu için daha detaylı bir yapılandırma:

# /etc/logrotate.d/apache2-custom

/var/log/apache2/access.log
/var/log/apache2/error.log {
    # Her gün rotate et
    daily
    
    # Log dosyası yoksa hata verme
    missingok
    
    # 30 gün tut
    rotate 30
    
    # Rotate edilen dosyaları gzip ile sıkıştır
    compress
    
    # Sıkıştırmayı bir gün geciktir (bir önceki günün logu açık kalabilir)
    delaycompress
    
    # Boş dosyaları rotate etme
    notifempty
    
    # Rotate sonrası dosyaları bu izin ve sahiplikle oluştur
    create 644 www-data adm
    
    # Tüm scriptleri bir kez çalıştır (birden fazla log dosyası varsa)
    sharedscripts
    
    # Rotate SONRASI Apache'ye USR1 sinyali gönder
    postrotate
        /usr/sbin/apachectl graceful > /dev/null 2>&1 || true
    endscript
}

logrotate Direktif Referansı

daily / weekly / monthly / yearly: Rotasyon sıklığını belirler.

rotate N: Kaç eski dosya tutulacağını belirler. rotate 14 ile 14 günlük log tutulur.

size N: Belirli boyuta ulaşınca rotate et. size 100M veya size 1G şeklinde kullanılır.

compress: Eski logları gzip ile sıkıştırır, disk tasarrufu için şart.

delaycompress: Son rotate edilmiş dosyayı bir sonraki rotate’e kadar sıkıştırmadan bekletir. Apache hala eski dosyaya yazıyor olabilir, bu direktif veri kaybını önler.

missingok: Log dosyası bulunamazsa logrotate hata vermez, sessizce devam eder.

notifempty: Boş log dosyalarını rotate etmez.

create mode owner group: Rotate sonrasında yeni dosyayı belirtilen izin ve sahiplikle oluşturur.

sharedscripts: prerotate ve postrotate scriptlerini birden fazla eşleşen dosya için tek seferinde çalıştırır.

copytruncate: Dosyayı kopyalayıp orijinalini sıfırlar. Apache’ye sinyal göndermeden çalışır ama küçük bir veri kaybı riski taşır. Zorunlu olmadıkça kullanmayın.

postrotate / endscript: Rotate işleminden sonra çalıştırılacak komutlar.

prerotate / endscript: Rotate işleminden önce çalıştırılacak komutlar.

olddir /path: Eski log dosyalarını belirtilen dizine taşır, ana log dizinini temiz tutar.

dateext: Rotated dosya ismine sayısal suffix yerine tarih ekler (access.log-20240115 gibi).

dateformat format: dateext için format belirler. dateformat -%Y%m%d ile access.log-20240115 elde edersiniz.

Sanal Host Bazlı logrotate

Birden fazla sanal host yönetiyorsanız, her sitenin loglarını ayrı tutmak iyi bir pratik:

# /etc/logrotate.d/apache2-vhosts

/var/log/apache2/site1.example.com-access.log
/var/log/apache2/site1.example.com-error.log {
    weekly
    rotate 8
    compress
    delaycompress
    missingok
    notifempty
    create 644 www-data adm
    dateext
    dateformat -%Y%m%d
    olddir /var/log/apache2/site1-archive
    sharedscripts
    postrotate
        /usr/sbin/apachectl graceful > /dev/null 2>&1 || true
    endscript
}

/var/log/apache2/site2.example.com-access.log
/var/log/apache2/site2.example.com-error.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 www-data adm
    dateext
    sharedscripts
    postrotate
        /usr/sbin/apachectl graceful > /dev/null 2>&1 || true
    endscript
}

logrotate’i Manuel Test Etme

Yeni bir konfigürasyon yazdıktan sonra test etmeden production’a almayın:

# Syntax kontrolü (debug modda, gerçekten çalıştırmaz)
logrotate -d /etc/logrotate.d/apache2-custom

# Zorla bir kez çalıştır (verbose çıktı ile)
logrotate -vf /etc/logrotate.d/apache2-custom

# Sadece belirli bir dosya için test
logrotate --debug --verbose /etc/logrotate.d/apache2-vhosts

# Son çalışma zamanını kontrol et
cat /var/lib/logrotate/status | grep apache

rotatelogs ile logrotate: Hangisini Seçmeli?

İkisi arasında seçim yaparken birkaç kritik farka dikkat etmek gerekiyor.

rotatelogs Apache sürecinin bir parçası olarak çalışır. Apache restart gerektirmez, rotasyon tam zamanında olur. Özellikle gerçek zamanlı log izleme ve anlık boyut kontrolü için idealdir. Ancak sıkıştırma özelliği yoktur, eski dosyaları kendiniz temizlemeniz gerekebilir.

logrotate ise sistemin cron altyapısını kullanır, sıkıştırma yapar, postrotate scriptiyle entegrasyon sağlar ve merkezi yönetim sunar. Dezavantajı: Cron çalışana kadar rotasyon gerçekleşmez ve Apache’ye graceful reload sinyali gönderilmesi gerekir.

Önerim: Yüksek trafikli sitelerde ikisini birlikte kullanmak mantıklı. rotatelogs ile günlük dosya oluşturun, logrotate ile sıkıştırın ve eski dosyaları temizleyin.

İkisini Birlikte Kullanma

# Apache konfigürasyonu: rotatelogs ile günlük dosya oluştur
# /etc/apache2/sites-available/example.conf
<VirtualHost *:80>
    ServerName example.com

    CustomLog "|/usr/bin/rotatelogs -l /var/log/apache2/access_%Y%m%d.log 86400" combined
    ErrorLog "|/usr/bin/rotatelogs -l /var/log/apache2/error_%Y%m%d.log 86400"
</VirtualHost>
# logrotate konfigürasyonu: Sadece sıkıştırma ve temizlik yap
# /etc/logrotate.d/apache2-rotatelogs
/var/log/apache2/access_*.log
/var/log/apache2/error_*.log {
    # Günlük dosyalar zaten rotatelogs tarafından oluşturuluyor
    # logrotate sadece sıkıştırma ve silme yapacak
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    # Apache'ye sinyal göndermeye gerek yok, rotatelogs halleder
    sharedscripts
    postrotate
        # Sadece 30 günden eski sıkıştırılmış dosyaları sil
        find /var/log/apache2/ -name "*.log.gz" -mtime +30 -delete
    endscript
}

Gerçek Dünya Senaryosu: Yüksek Trafikli E-ticaret Sitesi

Diyelim ki günde 500.000 istek alan bir e-ticaret sitesi yönetiyorsunuz. Access log günde 100 MB büyüyor, compliance gereksinimi 90 gün log saklama gerektiriyor. İşte bu senaryo için production-ready konfigürasyon:

# /etc/apache2/sites-available/ecommerce.conf

<VirtualHost *:443>
    ServerName shop.example.com

    # rotatelogs: Saatlik dosya (yoğun trafik için daha yönetilebilir)
    CustomLog "|/usr/bin/rotatelogs -l -n 2400 -L /var/log/apache2/ecommerce-access.log /var/log/apache2/ecommerce/access_%Y%m%d_%H.log 3600" combined

    # Error log günlük rotate
    ErrorLog "|/usr/bin/rotatelogs -l -L /var/log/apache2/ecommerce-error.log /var/log/apache2/ecommerce/error_%Y%m%d.log 86400"
</VirtualHost>
# /etc/logrotate.d/ecommerce-apache

/var/log/apache2/ecommerce/access_*.log
/var/log/apache2/ecommerce/error_*.log {
    daily
    rotate 90
    compress
    compresscmd /usr/bin/pigz
    compressext .gz
    compressoptions -9
    delaycompress
    missingok
    notifempty
    dateext
    dateformat -%Y%m%d
    olddir /var/log/apache2/ecommerce/archive
    
    sharedscripts
    prerotate
        # Rotate öncesi log analiz scriptini çalıştır
        /usr/local/bin/parse-access-logs.sh > /dev/null 2>&1 || true
    endscript
    
    postrotate
        # Sadece 90 günden eski arşivleri temizle
        find /var/log/apache2/ecommerce/archive/ -name "*.gz" -mtime +90 -delete
    endscript
}

logrotate Cron ve systemd Entegrasyonu

Debian/Ubuntu sistemlerde logrotate günlük cron ile çalışır:

# /etc/cron.daily/logrotate içeriğini kontrol et
cat /etc/cron.daily/logrotate

# systemd kullanan sistemlerde timer ile çalışır
systemctl status logrotate.timer
systemctl list-timers | grep logrotate

Eğer logrotate’in tam olarak belirli bir saatte çalışmasını istiyorsanız, timer’ı özelleştirebilirsiniz:

# /etc/systemd/system/logrotate.timer (override için)
[Unit]
Description=Daily rotation of log files
Documentation=man:logrotate(8)

[Timer]
OnCalendar=*-*-* 01:00:00
AccuracySec=1h
Persistent=true

[Install]
WantedBy=timers.target
# Timer'ı etkinleştir
systemctl daemon-reload
systemctl enable --now logrotate.timer
systemctl status logrotate.timer

Sık Yapılan Hatalar ve Çözümleri

Apache log dosyasını kilitleme sorunu: logrotate dosyayı rotate ettikten sonra Apache yeni dosyaya yazmaya devam etmez, eski dosyanın file descriptor’ını tutar. Bu yüzden postrotate‘de mutlaka apachectl graceful veya kill -USR1 kullanılmalıdır.

delaycompress’i atlamak: Eğer delaycompress kullanmazsanız, Apache hala açık tuttuğu log dosyası sıkıştırılmaya çalışılır. Bu veri kaybına neden olabilir.

rotatelogs’ta timezone sorunu: -l flag’ini unutursanız loglar UTC zaman damgasıyla açılır ama sunucu yerel saatteyse dosya isimleri karışır.

# Hatalı: UTC kullanır
CustomLog "|/usr/bin/rotatelogs /var/log/apache2/access_%Y%m%d.log 86400" combined

# Doğru: Yerel saat kullanır
CustomLog "|/usr/bin/rotatelogs -l /var/log/apache2/access_%Y%m%d.log 86400" combined

Disk dolduğunda log kaybı: Disk dolduğunda hem rotatelogs hem de logrotate log yazmayı durdurur. Bunu önlemek için disk kullanım monitörinüzü doğru kurun ve rotate sayısını gerçekçi tutun.

Sonuç

Apache log yönetiminde rotatelogs ve logrotate‘in birbirini tamamlayan araçlar olduğunu gördük. rotatelogs, Apache’nin doğal bir parçası olarak gerçek zamanlı log döndürme sağlar; logrotate ise sıkıştırma, arşivleme ve temizlik konusunda çok daha güçlüdür.

Production ortamı için önerim şu şekilde özetlenebilir: Yüksek trafikli sitelerde rotatelogs ile saatlik veya günlük dosya oluşturun, logrotate ile sıkıştırın ve eski dosyaları temizleyin. Düşük trafikli sitelerde ise sadece logrotate yeterlidir, sadelik her zaman kazanır.

Konfigürasyonları yazdıktan sonra -d ve -vf parametreleriyle test etmeyi, sistemin cron/timer çalışmasını kontrol etmeyi ve en az bir kez manuel tetikleyerek çalışmayı doğrulamayı ihmal etmeyin. Log yönetimi tek seferlik bir iş değil, periyodik olarak disk kullanımını ve konfigürasyonun düzgün çalışıp çalışmadığını kontrol etmeniz gereken bir bakım rutinidir.

Yorum yapın