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
statyerine[ -f dosya ]kullanmak daha hızlıdır, ama boyut veya zaman bilgisi gerekiyorsastatkaçı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.
noatimemount 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.