lsof Komutu ile Açık Dosyaları ve Süreçleri İzleme

Sistem yöneticiliğinde “bu dosyayı kim açmış?” ya da “bu port neden kapanmıyor?” gibi sorularla günde birkaç kez karşılaşırsınız. İşte tam bu noktada lsof komutu hayat kurtarıcı olur. Yıllarca farklı ortamlarda çalıştıktan sonra şunu net olarak söyleyebilirim: lsof olmadan bir Linux sistemini gerçek anlamıyla yönettiğinizi söyleyemezsiniz.

lsof, “list open files” yani açık dosyaları listele anlamına gelir. Linux’ta her şeyin bir dosya olduğunu düşünürsek, bu komutun ne kadar güçlü olduğunu tahmin edebilirsiniz. Soketler, pipe’lar, dizinler, sembolik linkler, cihaz dosyaları… Hepsi lsof ile izlenebilir. Bu yazıda komutu yüzeysel geçmeyeceğim; gerçek senaryolarla, sık yapılan hatalarla ve pratik kullanım kalıplarıyla ele alacağım.

lsof Nedir ve Neden Bu Kadar Önemlidir

Temel olarak lsof, çalışan süreçlerin hangi dosyaları, soketleri veya kaynakları açık tuttuğunu gösterir. Bu bilgi; disk alanı sorunlarını giderirken, port çakışmalarını çözerken, güvenlik olaylarını incelerken veya uygulama davranışını anlamaya çalışırken kritik öneme sahiptir.

Birçok sysadmin ps ve netstat ile idare etmeye çalışır. Ancak lsof, bu iki komutun kesişim noktasında duran ve çok daha fazlasını sunan bir araçtır. Özellikle silinmiş ama hala açık tutulan dosyalar gibi sinsi sorunlarda lsof tek çare olabilir.

Kurulu değilse hemen yükleyebilirsiniz:

# Debian/Ubuntu sistemlerde
sudo apt install lsof

# RHEL/CentOS/Rocky Linux sistemlerde
sudo yum install lsof
# veya
sudo dnf install lsof

Çoğu modern dağıtımda zaten kurulu gelir. Kontrol etmek için:

which lsof
lsof -v

Temel Kullanım ve Çıktıyı Anlamak

Tek başına çalıştırdığınızda lsof oldukça fazla çıktı üretir. Orta büyüklükteki bir sunucuda binlerce satır görmek normaldir.

sudo lsof | head -20

Çıktının sütunlarını anlamak önemlidir:

  • COMMAND: Dosyayı açan sürecin adı
  • PID: Süreç kimlik numarası
  • USER: Süreci çalıştıran kullanıcı
  • FD: Dosya tanımlayıcı tipi (cwd, txt, mem, 1u, 2w gibi)
  • TYPE: Dosya tipi (REG, DIR, CHR, FIFO, IPv4, IPv6 gibi)
  • DEVICE: Aygıt numaraları
  • SIZE/OFF: Dosya boyutu veya offset
  • NODE: Inode numarası
  • NAME: Dosyanın tam yolu veya bağlantı bilgisi

FD sütununda göreceğiniz bazı değerler özellikle kafa karıştırıcı olabilir:

  • cwd: Sürecin mevcut çalışma dizini
  • txt: Çalıştırılabilir dosya veya kütüphane
  • mem: Belleğe eşlenmiş dosya
  • 0u, 1u, 2u: stdin, stdout, stderr (u=okuma/yazma, r=sadece okuma, w=sadece yazma)

Belirli Bir Kullanıcının Açık Dosyaları

Bir kullanıcının neler yaptığını anlamak istediğinizde -u parametresi kullanılır:

lsof -u nginx
lsof -u www-data

Belirli bir kullanıcı dışındaki tüm kullanıcıların dosyalarını görmek için ^ operatörü kullanılır:

lsof -u ^root

Bu özellikle güvenlik olaylarını incelerken çok işe yarar. Örneğin sistemde yetkisiz bir işlem yapan bir kullanıcı hesabını analiz ederken o kullanıcının tüm açık dosya, soket ve süreçlerini tek komutla görebilirsiniz.

