stat Komutu ile Dosya Detaylarını Görüntüleme

Dosyalarla çalışırken çoğu zaman ls -l komutuyla yetinip geçeriz. Oysa bir dosya hakkında gerçekten derin bilgiye ihtiyaç duyduğunuzda, inode numarasından erişim zamanlarına, blok boyutundan dosya türüne kadar her şeyi tek seferde görmek istediğinizde, stat komutu tam da bu iş için tasarlanmıştır. Sistem yöneticileri için adeta gizli bir silah olan bu araç, dosya sistemi sorunlarını debuglamaktan güvenlik denetimlerine kadar pek çok senaryoda hayat kurtarır.

stat Komutu Nedir?

stat komutu, bir dosya veya dizin hakkında dosya sisteminin tuttuğu tüm metadata bilgilerini ekrana döker. Bu bilgiler arasında dosya boyutu, izinler, sahiplik, erişim zamanları ve inode bilgileri yer alır. Komut, Linux üzerinde GNU coreutils paketinin bir parçası olarak gelir ve neredeyse tüm dağıtımlarda önceden yüklü olarak bulunur.

ls komutundan temel farkı şudur: ls size dosyayı listeler, stat ise dosya hakkındaki her şeyi söyler. Bir dosyaya en son ne zaman erişildi, içeriği en son ne zaman değiştirildi, metadata ne zaman güncellendi, hangi aygıtta hangi blok numarasında tutuluyor… Bunların hepsine stat ile ulaşabilirsiniz.

Temel Kullanım

En basit haliyle stat komutunu bir dosya adıyla çalıştırmanız yeterlidir:

stat dosya.txt

Bu komutun çıktısı şöyle görünür:

  File: dosya.txt
  Size: 4096            Blocks: 8          IO Block: 4096   regular file
Device: 802h/2050d      Inode: 1835012     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/   ahmet)   Gid: ( 1000/   ahmet)
Access: 2024-01-15 14:32:10.123456789 +0300
Modify: 2024-01-14 09:15:44.987654321 +0300
Change: 2024-01-14 09:15:44.987654321 +0300
 Birth: 2024-01-10 08:00:00.000000000 +0300

Bu çıktıyı parça parça inceleyelim çünkü her satır ayrı bir anlam taşıyor.

Çıktıdaki Alanların Anlamı

File: Dosyanın adını gösterir. Eğer sembolik link ise hedef de parantez içinde belirtilir.

Size: Dosyanın bayt cinsinden boyutu. Dizinler için bu değer genellikle 4096 bayttır, çünkü dizin girişleri de dosya sisteminde bir blok kaplar.

Blocks: Dosyanın diskte kapladığı 512 baytlık blok sayısı. Bu değer bazen boyutla orantısız görünebilir çünkü dosya sistemi blok hizalaması yapar.

IO Block: Dosya sisteminin I/O işlemleri için kullandığı blok boyutu. Genellikle 4096 bayttır.

Device: Dosyanın bulunduğu aygıtın hex ve decimal gösterimi. 802h değeri 8. major (sda) ve 2. minor (sda2) aygıtı temsil eder.

Inode: Dosyanın inode numarası. Dosya sistemi içinde dosyayı benzersiz olarak tanımlayan sayıdır. Hard link’lerin aynı inode’u paylaştığını unutmayın.

Links: Dosyaya işaret eden hard link sayısı. Normal bir dosya için bu değer 1’dir. Eğer 2 veya üzeriyse, dosyanın başka hard link’leri var demektir.

Access (izinler): İki formatta gösterilir. Oktal format (0644) ve sembolik format (-rw-r–r–). Uid ve Gid ise sahip kullanıcı ve grup bilgisini hem sayısal hem de isim olarak verir.

Access (zaman): Dosyaya en son erişildiği zaman (atime). Bir dosyayı sadece okumak bile bu değeri günceller, ancak bazı dosya sistemleri performans için noatime seçeneğiyle mount edilir.

Modify: Dosyanın içeriğinin son değiştirilme zamanı (mtime). Bu değer yalnızca dosya içeriği yazıldığında güncellenir.

Change: Dosyanın metadata’sının son değiştirilme zamanı (ctime). İzin değiştirme, sahip değiştirme veya dosyayı yeniden adlandırma gibi işlemler bu değeri günceller. İçerik değişikliği de ctime’ı günceller.

Birth: Dosyanın oluşturulma zamanı (crtime). Bu alan bazı dosya sistemlerinde desteklenmeyebilir ve - olarak görünebilir.

Dizinlerde stat Kullanımı

stat komutunu dizinlerde de kullanabilirsiniz:

