Servis ayakta, kullanıcı "dün çalışıyordu" diyor ve siz bir tail -f /var/log/syslog çekiyorsunuz ama hiç yeni satır görünmüyor. Sorun şu ki o sunucuda söz konusu servis aslında syslog'a yazmıyor. Linux log konumu sabit bir yol değildir; dağıtıma, init system'e ve servisin nasıl derlendiğine bağlıdır. Bu üçünü ayırmadığınız sürece log dosyası aramak zaman kaybıdır.
Hızlı harita: Her servis nereye yazıyor
Günümüzdeki çoğu dağıtımda bu tablo aramaların %90'ını yanıtlar:
| Servis | Olağan yol | Not |
|---|---|---|
| Kernel ve boot | /var/log/kern.log veya dmesg | RHEL ailesinde /var/log/messages içinde |
| Kimlik doğrulama ve SSH | /var/log/auth.log | CentOS/Rocky'de: /var/log/secure |
| Nginx | /var/log/nginx/access.log | Hatalar aynı klasördeki error.log içinde |
| Apache | /var/log/apache2/ veya /var/log/httpd/ | Dağıtıma göre değişir |
| MySQL / MariaDB | /var/log/mysql/error.log | RHEL'de: /var/log/mysqld.log |
| PostgreSQL | /var/log/postgresql/ | Veya data directory içinde |
| PHP-FPM | /var/log/php8.2-fpm.log | Sürüm numarası dosya adında |
| Docker | journalctl -u docker | Konteyner logları başka bir yerde |
Bu tabloyu ezberlemeyin. systemctl status nginx komutu son satırında logun nerede olduğunu söyler ve nginx -T tüm konfigürasyonu access_log yoluyla birlikte yazdırır. Tahmin etmekten daha hızlıdır.
journald'e karşı dosya: Hangisine güvenelim
Ubuntu 22.04 ve üzerinde ve systemd bulunan neredeyse tüm dağıtımlarda, logların büyük bir kısmı aslında metin dosyası değildir. İkili journal dosyalarında saklanırlar, /var/log/journal/ veya /run/log/journal/ altında. Eğer ilk klasör yoksa, loglar RAM'de kalır ve her yeniden başlatmada silinir. Bu, "dünkü logum yok" sorununun en yaygın nedenlerinden biridir.
Journal'ın diske yazıp yazmadığını görmek için:
ls -d /var/log/journal
journalctl --disk-usage
Eğer ilk komut hata verirse, persistent değil demektir. mkdir -p /var/log/journal && systemd-journald --flush ve servisi yeniden başlatmakla düzelir. Journal'ın varsayılan boyutu normal kurulumlarda dosya sisteminin %10'una kadar büyür; 40 GB diskli bir sunucuda bu yaklaşık 4 GB demektir, dikkat etmezseniz bir sabah df -h ile sürprizle karşılaşırsınız.
Gerçekten işe yarayan filtreler
journalctl -u nginx --since "1 hour ago" iyi bir başlangıç noktasıdır. Sadece hataları görmek için -p err ekleyin ve canlı takip için -f. Eğer PID'niz varsa, journalctl _PID=1234 tam olarak o prosesi verir. Bu sonuncusu, birden fazla worker'ınız olduğunda ve sadece birinin sorunu olduğunda, on dakika ile iki saat arasındaki farktır.
Gerçek bir sınırlama: journald web sunucusu access loglarını tutmaz. Nginx ve Apache doğrudan dosyaya yazar, çünkü hacimleri o kadar yüksektir ki journal'a yazmak pratik değildir. Yani journald'nin olduğu sunucuda hem journalctl çekmeli hem de dosya üzerinde tail yapmalısınız. Bu ikisi tamamlayıcıdır, birbirinin yerine geçmez.
Burada hata yapıyorlar
Çok gördüğüm yaygın hata: Birisi yer açmak için rm /var/log/nginx/access.log çeker, sonra df -h çeker ve yerin boşalmadığını görür. Nedeni, Nginx'in hâlâ dosyayı açık tutması ve inode'un canlı olmasıdır; dosya dizinden kaybolmuştur ama baytları diskte kalmıştır. Doğru yol truncate -s 0 /var/log/nginx/access.log veya logrotate -f /etc/logrotate.d/nginx kullanmaktır. Eğer daha önce rm yaptıysanız, lsof +L1 ile silinmiş açık dosyaları bulun ve servisi reload edin.
İkinci hata daha incedir: Bazıları journalctl -u mysql çıktı verdiği için MySQL logunun orada olduğunu düşünür. Aslında systemd sadece servisin stdout'unu yakalar; MySQL'in kendisi error.log içine yazar ve o dosya daha eksiksiz ayrıntılara sahiptir. Eğer crash nedenini arıyorsanız, journal'ı değil dosyayı okuyun.
Log rotasyonu: Bir gecede sunucuyu uyutan şey
logrotate varsayılan olarak günlük çalışır ve servis konfigürasyonları /etc/logrotate.d/ içindedir. Tipik bir blok şöyle görünür:
/var/log/nginx/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
sharedscripts
postrotate
invoke-rc.d nginx rotate >/dev/null 2>&1
endscript
}
Burada iki satır kritiktir. create 0640 www-data adm yeni dosyanın sahipliğini belirler; eğer yanlışsa, ilk rotasyondan sonra Nginx artık yazamaz ve site 500 ile açılır. Ve postrotate servisi dosyayı yeniden açmaya zorlamalıdır, yoksa aynı açık inode sorunu tekrarlanır. logrotate -d /etc/logrotate.d/nginx ile gerçekten çalıştırmadan çıktıyı görebilirsiniz.
Yoğun trafikli sunucularda günlük rotasyon yeterli değildir. Eğer access.log'unuz 24 saatte birkaç gigabayta ulaşıyorsa, daily yerine size 500M koyun. Burada iki seçenek arasında bir seçim var: Zamana dayalı rotasyon öngörülebilir dosyalar verir ve analiz için daha kolaydır; boyuta dayalı rotasyon diski daha güvenli tutar. Ben yüksek trafikli web sunucularında boyutu seçiyorum, çünkü yoğun bir gün rotasyon sırası gelmeden diski doldurabilir.
Sunucu açılmadığında ve logunuz olmadığında
En kötü durum, servisin hiç başlamaması ve log da üretmemesidir. Önce systemctl status myservice -l --no-pager çekin; -l satırların kısaltılmamasını sağlar ve gerçek hata mesajını görürsünüz. Eğer servis systemd ile yönetilmiyorsa, doğrudan strace -f -e trace=openat ./binary ile çalıştırın ki hangi dosyayı açtığını ve nerede başarısız olduğunu görün.
Eğer sorun işletim sisteminin kendisindeyse ve erişiminiz kesilmişse, rescue modunu kullanın. Sunucuyu yeniden kurma ve rescue moduyla çalışma; erişimi kaybettiğinizde verileri kurtarma kılavuzu tam olarak bu senaryoyu kapsıyor. Ve eğer loglar sorunun belirli bir servisten değil kaynak tüketiminden kaynaklandığını gösteriyorsa, Yüksek sunucu yükünün nedenini teşhis etme; pratik ve adım adım kılavuz daha doğru yoldur.
Dağıtım farklarına bir bakış
Debian ve Ubuntu'da /var/log/syslog her şeyi toplar ve /var/log/auth.log ayrıdır. RHEL, Rocky ve AlmaLinux'ta syslog yoktur; /var/log/messages ve /var/log/secure onların yerini almıştır. musl ve busybox kullanan Alpine'da rsyslog bile kurulu olmayabilir ve her şey sadece journal'da olabilir. Eğer izleme betiği yazıyorsanız, yolu hardcode etmeyin; önce dosyanın varlığını kontrol edin.
Yeni sunucular için pratik bir ipucu: Bir sorun çıkmadan önce bir kez ls -la /var/log/ çekin ve orada ne olduğunu görün. Şimdi beş dakika, site çökmüşken gece ikide büyük bir tasarruftur. Eğer bulut altyapısında çalışıyorsanız ve bu işi baştan doğru yapmak istiyorsanız, bulut sunucu log diskini ayrı tutma imkânı verir ve dokümantasyon ve bilgi tabanı da logrotate konfigürasyon örneklerine sahiptir. NVMe diskli fiziksel sunucularda, yüksek hacimli log yazımı bir I/O sorunu değildir ve rotate değerini daha yükseğe çıkarabilirsiniz.
Sık sorulan sorular
Linux logu varsayılan olarak nerededir?
Ana klasör /var/log/'dur ve çoğu servisin kendi alt klasörü vardır, örneğin /var/log/nginx/ veya /var/log/mysql/. systemd bulunan sistemlerde logların bir kısmı journal'da saklanır ve cat ile değil journalctl ile okunur.
Bir servisin hangi dosyaya yazdığını nasıl anlarım?
En hızlı yol, çıktısında log yolunu gösteren systemctl status <service> komutudur. Yeterli değilse, lsof -p $(pidof nginx) | grep log o prosesin açık tüm log dosyalarını listeler. Nginx gibi konfigürasyonu olan servisler için nginx -T komutu access_log değerini yazdırır.
Eski loglarım neden yeniden başlatmadan sonra silindi?
Çünkü journald volatile modda çalışıyor ve logları tmpfs üzerindeki /run/log/journal/ içinde tutuyor. /var/log/journal/ oluşturup systemd-journald'yi yeniden başlatarak persistent mod etkinleşir ve loglar diskte kalır.
Logları başka bir sunucuya göndermek mümkün mü?
Evet, rsyslog veya systemd-journal-upload ile. Düşük hacim için UDP port 514 üzerinden rsyslog yeterlidir; log bütünlüğünün önemli olduğu ortamlar için TLS'li TCP daha doğru seçimdir. Sadece şuna dikkat edin: Hedef sunucu erişilemez olursa, yerel rsyslog kuyruğu doldurabilir ve kendisi sorun kaynağı olabilir.