Port ve Ağ Bağlantılarını İzlemek

Bence lsof‘un en sık kullanıldığı alan budur. “80 portu kim kullanıyor?” sorusu klasik bir sorudur ve cevabı çok basittir:

sudo lsof -i :80
sudo lsof -i :443
sudo lsof -i :3306

Belirli bir protokol için filtreleme yapmak da mümkündür:

# Sadece TCP bağlantıları
sudo lsof -i TCP

# Sadece UDP bağlantıları
sudo lsof -i UDP

# Belirli bir port aralığı
sudo lsof -i TCP:8000-9000

Gerçek bir senaryo paylaşayım: Bir müşteri sisteminde Apache servisini yeniden başlatmaya çalışıyorduk ama “Address already in use” hatası alıyorduk. netstat çıktısına baktık ama kim kullandığını net göremedik. lsof ile çözdük:

sudo lsof -i :80 -P -n

-P parametresi port numaralarını servis adına çevirmez (http, https yazmak yerine 80, 443 yazar), -n parametresi ise IP adreslerini hostname’e çevirmeyi atlar. Bu iki parametre komutu çok daha hızlı çalıştırır. Çıktıda eski bir PHP-FPM sürecinin portu boşaltmadan kapanmadığını gördük ve PID’i alarak zorla sonlandırdık.

Tüm ağ bağlantılarını görmek istiyorsanız:

sudo lsof -i -P -n

Bu komutu bir alias olarak .bashrc veya .bash_profile dosyanıza ekleyebilirsiniz:

alias netfiles='sudo lsof -i -P -n'

Belirli Bir Dosyayı Hangi Süreç Kullanıyor

Klasik sorun: Bir dosyayı silmek ya da taşımak istiyorsunuz ama “busy” hatası alıyorsunuz. Ya da bir log dosyasını rotate etmek istiyorsunuz ama hangi sürecin tuttuğunu bilmiyorsunuz.

sudo lsof /var/log/nginx/access.log
sudo lsof /etc/passwd
sudo lsof /var/lib/mysql/ibdata1

Bir dizin altındaki tüm açık dosyaları görmek için +D kullanılır:

sudo lsof +D /var/log/nginx/
sudo lsof +D /home/ahmet/

Dikkat: +D recursive çalışır ve büyük dizinlerde yavaş olabilir. Hızlı bir alternatif olarak +d (küçük harf) sadece belirtilen dizinin kendisindeki açık dosyaları gösterir, alt dizinlere inmez.

Silinmiş Ama Hala Açık Tutulan Dosyalar

Bu konu özellikle disk dolduğunda çok kritik hale gelir. Bir dosyayı sildiniz ama disk alanı boşalmadı. Bunun nedeni genellikle bir sürecin o dosyayı hala açık tutmasıdır. Linux’ta dosyayı silerseniz inode serbest kalmaz, süreç dosyayı kapatana kadar disk alanı geri kazanılmaz.

sudo lsof | grep deleted

Bu komutu bir sistemde çalıştırdığımda 8 GB’lık bir log dosyasının silinmiş ama Java tabanlı bir uygulama tarafından hala tutulduğunu gördüm. Uygulama yeniden başlatılınca disk anında boşaldı. Ama daha temiz bir çözüm şudur: Uygulamayı yeniden başlatmadan önce dosya tanımlayıcısını truncate edebilirsiniz:

# Önce PID ve FD numarasını bulun
sudo lsof | grep deleted | grep java

# Çıktıdan PID ve FD numarasını alın, sonra
> /proc/[PID]/fd/[FD]

Bu yöntem servis kesintisi olmadan disk alanını geri kazandırır. Üretim ortamlarında çok değerli bir tekniktir.

Belirli Bir Sürece Ait Açık Dosyalar

PID bildiğinizde -p ile o sürece ait tüm açık dosyaları, soketleri ve kütüphaneleri görebilirsiniz:

sudo lsof -p 1234

# Birden fazla PID için virgülle ayırın
sudo lsof -p 1234,5678

Bir sürecin PID’ini bilmiyorsanız önce bulun:

# Servis adından PID bulma
pidof nginx
pgrep mysql

