Bir uygulamanın neden bu kadar yavaş çalıştığını, bir servisin neden belirli bir dosyaya erişemediğini ya da bir programın arka planda ne yaptığını hiç merak ettiniz mi? İşte tam bu noktada strace devreye girer. Linux dünyasının en güçlü hata ayıklama araçlarından biri olan strace, bir sürecin çekirdeğe yaptığı tüm sistem çağrılarını gerçek zamanlı olarak izlemenizi sağlar. Kaynak koduna ihtiyaç duymadan, debug sembolü olmadan, sadece süreci çalıştırarak ne yaptığını görebilirsiniz. Bu yazıda strace‘i gerçek dünya senaryolarıyla ele alacağız.
strace Nedir ve Nasıl Çalışır?
strace, Linux çekirdeğinin ptrace sistem çağrısını kullanarak bir süreci izleyen bir araçtır. Program çalışırken yaptığı her sistem çağrısını (open, read, write, fork, execve vb.) ve bu çağrıların dönüş değerlerini ekrana basar. Sinyal bildirimlerini de yakalayabilir.
Temel mantığı şöyle düşünebilirsiniz: Uygulamanız kullanıcı uzayında (user space) çalışır. Dosya okumak, ağ bağlantısı kurmak, bellek ayırmak gibi işlemler için çekirdeğe (kernel space) geçmesi gerekir. İşte bu geçiş noktaları sistem çağrılarıdır ve strace tam olarak bu geçişleri dinler.
Dikkat: strace izlediği süreci yavaşlatır. Production ortamında dikkatli kullanılmalıdır. Bazı durumlarda %10-100 arasında performans kaybı yaşanabilir.
Kurulum
Çoğu dağıtımda varsayılan olarak gelmez ama paket depolarında mevcuttur:
# Debian/Ubuntu
sudo apt install strace
# RHEL/CentOS/Fedora
sudo yum install strace
# veya
sudo dnf install strace
# Arch Linux
sudo pacman -S strace
Temel Kullanım
En basit kullanım şekli bir komutun önüne strace eklemektir:
strace ls /tmp
Bu komutu çalıştırdığınızda ekrana akan onlarca satır sizi şaşırtabilir. Basit bir ls komutu bile onlarca sistem çağrısı yapar. Çıktının bir kısmı şöyle görünür:
execve("/usr/bin/ls", ["ls", "/tmp"], 0x7ffd... /* 23 vars */) = 0
brk(NULL) = 0x55a8b2e45000
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF2113>1"..., 832) = 832
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
Her satır bir sistem çağrısıdır. Format şöyledir: sistem_cagri_adi(parametreler) = donus_degeri
Önemli Parametreler
strace‘in asıl gücü parametrelerinden gelir:
- -e trace=: Belirli sistem çağrılarını filtreler, örneğin
-e trace=open,read - -p PID: Halihazırda çalışan bir sürece bağlanır
- -f: Fork edilen alt süreçleri de izler
- -o dosya: Çıktıyı bir dosyaya yazar
- -t: Her satıra zaman damgası ekler (saat:dakika:saniye)
- -T: Her sistem çağrısının ne kadar sürdüğünü gösterir
- -c: İstatistik özeti verir, hangi çağrı kaç kez yapılmış
- -s: String çıktı uzunluğunu ayarlar, varsayılan 32 karakterdir
- -v: Yapıları tam detayıyla gösterir
- -x: String olmayan argümanları hexadecimal gösterir
- -y: File descriptor’ları dosya yollarıyla gösterir
- -yy: Soket bilgilerini de ekler
Gerçek Dünya Senaryosu 1: Uygulama Hangi Dosyaları Açıyor?
En sık karşılaştığım senaryolardan biri şudur: Bir uygulama başlarken hata veriyor ama hangi config dosyasını okumaya çalıştığını bilmiyorsunuz. Belgelendirme yok, kaynak kodu yok ya da bakmaya zamanınız yok.
strace -e trace=openat,open -o /tmp/dosya_izleme.txt uygulama_adi
cat /tmp/dosya_izleme.txt | grep -i "config|conf|.ini|.yaml"
Daha da pratik bir yaklaşım:
strace -e trace=openat 2>&1 python3 myapp.py | grep "ENOENT"
ENOENT (No such file or directory) hatası alan satırları filtreleyerek uygulamanın aradığı ama bulamadığı dosyaları hemen görürsünüz. Bu tek satır bana sayısız kez saatlerce debug sürecini birkaç dakikaya indirdi.
Örnek çıktı:
openat(AT_FDCWD, "/etc/myapp/config.yaml", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/local/etc/myapp.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/user/.myapp/config", O_RDONLY) = 5
İşte bu çıktı size şunu söyler: Uygulama önce iki yerde aradı, bulamadı, üçüncüde buldu. Artık hangi config dosyasının kullanıldığını kesin olarak biliyorsunuz.
Gerçek Dünya Senaryosu 2: Çalışan Bir Sürece Bağlanma
Bazen sorun zaten çalışan bir süreçte oluşur. Servisi yeniden başlatmak istemiyorsunuz ya da sorun sadece belirli koşullarda ortaya çıkıyor. -p parametresiyle mevcut bir sürece bağlanabilirsiniz:
# Önce PID'i bulun
pgrep nginx
# veya
pidof nginx
# Sürece bağlanın
sudo strace -p 1234
Nginx’in birden fazla worker süreci varsa hepsini aynı anda izleyebilirsiniz:
sudo strace -p 1234 -p 1235 -p 1236 -o /tmp/nginx_strace.log
Ya da tüm nginx süreçlerine otomatik bağlanmak için:
sudo strace $(pgrep nginx | sed 's/^/-p /' | tr 'n' ' ') -o /tmp/nginx_debug.log
Gerçek Dünya Senaryosu 3: Performans Darboğazı Tespiti
Bir serviste periyodik yavaşlama var. Kodda herhangi bir sorun göremiyorsunuz. -c ve -T parametreleri burada hayat kurtarır.
-c ile istatistik özeti alın:
strace -c -p $(pgrep myservice) &
sleep 30
kill %1
Çıktı şöyle görünür:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
78.23 2.342100 2342 1000 fsync
12.45 0.373200 37 10000 write
5.32 0.159600 16 10000 read
...
Eğer fsync çağrısı zamanın %78’ini alıyorsa, uygulama her yazma işleminde diski senkronize ediyordur. Bu ciddi bir performans problemidir. Diskinizin yavaş olması ya da SSD yerine HDD kullanılıyor olması bu sorunu katmerlendirir.
-T parametresiyle hangi çağrıların uzun sürdüğünü tek tek görebilirsiniz:
strace -T -e trace=read,write,fsync -p 1234 2>&1 | awk '$NF ~ /.[0-9]+/ && $NF+0 > 0.1'
Bu komut 100ms’den uzun süren sistem çağrılarını filtreler. Çıktıda gördüğünüz gibi değerler saniye cinsindendir.
Gerçek Dünya Senaryosu 4: Ağ Bağlantılarını İzleme
Bir uygulama nereye bağlanıyor? Hangi IP’lere, hangi portlara istek atıyor? Bunu firewall logları olmadan da anlayabilirsiniz:
strace -e trace=network -p $(pgrep myapp) 2>&1 | grep -E "connect|bind|listen"
Daha detaylı soket bilgisi için:
strace -e trace=connect,bind,socket -yy -p 1234
-yy parametresi soket bilgilerini insan okunabilir formatta gösterir:
connect(5<TCP:[local_ip:port]>, {sa_family=AF_INET, sin_port=htons(5432), sin_addr=inet_addr("192.168.1.100")}, 16) = 0
Artık uygulamanın 192.168.1.100:5432 adresine (muhtemelen PostgreSQL) bağlandığını görebiliyorsunuz. Herhangi bir network monitoring aracı kurmadan, sadece strace ile.
Gerçek Dünya Senaryosu 5: Permission Denied Hatalarını Analiz Etme
“Permission denied” hatası alıyorsunuz ama hangi dosya ya da kaynak için olduğunu bilmiyorsunuz. Uygulama sadece genel bir hata mesajı verip çıkıyor.
strace -e trace=openat,stat,access 2>&1 myapp | grep "EACCES|EPERM"
Çıktı:
openat(AT_FDCWD, "/var/log/myapp/app.log", O_WRONLY|O_CREAT|O_APPEND, 0644) = -1 EACCES (Permission denied)
Hemen anladınız: /var/log/myapp/app.log dosyasına yazma izni yok. Çözüm basit:
sudo chown myappuser:myappuser /var/log/myapp/
# veya
sudo chmod 755 /var/log/myapp/
Bu yöntemi kullanarak özellikle systemd servisleri ve containerized uygulamalarda çok sık izin sorunlarını çözdüm. Kaynak kodu olmayan third-party araçlarda bu yaklaşım gerçekten paha biçilemez.
Gerçek Dünya Senaryosu 6: Sonsuz Döngü ve Yüksek CPU Tespiti
Bir process %100 CPU kullanıyor ama neden bilmiyorsunuz. strace burada da yardımcı olur:
sudo strace -p $(pgrep -f "sorunlu_uygulama") -c -e trace=all
Eğer çıktıda aynı sistem çağrısının milyonlarca kez tekrarlandığını görüyorsanız (örneğin gettimeofday, clock_gettime), uygulama muhtemelen sonsuz bir döngüde zaman kontrolü yapıyor ya da busy-waiting durumundadır.
Gerçek zamanlı olarak görmek isterseniz:
sudo strace -p 1234 2>&1 | head -50
Çıktı akışına bakın: Eğer aynı satırlar sürekli tekrar ediyorsa, sonsuz döngü olduğu açıktır.
Çıktıyı Anlamlandırma: Hata Kodları
strace çıktısında bazı hata kodlarına çok sık rastlarsınız. Bunları ezberlemek debug sürecini hızlandırır:
- ENOENT: Dosya veya dizin bulunamadı
- EACCES: Erişim reddedildi
- EPERM: İşlem izni yok (genellikle root gerektiren işlemler için)
- ENOBUFS / ENOMEM: Bellek veya buffer yetersiz
- EINTR: Sistem çağrısı sinyal tarafından kesildi
- EAGAIN / EWOULDBLOCK: Kaynak geçici olarak kullanılamıyor (non-blocking I/O)
- ECONNREFUSED: Bağlantı reddedildi
- ETIMEDOUT: Bağlantı zaman aşımına uğradı
- EEXIST: Dosya veya dizin zaten var
- EBADF: Geçersiz file descriptor
Bu kodlar çıktıda her zaman parantez içinde açıklamasıyla birlikte gelir, bu da strace‘i gerçekten kullanıcı dostu kılar.
Alt Süreçleri İzleme: -f Parametresi
Bir süreç başka süreçler başlatıyorsa (örneğin bir shell scripti, systemd servisi ya da multiprocess uygulama), -f parametresi ile fork edilen tüm alt süreçleri de izleyebilirsiniz:
strace -f -o /tmp/full_trace.log bash deploy.sh
Bu özellikle CI/CD pipeline’larında veya karmaşık başlangıç scriptlerinde sorun giderirken çok işe yarar. Çıktıda her süreç kendi PID’iyle belirtilir:
[pid 12345] execve("/usr/bin/git", ["git", "pull"], ...) = 0
[pid 12346] openat(AT_FDCWD, ".git/config", O_RDONLY) = 3
String Uzunluğunu Artırma: -s Parametresi
Varsayılan olarak strace stringleri 32 karakterde keser. Bu bazen kritik bilgileri gizler. Özellikle HTTP isteklerini, veritabanı sorgularını veya uzun dosya yollarını izlerken string uzunluğunu artırın:
strace -s 1024 -e trace=write -p $(pgrep myapp)
Eğer bir uygulamanın tam olarak hangi SQL sorgusunu gönderdiğini görmek istiyorsanız:
strace -s 4096 -e trace=write,sendto -p $(pgrep myapp) 2>&1 | grep -A2 "SELECT|INSERT|UPDATE"
Bu yöntem, ORM kullanan uygulamalarda gerçekte hangi sorguların üretildiğini görmek için harika çalışır.
Pratik Tek Satırlık Komutlar
Sysadmin günlük hayatında işe yarayan hazır tarifler:
# Bir sürecin açık tuttuğu tüm dosyaları bul
strace -e trace=openat -p 1234 2>&1 | grep -v "= -1"
# En çok hangi sistem çağrısı yapılıyor?
strace -c myprogram 2>&1 | sort -k4 -rn | head -10
# Ağ trafiğini izle ve IP adresi göster
strace -e trace=connect -yy myprogram 2>&1 | grep "sin_addr"
# Gerçek zamanlı yazma işlemlerini izle
strace -e trace=write -s 2048 -p 1234 2>&1 | grep -v "^write.*= [0-9]$"
# Belirli bir dosyaya yapılan tüm erişimleri izle
strace -e trace=openat -p 1234 2>&1 | grep "dosya_adi"
ltrace ile Karşılaştırma
strace sistem çağrılarını izlerken, ltrace kütüphane çağrılarını (libc fonksiyonları gibi) izler. İkisi birbirini tamamlar:
# Sistem çağrıları
strace -e trace=read,write myapp
# Kütüphane çağrıları (strcmp, malloc vb.)
ltrace myapp
Hangi katmanda sorun olduğunu anlamak için ikisini birlikte kullanmak iyi bir yaklaşımdır. Eğer ltrace‘de sorun görüyorsanız uygulama mantığında, strace‘de görüyorsanız işletim sistemi etkileşimindedir.
Güvenlik ve Production Dikkat Notları
strace güçlü bir araçtır ama dikkatli kullanılmalıdır:
- Performans etkisi: İzlenen süreç ciddi ölçüde yavaşlar. Production’da kısa süreli kullanın.
- Güvenlik:
straceçıktısında şifreler, API anahtarları, session token’lar görünebilir. Çıktı dosyalarını güvenli tutun. - Root yetkisi: Başka bir kullanıcının sürecine bağlanmak için root gerekir.
- Seccomp: Bazı containerized ortamlar
ptracesistem çağrısını kısıtlar. Docker’da--cap-add=SYS_PTRACEgerekebilir. - SELinux: SELinux politikaları
stracekullanımını engelleyebilir, geçici olarakpermissivemoda alınabilir.
Docker container içinde kullanmak için:
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined myimage strace myapp
Alternatif: perf ve bpftrace
strace harika bir araç ama production’da daha hafif alternatiflere ihtiyaç duyabilirsiniz:
- perf trace:
strace‘e benzer ama çok daha düşük overhead ile çalışır. eBPF tabanlı sistemlerde tercih edilir. - bpftrace: Modern Linux çekirdeklerinde eBPF ile sistem çağrılarını neredeyse sıfır overhead ile izler.
# perf trace ile aynı işlev
sudo perf trace -p 1234
# bpftrace ile openat çağrılarını izle
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %sn", comm, str(args->filename)); }'
Ancak hata ayıklama ve öğrenme aşamasında strace‘in okunabilirliği ve kullanım kolaylığı hala rakipsizdir.
Sonuç
strace, Linux sistem yönetiminin ve hata ayıklamanın vazgeçilmez araçlarından biridir. Belgelendirmesi olmayan bir uygulamanın hangi dosyaları okuduğunu bulmak, gizli bir permission hatasını yakalamak, performans darboğazını tespit etmek ya da ağ bağlantılarını izlemek için kaynak koda ihtiyaç duymadan çalışabilirsiniz. Bu özelliği onu özellikle binary uygulamalar, legacy sistemler ve third-party araçlarla uğraşırken paha biçilmez kılar.
Temel kullanımı öğrendikten sonra -e, -f, -c, -T gibi parametreleri günlük iş akışınıza entegre edin. Zamanla strace çıktısını okumak size ikinci bir dil gibi gelmeye başlar. Bir süreci “şeffaflaştırmak” ve arka planda ne yaptığını görmek hem hata ayıklamayı hem de sistemi anlama sürecini kökten değiştirir.
Son bir tavsiye: Bir sonraki “neden çalışmıyor?” probleminizde direkt Google’a atlamadan önce strace -e trace=openat,connect -o /tmp/debug.log problemli_komut deneyin. Çoğu zaman cevap orada gizlidir.