Linux’ta Hard Link Tespiti ve Yönetimi: Dosya Referanslarını Takip Etmek
Dosya sisteminde bir şeylerin “garip” göründüğü o anı muhtemelen hepiniz yaşamışsınızdır. rm ile sildiğinizi sandığınız bir dosya hala yer kaplıyor, ya da iki farklı dizinde aynı içerikli dosyalar var ama diff hiçbir fark bulmuyor. Büyük ihtimalle hard link meselesinin içindesinizdir. Bu yazıda hard link’lerin ne olduğunu değil (onu zaten biliyorsunuz), bunları nasıl tespit edeceğinizi ve yöneteceğinizi ele alacağız.
Hard Link Nedir, Neden Önemlidir?
Hızlıca üzerinden geçelim: Linux’ta bir dosya oluşturduğunuzda aslında bir inode oluşturulur ve dizin girişi bu inode’u işaret eder. Hard link oluşturduğunuzda yeni bir inode yaratmazsınız, sadece aynı inode’u işaret eden ikinci (ya da üçüncü, dördüncü…) bir dizin girişi eklersiniz. Bu yüzden hard link’li dosyalar gerçek anlamda “kopya” değildir; aynı veridir, sadece farklı isimlerle erişilmektedir.
Sorun şu ki bu yapı; depolama hesaplarını yanıltır, yedekleme sistemlerini karıştırır ve bazen güvenlik açıklarına zemin hazırlar. Bir sysadmin olarak bu yapıları görebilmek ve kontrol altında tutabilmek kritik bir beceridir.
stat ile İşe Başlamak
Hard link tespitinin temel aracı stat komutudur. Bir dosyanın kaç hard link’e sahip olduğunu anlamanın en doğrudan yolu budur.
stat /etc/passwd
Çıktıda şuna benzer bir satır göreceksiniz:
Links: 1
Eğer bu sayı 1’den büyükse, o inode’u birden fazla dizin girişinin paylaştığı anlamına gelir. Basit ama kritik bir bilgi.
# Sadece link sayısını almak için:
stat --format="%h" /etc/passwd
# İnode numarasını da görmek için:
stat --format="%i %h %n" /etc/passwd
İnode numarası burada çok önemlidir. Aynı inode numarasına sahip iki farklı dosya, kesinlikle hard link ilişkisi içindedir. Bunu aklınızın bir köşesine yazın.
find ile Sistem Genelinde Hard Link Tespiti
stat tek dosya için kullanışlıdır ama sistem genelinde hard link avı yapacaksanız find komutuna ihtiyacınız var.
Belirli Bir Dosyanın Tüm Hard Link’lerini Bulmak
Diyelim ki /var/log/uygulama.log dosyasının başka nerede referanslandığını öğrenmek istiyorsunuz. Önce inode numarasını alın, sonra o inode ile tüm sistemi tarayın:
# İnode numarasını öğren
INODE=$(stat --format="%i" /var/log/uygulama.log)
# Bu inode'u kullanan tüm dosyaları bul
find / -inum $INODE 2>/dev/null
Bu yöntem özellikle “sildim ama neden hala yer kaplıyor?” sorusunun cevabını bulmak için birebir. Bir dosyayı sildiğinizde aslında sadece o dizin girişini siliyorsunuz. Inode’a bağlı başka dizin girişleri varsa, veri hala orada duruyor.
Birden Fazla Hard Link’e Sahip Tüm Dosyaları Bulmak
Bir dizin altındaki tüm hard link’li dosyaları listelemek için:
find /home -type f -links +1 -ls 2>/dev/null
-links +1 parametresi “link sayısı 1’den büyük olan” anlamına geliyor. -ls ise inode numarasını da içeren detaylı çıktı veriyor; hangi dosyaların birbirine bağlı olduğunu görmenize yardımcı oluyor.
Çıktıyı inode numarasına göre sıralarsanız, hangi dosyaların aynı inode’u paylaştığını çok daha kolay görebilirsiniz:
find /home -type f -links +1 -printf "%i %n %pn" 2>/dev/null | sort -n
Bu komutun çıktısını yorumlamak şöyle: aynı inode numarasıyla başlayan satırlar aynı fiziksel veriyi paylaşıyor demektir.
ls -i ile Hızlı İnode Kontrolü
Bir dizinde hangi dosyaların hard link ilişkisi içinde olduğunu anlamanın en hızlı yolu ls -i kullanmaktır:
ls -li /etc/
Sol taraftaki sayı inode numaralarıdır. Aynı inode numarasına sahip dosyaları gördüğünüzde, bunlar aynı veriyi paylaşıyor demektir. Özellikle /etc gibi dizinlerde bu kontrol, konfigürasyon dosyalarının beklenmedik şekilde paylaşılıp paylaşılmadığını anlamak için işe yarar.
Gerçek Dünya Senaryosu 1: Yedekleme Sistemi ve Hard Link Tuzağı
Rsync tabanlı artımlı yedekleme sistemleri hard link’leri yoğun kullanır. --link-dest parametresiyle rsync, değişmeyen dosyalar için kopyalama yapmak yerine önceki yedekten hard link oluşturur. Bu depolamadan büyük tasarruf sağlar ama kontrolden çıkarsa karmaşıklık yaratır.
# Yedekleme dizinindeki hard link yapısını analiz et
find /backup/ -type f -links +1 -printf "%it%nt%st%pn" 2>/dev/null
| sort -k1,1n -k4,4
| awk '{inode=$1; links=$2; size=$3; path=$4}
inode != prev_inode {prev_inode=inode; print "---"; print $0; next}
{print $0}'
Bu script aynı inode’u paylaşan dosyaları gruplandırarak gösterir. Yedekleme sisteminin beklediğiniz şekilde hard link kullandığını doğrulamak için idealdir.
Bir keresinde yedekleme scriptindeki bir bug yüzünden 6 aylık yedekler gerçekten bağımsız kopya olarak oluşturulmuştu; hard link yerine gerçek kopya. Disk dolmuş, kimse fark etmemişti. Yukarıdaki komutla durumu anlayıp, rsync’i --link-dest ile yeniden çalıştırarak sorunu çözdük. Ama önce var olan durumu anlamak gerekmişti, işte bunun için bu araçlar lazım.
Hard Link Sayısını Script ile Raporlamak
Sistem genelinde hard link kullanımını raporlayan basit ama işlevsel bir script:
#!/bin/bash
# hardlink_report.sh
# Belirtilen dizinde hard link gruplarını raporlar
TARGET_DIR="${1:-/home}"
TEMP_FILE=$(mktemp)
echo "Hard Link Raporu: $TARGET_DIR"
echo "Tarih: $(date)"
echo "================================"
# İnode numarası 1'den fazla link içeren dosyaları bul
find "$TARGET_DIR" -type f -links +1 -printf "%it%pn" 2>/dev/null
| sort > "$TEMP_FILE"
# Aynı inode'u paylaşan grupları işle
current_inode=""
group_count=0
while IFS=$'t' read -r inode path; do
if [ "$inode" != "$current_inode" ]; then
if [ -n "$current_inode" ]; then
echo ""
fi
echo "Inode $inode:"
current_inode="$inode"
group_count=$((group_count + 1))
fi
echo " -> $path"
done < "$TEMP_FILE"
echo ""
echo "Toplam hard link grubu: $group_count"
rm -f "$TEMP_FILE"
Bu scripti cron’a koyup haftalık çalıştırabilirsiniz. Beklenmedik hard link grupları oluşmuşsa erken fark edersiniz.
Gerçek Dünya Senaryosu 2: Güvenlik Açısından Hard Link Kontrolü
Hard link’ler güvenlik bağlamında da önem taşır. Klasik bir senaryo: setuid bit’li bir binary’ye hard link oluşturup ayrıcalık yükseltme denemesi. Modern kerneller bu tür saldırıları büyük ölçüde engellemiş olsa da, yine de sisteminizde setuid dosyalarına hard link var mı diye kontrol etmek iyi bir alışkanlıktır.
# Setuid bit'li ve birden fazla hard link'e sahip dosyaları bul
find / -type f -perm /4000 -links +1 -ls 2>/dev/null
Ayrıca /proc/sys/fs/protected_hardlinks ayarını kontrol edin:
cat /proc/sys/fs/protected_hardlinks
Bu değer 1 ise (modern sistemlerde varsayılan olarak 1 olmalı), kullanıcılar sahip olmadıkları dosyalara hard link oluşturamaz. Eğer 0 görüyorsanız:
# Kalıcı hale getirmek için:
echo "fs.protected_hardlinks = 1" >> /etc/sysctl.conf
sysctl -p
Bu kontrolü güvenlik taramalarınızın bir parçası haline getirin.
hardlink Aracı: Duplicate Dosyaları Hard Link’e Çevirmek
find ile tespit yapıyorduk, peki ya aktif yönetim? Burada hardlink komutu devreye giriyor. Bu araç, aynı içeriğe sahip dosyaları bulup bunları hard link’e dönüştürerek disk alanı tasarrufu sağlar.
Önce kuralım:
# Debian/Ubuntu
apt-get install hardlink
# RHEL/CentOS/Rocky
dnf install hardlink
Temel kullanım:
# Bir dizindeki duplicate dosyaları tespit et (dry-run)
hardlink -t -v /opt/uygulamalar/
# Gerçekten uygula
hardlink -v /opt/uygulamalar/
-t: Test modu, gerçekte işlem yapmaz, ne kadar alan kazanılacağını gösterir. -v: Verbose, hangi dosyaların link’leneceğini listeler. -n: Nul byte içeren dosyaları dikkate alma. -f: Farklı zaman damgalarına sahip dosyaları da işle. -c: İçerik yerine sadece boyut ve zaman damgasını karşılaştır (daha hızlı ama daha az güvenilir).
Dikkat: hardlink komutu farklı Linux dağıtımlarında iki ayrı implementasyon olarak geliyor. RHEL ekosistemindeki hardlink ile Debian’daki hardlink biraz farklı davranışlar sergileyebilir. Kullandığınız dağıtımdaki man hardlink sayfasını okuyun.
rdfind ve fdupes Alternatif Yaklaşımlar
hardlink aracının yanı sıra, duplicate tespiti için rdfind ve fdupes da popüler araçlardır. Her birinin farklı güçlü yanları var.
fdupes ile önce analiz, sonra hard link:
# Duplicate dosyaları listele
fdupes -r /opt/uygulamalar/
# Hard link oluşturarak duplicate'leri birleştir
fdupes -r -L /opt/uygulamalar/
rdfind daha agresif çalışır ve büyük dizinlerde hız avantajı sağlar:
# Sadece raporla
rdfind -dryrun true /opt/uygulamalar/
# Hard link oluştur
rdfind -makehardlinks true /opt/uygulamalar/
Büyük bir uygulama sunucusunda /opt altında yüzlerce Python virtual environment olduğunda, bu araçlar ciddi disk tasarrufu sağlayabilir. Aynı Python version’ına ait standard library dosyaları her venv’de kopyalanmış halde duruyorsa, hard link’e dönüştürerek GB’larca alan kazanabilirsiniz.
Hard Link Kıracak Operasyonlar
Hard link yönetimi yaparken şunu bilmek kritik: bazı operasyonlar hard link’i “kırar” ve dosyayı bağımsız bir kopya haline getirir. Bu operasyonlar şunlardır:
Copy-on-Write (CoW): Bazı araçlar dosyayı açıp değiştirdiğinde, kernel yeni bir inode oluşturabilir. Bu davranış dosya sistemine ve araca göre değişir.
cp --remove-destination: Hard link olan bir dosyayı bu bayrakla kopyaladığınızda, önce siler sonra yeniden yazar; link kırılır.
Metin editörleri: Vim, --backup modunda çalışırken orijinal dosyayı siler ve yenisini yazar; bu hard link’i kopar. Nano ve bazı editörler de benzer davranır.
Hard link’i kasıtlı olarak koparmak istediğinizde:
# Hard link'i kopar, bağımsız kopya oluştur
cp --remove-destination /kaynak/dosya /hedef/dosya
# Ya da rsync ile:
rsync --copy-dest=. kaynak hedef
İnode Tüketimini İzlemek
Hard link meselesiyle bağlantılı bir konu: inode tüketimi. Çok sayıda küçük dosya olan sistemlerde disk dolmadan önce inode’lar tükenebilir. Hard link yönetimi bu konuda da yardımcı olur.
# Inode kullanımını göster
df -i
# En çok inode tüketen dizinleri bul
find / -xdev -printf "%hn" 2>/dev/null | sort | uniq -c | sort -rn | head -20
Hard link kullanımı inode sayısını artırmaz (aynı inode paylaşılır), bu yüzden inode tüketimi sorunu yaşayan sistemlerde duplicate dosyaları hard link’e dönüştürmek çift yönlü kazanç sağlar: hem disk alanı hem de inode sayısı.
Symlink ile Karıştırmayın
Son olarak, hard link tespitinde sık yapılan bir hataya değinelim: symbolic link’ler (symlink) ile karıştırmak.
# Symlink'leri bul (bunlar hard link DEĞİL)
find /etc -type l -ls 2>/dev/null
# Hard link'li dosyaları bul (aynı inode, farklı isim)
find /etc -type f -links +1 -ls 2>/dev/null
Temel fark: symlink kırılabilir (işaret ettiği dosya silinirse çalışmaz), hard link kırılamaz (son hard link silinene kadar veri korunur). Symlink’ler ls -la çıktısında -> işaretiyle görünür, hard link’ler ise normal dosya gibi görünür.
Birini diğeriyle karıştırmak ciddi hatalara yol açabilir; özellikle silme operasyonlarında.
Sonuç
Hard link tespiti ve yönetimi, görünürde küçük ama derinlemesine baktığınızda sistem yönetiminin kritik bir katmanı. stat ile inode bilgisi almak, find -inum ile hard link’leri izlemek, hardlink ya da fdupes ile duplicate’leri yönetmek; bunlar günlük toolbox’ınızda olması gereken beceriler.
Özellikle yedekleme sistemleri, büyük uygulama sunucuları ve çok kullanıcılı ortamlarda hard link yapısını anlamak; hem depolama verimliliği hem de güvenlik açısından size önemli avantaj sağlar. protected_hardlinks ayarını kontrol etmeyi, setuid binary’leri üzerindeki beklenmedik hard link’leri izlemeyi ve yedekleme scriptlerinizin hard link davranışını doğrulamayı alışkanlık haline getirin.
En önemlisi: bir dosyayı sildiğinizde gerçekten silinip silinmediğini kontrol etme alışkanlığı edinin. rm bir link siler, veriyi değil. Bunu içselleştirdiğinizde dosya sistemini çok daha rahat yönetirsiniz.