# Sonra lsof ile analiz
sudo lsof -p $(pidof nginx)

Bu yöntemi özellikle uygulama davranışını anlamak için kullanıyorum. Yeni deploy ettiğiniz bir servis beklenmedik davranış gösteriyorsa, hangi dosyaları açtığını görmek size çok şey anlatır. Doğru config dosyasını mı okuyor? Beklenen soketleri mi dinliyor? Gereksiz yere büyük dosyaları mı açık tutuyor?

Komut Adına Göre Filtreleme

-c parametresi ile süreç adına göre filtreleme yapabilirsiniz:

sudo lsof -c nginx
sudo lsof -c python
sudo lsof -c java

Birden fazla komut için:

sudo lsof -c nginx -c apache2

Bu parametre kısmi eşleşme yapar. Yani lsof -c py dediğinizde python, python3, pypy gibi tüm süreçleri getirir. Çok geniş bir çıktı almak istemiyorsanız tam isim kullanın.

lsof ile Gerçek Dünya Senaryoları

Senaryo 1: Hangi Süreç Bu Dosyayı Kilitlemiş?

Bir veritabanı yedek betiği yazıyorsunuz ve hedef dosyaya erişemiyorsunuz:

sudo lsof /var/backups/db_backup.sql.gz

# Eğer çıktı geldiyse, o dosyayı tutan süreçleri görürsünüz
# Sonlandırmak istiyorsanız
sudo lsof -t /var/backups/db_backup.sql.gz | xargs kill -9

-t parametresi sadece PID’leri döner, bu yüzden xargs ile doğrudan komut çalıştırabilirsiniz.

Senaryo 2: Güvenlik Olayı Analizi

Sistemde şüpheli bir süreç var ve ne yaptığını anlamak istiyorsunuz:

# Şüpheli süreci bulun
ps aux | grep suspicious_process

# Açık dosyalar, ağ bağlantıları ve her şeyi görün
sudo lsof -p [PID]

# Sadece ağ bağlantılarına bakın
sudo lsof -i -p [PID]

# Çalıştırılabilir dosyanın nerede olduğunu görün (txt tipi)
sudo lsof -p [PID] | grep txt

Senaryo 3: Uygulama Kaç Dosya Tanımlayıcı Kullanıyor

Özellikle Java veya Node.js uygulamalarında “Too many open files” hatası sık karşılaşılan bir sorundur. Önce mevcut durumu görün:

# Toplam açık dosya sayısı
sudo lsof -p [PID] | wc -l

# Sistem genelinde açık dosya limiti
cat /proc/sys/fs/file-max

# Mevcut kullanım
cat /proc/sys/fs/file-nr

Eğer bir uygulama sürekli dosya tanımlayıcı sızdırıyorsa (file descriptor leak), bunu lsof çıktısını periyodik olarak kayıt altına alarak tespit edebilirsiniz:

# Her 30 saniyede bir kayıt al
while true; do
    echo "=== $(date) ===" >> /tmp/lsof_monitor.log
    sudo lsof -p $(pidof your_app) | wc -l >> /tmp/lsof_monitor.log
    sleep 30
done

Sayı sürekli artıyorsa leak var demektir.

lsof ile Ağ Durumunu İzleme

netstat ve ss komutları devre dışı bırakılmış sistemlerde veya daha detaylı bilgi istediğinizde lsof tek başına ağ analizini yapabilir:

# Belirli bir uzak host'a yapılan tüm bağlantılar
sudo lsof -i @192.168.1.100

# Belirli bir uzak host ve porta bağlantılar
sudo lsof -i @192.168.1.100:3306

# ESTABLISHED durumdaki TCP bağlantıları
sudo lsof -i TCP -s TCP:ESTABLISHED

# LISTEN durumundaki tüm portlar
sudo lsof -i TCP -s TCP:LISTEN -P -n

Son komut özellikle “hangi servisler hangi portları dinliyor?” sorusunu çok temiz bir şekilde yanıtlar. Bunu netstat -tlnp yerine kullanmayı tercih ediyorum çünkü PID ve süreç bilgisi daha net görünür.

Faydalı Parametre Kombinasyonları