stat /var/log
  File: /var/log
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: 802h/2050d      Inode: 131073      Links: 14
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-01-15 14:00:01.123456789 +0300
Modify: 2024-01-15 13:58:22.987654321 +0300
Change: 2024-01-15 13:58:22.987654321 +0300
 Birth: -

Burada dikkat edilmesi gereken nokta Links değeridir. Dizinler için bu değer, alt dizin sayısı artı 2’ye eşittir. 2 değerinin kaynağı şudur: biri dizinin kendisini gösteren . (nokta), diğeri ise üst dizinden gelen link. Bu yüzden /var/log için Links: 14 görüyorsak, bu dizinde 12 alt dizin var demektir.

Sembolik Linklerde stat Kullanımı

Sembolik linklerle çalışırken stat komutu linkin kendisi hakkında bilgi verir, hedef dosya hakkında değil:

ln -s /etc/hosts /tmp/hosts_link
stat /tmp/hosts_link
  File: /tmp/hosts_link -> /etc/hosts
  Size: 10              Blocks: 0          IO Block: 4096   symbolic link
Device: 802h/2050d      Inode: 2097153     Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/   ahmet)   Gid: ( 1000/   ahmet)

Eğer linkin hedefi hakkında bilgi almak istiyorsanız -L parametresini kullanın:

stat -L /tmp/hosts_link

Bu komut artık /etc/hosts dosyasının bilgilerini gösterecektir.

Önemli Parametreler

-L, –dereference: Sembolik linkleri takip eder, hedef dosyanın bilgilerini gösterir.

-f, –file-system: Dosya sistemi hakkında bilgi verir, dosya hakkında değil.

-c, –format: Özel format belirleyerek sadece istediğiniz alanları görüntüler.

-t, –terse: Çıktıyı tek satırda, kompakt biçimde gösterir. Script yazarken oldukça kullanışlıdır.

–printf: -c gibi format belirler ama otomatik newline eklemez, n ile kendiniz eklemeniz gerekir.

Dosya Sistemi Bilgilerini Görüntüleme

-f parametresiyle stat bir dosyanın bulunduğu dosya sistemi hakkında bilgi verir:

stat -f /home/ahmet/belgeler
  File: "/home/ahmet/belgeler"
    ID: 1234abcd5678ef00 Namelen: 255     Type: ext2/ext3
Block size: 4096       Fundamental block size: 4096
Blocks: Total: 52428800   Free: 31457280   Available: 28311552
Inodes: Total: 13107200   Free: 12845678

Bu çıktı size disk kullanımı, boş alan ve kullanılabilir inode sayısı hakkında özet bilgi verir. df komutuna benzer ama daha düşük seviyeli veriler sunar.

Özel Format Kullanımı

stat komutunun en güçlü özelliklerinden biri özel format desteğidir. Script yazarken sadece ihtiyacınız olan bilgiyi çekmek için bu özelliği sık sık kullanacaksınız.

Format belirteclerinin başlıcaları:

%n: Dosya adı %s: Dosya boyutu (bayt) %b: Ayrılan blok sayısı %f: Ham izin bilgisi (hex) %U: Sahip kullanıcı adı %G: Sahip grup adı %i: Inode numarası %h: Hard link sayısı %a: Erişim izinleri (oktal) %A: Sembolik erişim izinleri (örn: -rw-r–r–) %x: Son erişim zamanı %y: Son değiştirilme zamanı %z: Son metadata değişikliği zamanı %w: Oluşturulma zamanı %F: Dosya türü %d: Aygıt numarası (decimal) %t: Major aygıt numarası (hex) %T: Minor aygıt numarası (hex)

Örnek kullanım:

stat -c "%n: %s bayt, İzinler: %A, Sahip: %U" /etc/passwd

Çıktı:

/etc/passwd: 2847 bayt, İzinler: -rw-r--r--, Sahip: root

Birden fazla dosya için aynı anda kullanmak da mümkündür:

stat -c "%n | %s | %y" /var/log/*.log

Gerçek Dünya Senaryoları

Senaryo 1: Log Rotasyon Sorunlarını Tespit Etme

Bir üretim sunucusunda log dosyalarının düzgün rotate edilip edilmediğini kontrol etmeniz gerekiyor. Sadece boyuta bakmak yeterli değil, son değiştirilme zamanına da bakmanız lazım:

for log in /var/log/*.log; do
    echo "=== $log ==="
    stat -c "Boyut: %s bayt | Son değişiklik: %y | Hard linkler: %h" "$log"
done

Bu script size her log dosyasının boyutunu ve son değiştirilme zamanını gösterir. Eğer bir log dosyasının mtime’ı çok eskiyse, uygulamanın o dosyaya yazmayı durdurduğunu veya log rotation’ın başarısız olduğunu anlayabilirsiniz.

Senaryo 2: Hard Link Tespiti

Sistem üzerinde yanlışlıkla hard link oluşturulup oluşturulmadığını ya da bir dosyanın birden fazla hard link’e sahip olup olmadığını kontrol etmek:

find /home -type f -links +1 -exec stat -c "%i %h %n" {} ; | sort -n

Bu komut, birden fazla hard link’e sahip tüm dosyaları inode numaralarıyla birlikte listeler. Aynı inode numarasına sahip birden fazla satır görüyorsanız, bunlar aynı dosyanın farklı isimlerle erişilen hard link’leridir.

Senaryo 3: Güvenlik Denetimi için İzin Kontrolü

Kritik sistem dosyalarının izinlerinin değişip değişmediğini kontrol etmek, güvenlik rutinlerinin önemli bir parçasıdır. Aşağıdaki script, kritik dosyaların izinlerini ve sahipliğini kaydeder:

#!/bin/bash
KRITIK_DOSYALAR="/etc/passwd /etc/shadow /etc/sudoers /etc/ssh/sshd_config"

for dosya in $KRITIK_DOSYALAR; do
    if [ -f "$dosya" ]; then
        stat -c "%n | İzin: %a | Sahip: %U:%G | ctime: %z" "$dosya"
    fi
done

Bu çıktıyı bir referans dosyasına kaydedip, düzenli aralıklarla karşılaştırarak izin değişikliklerini tespit edebilirsiniz.

Senaryo 4: Dosya Sistemi İnode Tükenmesi

Sunucunuzda “No space left on device” hatası alıyorsunuz ama df ile baktığınızda disk dolu görünmüyor. Bu klasik inode tükenmesi sorunudur:

stat -f /var

Çıktıdaki Inodes: Free: değerine bakın. Eğer bu değer 0’a yakınsa, sorun disk alanı değil inode tükenmiş demektir. Küçük dosya üreten uygulamalar (özellikle mail spool veya bazı cache mekanizmaları) inode’ları hızla tüketebilir.

Senaryo 5: Deployment Doğrulama

Bir uygulama deploy ettikten sonra dosyaların doğru yere kopyalanıp kopyalanmadığını ve zamanlarının güncel olup olmadığını doğrulamak:

#!/bin/bash
DEPLOY_ZAMANI=$(date +%s)
APP_DOSYALARI="/var/www/html /etc/nginx/nginx.conf /etc/nginx/conf.d/app.conf"

for dosya in $APP_DOSYALARI; do
    MTIME=$(stat -c "%Y" "$dosya" 2>/dev/null)
    if [ -n "$MTIME" ]; then
        FARK=$((DEPLOY_ZAMANI - MTIME))
        if [ $FARK -lt 300 ]; then
            echo "OK: $dosya (${FARK}s önce güncellendi)"
        else
            echo "UYARI: $dosya son 5 dakikada güncellenmedi!"
        fi
    else
        echo "HATA: $dosya bulunamadı!"
    fi
done

Senaryo 6: Backup Doğrulama

Yedekleme işleminden sonra kaynak ve hedef dosyaların boyutlarını karşılaştırmak:

KAYNAK="/data/veritabani/db.sql"
HEDEF="/backup/db_backup.sql"

KAYNAK_BOYUT=$(stat -c "%s" "$KAYNAK")
HEDEF_BOYUT=$(stat -c "%s" "$HEDEF")

if [ "$KAYNAK_BOYUT" -eq "$HEDEF_BOYUT" ]; then
    echo "Yedekleme başarılı: $HEDEF_BOYUT bayt"
else
    echo "HATA: Boyut uyuşmazlığı! Kaynak: $KAYNAK_BOYUT, Hedef: $HEDEF_BOYUT"
fi

Zaman Değerlerini Epoch Formatında Almak

Zaman karşılaştırmaları yaparken insan okunabilir format yerine Unix epoch (saniye cinsinden) formatını kullanmak çok daha pratiktir:

# Modify time'ı epoch olarak al
stat -c "%Y" /var/log/syslog

# Access time'ı epoch olarak al  
stat -c "%X" /tmp/gecici_dosya

# Change time'ı epoch olarak al
stat -c "%Z" /etc/passwd

Büyük harf format belirteçleri (%X, %Y, %Z, %W) epoch değerini verirken, küçük harf karşılıkları (%x, %y, %z, %w`) insan okunabilir formatta verir.

stat vs ls Karşılaştırması

Pek çok sysadmin ls -l ile yetinir, ama ikisi arasındaki farkları bilmek önemlidir.

ls -l ile görülen bilgiler: izinler, link sayısı, sahip, grup, boyut, tarih ve dosya adı.

stat ile ek olarak görülen bilgiler: inode numarası, blok boyutu, aygıt numarası, nanosaniye hassasiyetinde zaman bilgisi, ayrı ayrı atime/mtime/ctime değerleri ve dosya sistemi blok bilgileri.

Script yazarken özellikle stat -c formatı, ls çıktısını parse etmeye çalışmaktan çok daha güvenilir ve taşınabilirdir. ls çıktısı farklı sistemlerde veya dil ayarlarında farklı görünebilir, oysa stat -c tutarlı çıktı üretir.

Terse Mod ile Hızlı Çıktı

Script’lerde tek satırlık özet bilgiye ihtiyaç duyduğunuzda -t parametresi kullanışlıdır:

stat -t /etc/hosts

Çıktı tek satırda şöyle görünür:

/etc/hosts 221 8 81a4 0 0 802 1835012 1 0 0 1705320730 1705320730 1705320730 1705320730 4096

Bu format şöyle okunur: dosya_adı boyut bloklar izin(hex) uid gid aygıt inode linkler major minor atime mtime ctime birthtime blok_boyutu.

Bu çıktıyı awk ile kolayca işleyebilirsiniz:

stat -t /etc/hosts | awk '{print "Boyut: "$2" Inode: "$8" İzin: "$4}'

Birden Fazla Dosyayı Toplu İşleme

stat komutu birden fazla dosya adı alabilir:

stat /etc/passwd /etc/group /etc/hosts

Ya da glob pattern kullanabilirsiniz:

stat /var/log/*.log

Büyük dizinlerde her dosyanın sadece boyutunu listeleyen bir one-liner:

stat -c "%st%n" /usr/bin/* | sort -rn | head -20

Bu komut /usr/bin altındaki en büyük 20 dosyayı boyutlarıyla birlikte listeler.

macOS’ta stat Kullanımı

macOS’ta stat komutu BSD versiyonudur ve GNU versiyonundan farklı parametreler kullanır. macOS’ta -f parametresi format belirtmek için kullanılır (GNU’daki -c yerine):

# macOS'ta
stat -f "%z bayt, İzin: %Mp%Lp, Sahip: %Su" /etc/hosts

# GNU/Linux'ta karşılığı
stat -c "%s bayt, İzin: %a, Sahip: %U" /etc/hosts

Platform bağımsız script yazıyorsanız bunu göz önünde bulundurmanız gerekir. macOS üzerinde GNU coreutils’i brew install coreutils ile kurarak gstat adıyla GNU versiyonunu kullanabilirsiniz.

Pratik İpuçları

Günlük sysadmin hayatında stat komutunu daha verimli kullanmak için bazı pratik notlar:

  • Bir dosyanın son değiştirilme zamanına hızlıca bakmak için stat -c "%y %n" yeterlidir, tam çıktıyı beklemeden.
  • Script’lerde dosya varlığını kontrol etmek için stat yerine [ -f dosya ] kullanmak daha hızlıdır, ama boyut veya zaman bilgisi gerekiyorsa stat kaçınılmazdır.
  • ctime‘ın değiştirilme zamanı olmadığını, metadata değişiklik zamanı olduğunu unutmayın. “c” harfi “change” içindir, “create” değil.
  • Inode numarası değişmişse, dosya yerinde düzenlenmemiş demektir. Birçok metin editörü ve deployment aracı dosyayı silip yeniden yazar, bu durumda inode numarası değişir.
  • noatime mount seçeneğiyle bağlanmış dosya sistemlerinde atime güncellemesi yapılmaz, bu yüzden atime değeri her zaman güvenilir değildir.

Sonuç

stat komutu, dosya sistemiyle derin bir diyalog kurmanızı sağlayan güçlü bir araçtır. ls size bir dosyanın yüzeyini gösterirken, stat o dosyayla ilgili dosya sisteminin bildiği her şeyi ortaya döker. Inode sorunlarından güvenlik denetimlerine, backup doğrulamadan deployment kontrolüne kadar pek çok senaryoda bu komutun gerçek değerini keşfedeceksiniz.

Özellikle stat -c ile özel format kullanımını öğrenmek, shell script yazarken hayatınızı büyük ölçüde kolaylaştırır. ls çıktısını kırıp parse etmeye çalışmak yerine, doğrudan ihtiyacınız olan alanı güvenilir bir şekilde çekebilirsiniz. Bir dahaki sefere bir dosya hakkında “acaba bu dosya ne zaman değişti, kim sahip, inode’u nedir” diye merak ettiğinizde, stat komutunu açın ve tek seferde tüm cevapları alın.

Yorum yapın