Tek başlarına önemli olan bazı parametreler:

  • -n: Hostname çözümleme yapma, IP adresini olduğu gibi göster
  • -P: Port numaralarını servis adına dönüştürme
  • -t: Sadece PID’leri göster (script’lerde çok kullanışlı)
  • -l: Kullanıcı adı yerine UID göster
  • -r [saniye]: Belirtilen aralıkla sürekli tekrar çalıştır
  • -a: Birden fazla filtre kullanırken AND mantığı uygula (varsayılan OR’dur)

-a parametresi önemli bir noktadır. Şöyle ki, lsof -u nginx -i TCP yazdığınızda “nginx kullanıcısının TCP bağlantıları veya tüm TCP bağlantıları” değil, “nginx kullanıcısının TCP bağlantıları” istiyorsanız -a eklemeniz gerekir:

# nginx kullanıcısının TCP bağlantıları (AND mantığı)
sudo lsof -u nginx -a -i TCP

# Periyodik izleme, her 5 saniyede yenile
sudo lsof -i TCP -s TCP:LISTEN -P -n -r 5

-r parametresi ile watch komutuna benzer bir davranış elde edersiniz ama lsof‘a özgü filtrelerle birlikte çok daha kullanışlıdır.

Çıktıyı Script’lerde Kullanmak

lsof çıktısını işlemek için birkaç pratik yöntem:

# Bir porta bağlı tüm süreçleri sonlandır
sudo kill $(sudo lsof -t -i :8080)

# Silinmiş dosyaları tutan süreçleri yeniden başlat
sudo lsof | grep deleted | awk '{print $2}' | sort -u | while read pid; do
    echo "Restarting process: $pid ($(cat /proc/$pid/comm 2>/dev/null))"
done

# Belirli bir dizindeki dosyaları tutan süreçlerin özeti
sudo lsof +D /var/log | awk 'NR>1 {print $1, $2, $3}' | sort | uniq -c | sort -rn

lsof Performansı Hakkında

Büyük sistemlerde lsof yavaş çalışabilir. Bunu hızlandırmak için:

  • -n ve -P ekleyin, DNS ve servis adı çözümlemesi zaman alır
  • Mümkün olduğunca filtre kullanın, tüm sistemi taramaktan kaçının
  • +D yerine +d tercih edin büyük dizinlerde
  • Çıktıyı başka araçlarla işleyecekseniz önce bir dosyaya kaydedin
# Hızlı ağ bağlantısı kontrolü
sudo lsof -nP -i TCP 2>/dev/null

# Önce dosyaya al, sonra analiz et
sudo lsof -nP > /tmp/lsof_snapshot.txt
grep "LISTEN" /tmp/lsof_snapshot.txt
grep "ESTABLISHED" /tmp/lsof_snapshot.txt

Özellikle /tmp/lsof_snapshot.txt yaklaşımı, olayları karşılaştırmak için çok değerlidir. Sabah aldığınız snapshot ile akşam aldığınızı diff ile karşılaştırabilirsiniz.

Sonuç

lsof, sistemin o anki durumunu anlamamızı sağlayan bir fotoğraf makinesi gibidir. Disk sorunları, port çakışmaları, güvenlik analizi, uygulama hata ayıklama… Bunların hepsinde lsof size somut, aksiyon alınabilir bilgi verir.

Şunu özellikle vurgulamak istiyorum: lsof‘un gücü tek başına değil, diğer araçlarla kombinasyonunda ortaya çıkar. grep, awk, xargs ve kill ile birlikte kullandığınızda olayları çözmek çok hızlanır. Zaman içinde kendi lsof kombinasyonlarınızı keşfedeceksiniz ve bunların büyük bir kısmını alias olarak tanımlamanızı öneririm.

Son olarak şunu da söylemeliyim: lsof root yetkileriyle çalıştırıldığında sistem genelindeki tüm açık dosyaları gösterir, ancak normal kullanıcı olarak çalıştırırsanız sadece o kullanıcıya ait süreçleri görürsünüz. Üretim sistemlerinde bunu göz önünde bulundurun ve çıktıda “Permission denied” mesajı görürseniz şaşırmayın, sadece sudo ile çalıştırmanız yeterlidir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir