Bir gece yarısı sitelerin açılmıyor, veritabanı yazma yapamıyor, hatta SSH ile bağlandığınızda kabuk bile şikayet ediyor: bash: cannot create temp file for here-document: No space left on device. Bu, bir sistem yöneticisinin en sık karşılaştığı ama en çok panikletici sorunlardan biridir. İyi haber şu: neredeyse her zaman geri döndürülebilir bir durumdur ve doğru komutlarla suçluyu birkaç dakikada bulmak mümkündür. Kötü haber ise, yanlış refleksle rastgele dosya silmeye başlamak durumu daha da kötüleştirebilir; çünkü bazı senaryolarda dosyayı silmek diski hiç boşaltmaz.
Bu rehberde, "No space left on device" hatasını profesyonel bir yaklaşımla ele alacağız. Önce diskin gerçekten dolu olup olmadığını, yoksa inode denen dosya sayacının mı tükendiğini ayıracağız. Ardından yer kaplayan dizini df ve du ile bulacak, /var/log ve journald şişmesini, apt önbelleğini temizleyecek; en sinsi durum olan "silindiği hâlde bir süreç tarafından açık tutulan" dosyaları lsof ile ortaya çıkaracağız. Son olarak logrotate ile bu belanın bir daha kapınızı çalmaması için kalıcı önlemleri kuracağız.
Önce Diskin Gerçekten Dolu Olduğunu Doğrulayın#
Panikle silmeye başlamadan önce yapılacak ilk iş, hangi bölümün (partition) dolduğunu görmektir. df komutu bunun için biçilmiş kaftandır. -h bayrağı çıktıyı insan okunur (human-readable) hâle getirir:
df -h
Örnek bir çıktı şöyle görünür:
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 40G 20M 100% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
/dev/vdb1 100G 32G 68G 32% /var/lib/mysql
Buradaki kritik sütun Use%. / bölümü %100 görünüyor ve sadece 20 MB boş kalmış. Demek ki sorun kök dizinde. Dikkat edin, sunucularda genellikle birden fazla bağlama noktası (mount point) olur; /var, /home veya veritabanı için ayrı bir disk olabilir. Doğru bölümü hedeflemezseniz, dolu olmayan bir yerde saatlerce dosya ararsınız.
Bazen df -h her bölümü bol boş alanla gösterir ama sistem yine de "no space" der. Bu, klasik bir tuzaktır: disk değil, inode dolmuştur. Bunu ayırt etmek için mutlaka şunu da çalıştırın:
df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vda1 2621440 2621440 0 100% /
IUse% sütunu %100 ise, disk alanınız boş olsa bile yeni dosya oluşturamazsınız. İnode konusunu aşağıda ayrı bir başlıkta derinlemesine ele alacağız; şimdilik bu iki komutun birlikte çalıştırılması gerektiğini aklınızda tutun. İnode ve kota mantığının detayını disk kotası ve inode rehberimizde bulabilirsiniz.
du ile Yer Kaplayan Dizini Bulma#
Dolu bölümü tespit ettikten sonra sıra o bölüm içinde "kim bu kadar yer kaplıyor?" sorusuna geldi. du (disk usage) komutu her dizinin toplam boyutunu hesaplar. En pratik kullanım, ilk seviye dizinleri boyutlarına göre büyükten küçüğe sıralamaktır:
du -h --max-depth=1 / | sort -hr | head -20
Bu komutu sırasıyla derinleştirerek suçluya inersiniz. Diyelim çıktı /var dizinini işaret etti:
28G /var
6.5G /usr
2.1G /home
1.2G /root
Şimdi /var içine inip aynı komutu tekrar edelim:
du -h --max-depth=1 /var | sort -hr | head -20
21G /var/log
5.0G /var/lib
1.8G /var/cache
/var/log 21 GB. İşte suçlu. Bu "kademeli daralma" tekniği neredeyse her seferinde işe yarar. Büyük sunucularda du taraması uzun sürebilir; bu durumda -x bayrağını ekleyerek başka bağlama noktalarına geçmesini engelleyin, böylece yalnızca dolu bölümü tarar:
du -hx --max-depth=1 /var | sort -hr | head -20
Grafik bir görünüm istiyorsanız, ncdu aracı çok işe yarar. Ok tuşlarıyla dizinler arasında gezinip en büyükleri anında görürsünüz:
apt install ncdu # Debian/Ubuntu
ncdu -x /
| Komut | Ne işe yarar | Ne zaman kullanılır |
|---|---|---|
df -h | Bölüm bazında doluluk | İlk teşhis, hangi disk dolu |
df -i | İnode doluluğu | Disk boş ama hata varsa |
du -h --max-depth=1 | Dizin boyutları | Suçlu dizini bulma |
ncdu -x | İnteraktif tarama | Görsel keşif |
lsof +L1 | Silinmiş açık dosyalar | df ile du uyuşmuyorsa |
/var/log ve journald Şişmesini Temizleme#
Log dosyaları, dolu disklerin bir numaralı sebebidir. Kötü yapılandırılmış bir uygulama, döngüye giren bir hata ya da saldırı denemeleriyle şişen bir erişim logu diski günler içinde tüketebilir. Önce hangi log dosyalarının en büyük olduğunu görelim:
du -ah /var/log | sort -hr | head -20
Klasik şüpheliler nginx/access.log, syslog, mysql/mysql-slow.log ve mail.log gibi dosyalardır. Önemli uyarı: Bir log dosyasını rm ile silmeyin! Uygulama o dosyaya hâlâ yazıyorsa, dosyayı silmek yeri hemen boşaltmaz (bunun nedenini bir sonraki başlıkta göreceğiz) ve loglama bozulabilir. Doğru yöntem, dosyayı truncate ile sıfırlamaktır:
truncate -s 0 /var/log/nginx/access.log
Bu komut dosyanın içeriğini anında boşaltır ama dosya tanıtıcısını (file descriptor) korur, böylece nginx sorunsuz yazmaya devam eder.
systemd kullanan modern sistemlerde asıl şişkinlik çoğunlukla journald'dedir. Günlüklerin toplam boyutunu görmek için:
journalctl --disk-usage
Archived and active journals take up 8.4G in the file system.
Bunu güvenli biçimde küçültmek için vacuum seçeneklerini kullanın. Örneğin son 3 güne ait kayıtları tutup gerisini silmek veya toplam boyutu 200 MB ile sınırlamak:
# Zamanla sınırla
journalctl --vacuum-time=3d
# Boyutla sınırla
journalctl --vacuum-size=200M
Bu değişikliği kalıcı yapmak için /etc/systemd/journald.conf dosyasında bir üst sınır belirleyin:
[Journal]
SystemMaxUse=200M
SystemKeepFree=1G
MaxRetentionSec=1week
Ardından servisi yeniden başlatın: systemctl restart systemd-journald. Böylece journald bir daha diskinizi ele geçiremez.
apt Önbelleği ve Diğer Geçici Alanlar#
Debian ve Ubuntu tabanlı sistemlerde /var/cache/apt/archives dizini, kurulan tüm .deb paketlerini saklar. Zamanla bu birikinti gigabaytlara ulaşabilir. Güvenle temizlemek için:
# İndirilmiş paket önbelleğini boşalt
apt-get clean
# Artık gerekmeyen bağımlılıkları kaldır
apt-get autoremove --purge
# Eski paket sürümlerini temizle
apt-get autoclean
Diğer sık dolan geçici alanlar da vardır. /tmp dizini, bazı uygulamaların büyük ara dosyalar bıraktığı yerdir; içeriğini kontrol edin ama tüm sistemi bilmeden toptan silmeyin, çalışan süreçlerin soketleri burada olabilir. Docker kullanıyorsanız, kullanılmayan imaj ve katmanlar devasa yer kaplar:
# Docker'da kullanılmayan tüm nesneleri temizle
docker system prune -a --volumes
# Kullanımı önceden gör
docker system df
Uygulama düzeyinde de sık dolan yerler vardır. Composer, npm ve pip önbellekleri, eski yedek dosyaları (.sql, .tar.gz) ve WordPress gibi CMS'lerin uploads ile cache klasörleri hızla büyür. Yedeklerinizi sunucu diskinde biriktirmek yerine harici bir konuma taşımayı düşünün; yedekleme çözümlerimiz tam da bunun için vardır. WordPress özelinde önbellek ve log birikimini düzenli yönetmek için WordPress bakım hizmetimize göz atabilirsiniz.
En Sinsi Sorun: Silinmiş Ama Açık Tutulan Dosyalar#
Şimdi en kafa karıştırıcı senaryoya geldik. du ile taradığınızda toplam kullanım örneğin 12 GB çıkıyor, ama df diski %100 (40 GB) dolu gösteriyor. Aradaki 28 GB nerede? Cevap: bir süreç, silinmiş bir dosyayı hâlâ açık tutuyordur.
Linux'ta bir dosyayı rm ile sildiğinizde, o dosyaya yazan süreç dosyayı hâlâ açıksa, disk alanı serbest bırakılmaz. Dosya dizin ağacından kaybolur (yani du onu göremez) ama inode ve kapladığı bloklar, süreç dosya tanıtıcısını kapatana kadar diskte durmaya devam eder. En tipik örnek: birisi paniğe kapılıp rm /var/log/mysql-slow.log yapar ama MySQL o dosyaya hâlâ yazmaktadır. Sonuç: yer boşalmaz, sadece görünmez olur.
Bu hayalet dosyaları bulmak için lsof komutunun +L1 bayrağı kullanılır. Bu bayrak, bağlantı sayısı (link count) 1'in altında olan, yani silinmiş ama hâlâ açık dosyaları listeler:
lsof +L1
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
mysqld 1123 mysql 7u REG 253,1 28991029248 0 1835 /var/log/mysql-slow.log (deleted)
İşte suçlu: mysqld süreci, silinmiş bir 27 GB'lık dosyayı hâlâ tutuyor. NAME sütunundaki (deleted) etiketi ve NLINK değerinin 0 olması bunu doğruluyor. Çözüm için o dosya tanıtıcısını serbest bırakmanız gerekir. En temiz yöntem, ilgili servisi yeniden başlatmak veya yeniden yükleme (reload) sinyali göndermektir:
systemctl restart mysql
Servisi yeniden başlatamayacağınız kritik durumlarda, /proc sanal dosya sistemi üzerinden dosyayı truncate ederek yeri anında geri kazanabilirsiniz. Yukarıdaki örnekte PID 1123 ve FD 7 için:
truncate -s 0 /proc/1123/fd/7
Bu numara, servisi durdurmadan diski kurtarmanın hayat kurtaran yöntemidir. /proc/<PID>/fd/<FD> yolu, silinmiş dosyaya hâlâ erişim sağlar ve onu sıfırlamak yeri hemen boşaltır.
İnode Tükenmesi: Disk Boş Ama Hata Var#
Başta değindiğimiz df -i senaryosuna geri dönelim. İnode, dosya sisteminin her dosya ve dizin için tuttuğu bir kayıt yapısıdır; adını, izinlerini, sahibini ve verinin nerede olduğunu tutar. Dosya sistemi oluşturulduğunda sabit sayıda inode ayrılır. Milyonlarca minik dosya (örneğin PHP oturum dosyaları, e-posta kuyruğu, önbellek parçacıkları) oluşturursanız, her biri sadece birkaç bayt olsa bile inode havuzu tükenir. Sonuç: disk boş görünse de yeni dosya oluşturamazsınız.
Önce inode durumunu doğrulayın:
df -i
IUse% %100 ise, hangi dizinin milyonlarca dosya barındırdığını bulmalısınız. Bir dizin altındaki dosya sayısını sayan bu komut, suçluyu ortaya çıkarır:
for d in /var/* /home/* /tmp; do
echo "$(find "$d" -xdev -type f 2>/dev/null | wc -l) $d"
done | sort -rn | head
En sık suçlular şunlardır: PHP oturum dizini /var/lib/php/sessions, Postfix/Exim e-posta kuyruğu /var/spool/, kötü yapılandırılmış bir uygulamanın önbellek klasörü. Örneğin PHP oturumları temizlenmediyse yüz binlerce dosya birikebilir. Bu dosyaları güvenli ve verimli biçimde silmek için find kullanın; rm * çoğu zaman "argüman listesi çok uzun" hatası verir çünkü kabuk milyonlarca dosya adını tek seferde işleyemez:
# 7 günden eski oturum dosyalarını sil
find /var/lib/php/sessions -type f -mtime +7 -delete
# Genel yöntem: eski geçici dosyaları toplu sil
find /path/to/cache -type f -mtime +2 -delete
İnode tükenmesinin kök çözümü, uygulamanın minik dosya üretme davranışını düzeltmek ve düzenli temizlik (cron) kurmaktır. Konunun ayrıntısı ile kota ayarları için disk kotası ve inode yönetimi rehberimizi incelemenizi öneririz.
Tekrarını Önleme: logrotate ve Düzenli Bakım#
Diski boşaltmak yangını söndürmektir; asıl mesele yangının bir daha çıkmamasıdır. Log şişmesinin kalıcı çözümü logrotate'tir. Bu araç, log dosyalarını periyodik olarak döndürür (rotate), sıkıştırır ve eskileri siler. Çoğu dağıtımda kuruludur ve /etc/logrotate.d/ altına uygulama bazlı yapılandırma dosyaları koyarsınız.
Özel bir uygulama logu için örnek bir yapılandırma:
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
postrotate
systemctl reload myapp > /dev/null 2>&1 || true
endscript
}
Bu ayarlar günlük döndürme yapar, 14 kopya saklar, eskileri sıkıştırır ve döndürme sonrası servise reload sinyali gönderir (böylece "silinmiş ama açık dosya" sorunu yaşanmaz). Yapılandırmayı hemen test etmek için:
logrotate -d /etc/logrotate.d/myapp # kuru çalıştırma (debug)
logrotate -f /etc/logrotate.d/myapp # zorla çalıştır
Bunun yanında birkaç iyi alışkanlık, disk krizlerini büyük ölçüde önler:
- Disk doluluğu için izleme kurun.
%80eşiğinde uyarı almak,%100'de site çökmesinden çok daha iyidir. Sunucularınızı sürekli izleyip aksama olduğunda bilgilendirilmek için panel içindeki uptime uyarıları özelliğinden faydalanabilirsiniz. - Yedekleri sunucu diskinde biriktirmeyin; harici depolamaya taşıyın.
- Veritabanı slow query loglarına ve debug loglarına bir üst sınır koyun.
/tmpiçin periyodik temizlik (systemd-tmpfiles veya cron) tanımlayın.
Diskiniz kronik olarak yetersiz kalıyorsa, sorun temizlikte değil kapasitede olabilir. Büyüyen projeler için daha fazla disk ve kaynak sunan VDS sunucularımıza ya da esnek sanal sunucu çözümlerimize geçmek mantıklı olur. Bellek darboğazı da yaşıyorsanız swap alanı oluşturma rehberimiz ek bir tampon sağlayabilir; yine de swap, gerçek disk ya da RAM'in yerini tutmaz, yalnızca zaman kazandırır.
Sıkça Sorulan Sorular#
df boş alan gösteriyor ama disk dolu diyor, neden?#
Bu durumun en yaygın iki nedeni vardır. Birincisi inode tükenmesidir; df -i çalıştırın, IUse% %100 ise disk alanı boş olsa bile yeni dosya oluşturamazsınız. İkincisi silinmiş ama bir süreç tarafından açık tutulan dosyalardır; lsof +L1 ile bu hayalet dosyaları bulup ilgili servisi yeniden başlatınca ya da /proc/<PID>/fd/<FD> yolunu truncate edince yer geri gelir.
Log dosyasını rm ile silmek neden yeterli değil?#
Çünkü uygulama o dosyaya hâlâ yazıyorsa, dosyayı dizinden silmek disk bloklarını serbest bırakmaz. Süreç dosya tanıtıcısını açık tuttuğu sürece bloklar diskte kalmaya devam eder ve df hâlâ dolu gösterir. Doğru yöntem truncate -s 0 dosya.log ile içeriği boşaltmaktır; bu, dosya tanıtıcısını koruyarak yeri anında geri kazandırır ve loglamayı bozmaz.
Hangi dizinin ne kadar yer kapladığını en hızlı nasıl bulurum?#
du -hx --max-depth=1 /yol | sort -hr | head -20 komutu bir dizinin altındaki ilk seviye klasörleri boyutlarına göre sıralar. Çıkan en büyük dizinin içine girip aynı komutu tekrarlayarak kademeli olarak suçluya inersiniz. Görsel bir keşif isterseniz ncdu -x / aracı ok tuşlarıyla gezinme imkânı sunar ve en büyük dosyaları anında gösterir.
journald diskimi doldurdu, güvenli şekilde nasıl küçültürüm?#
Önce journalctl --disk-usage ile mevcut boyutu görün. Ardından journalctl --vacuum-size=200M ile toplam boyutu ya da journalctl --vacuum-time=3d ile saklama süresini sınırlayın. Kalıcı çözüm için /etc/systemd/journald.conf dosyasında SystemMaxUse=200M gibi bir üst sınır tanımlayıp systemctl restart systemd-journald çalıştırın; böylece günlükler bir daha kontrolsüz büyümez.
İnode dolması disk dolmasından farklı mıdır?#
Evet, tamamen farklıdır. Disk dolması verinin kapladığı gerçek alanla ilgilidir; inode dolması ise dosya sisteminin tutabileceği toplam dosya-dizin sayısının tükenmesidir. Yüz binlerce minik dosya (PHP oturumları, e-posta kuyruğu) birkaç megabaytlık yer kaplasa bile tüm inode havuzunu bitirebilir. df -h boş, df -i ise %100 gösteriyorsa çözüm alan açmak değil, gereksiz küçük dosyaları find ... -delete ile temizlemektir.
Diski temizledim ama birkaç günde tekrar doluyor, kalıcı çözüm ne?#
Tekrarlayan doluluk, kaynak sorununun temizlikle değil yapılandırmayla çözülmesi gerektiğini gösterir. Log şişmesi için logrotate kuralları tanımlayın, journald'a boyut sınırı koyun, uygulama önbelleği ve geçici dosyalar için cron temizliği yazın ve %80 eşiğinde disk uyarısı kurun. Bu önlemlere rağmen alan yetmiyorsa sorun kapasitededir; daha büyük diskli bir VDS ya da sanal sunucuya geçmek en sağlıklı adımdır.
Kapanış#
"No space left on device" hatası, ilk anda felaket gibi görünse de metodik yaklaşıldığında hızla çözülen bir sorundur. Özet reçete şudur: önce df -h ve df -i ile diskin mi yoksa inode'un mu dolduğunu ayırın, du ile suçlu dizini bulun, logları truncate ve journalctl --vacuum ile küçültün, lsof +L1 ile hayalet dosyaları yakalayın ve son olarak logrotate ile bu belanın kökünü kazıyın. Bu adımları bir kez alışkanlık hâline getirdiğinizde, gece yarısı disk alarmları tarih olur.
Eğer sunucu yönetimiyle uğraşmak yerine işinize odaklanmak istiyorsanız, bu yükü biz üstlenebiliriz. Uzman ekibimizin sunucularınızı izlediği, güncellediği ve tam da bu tür krizleri sizin adınıza çözdüğü sunucu yönetimi hizmetimize göz atın. Daha fazla kaynağa ihtiyaç duyuyorsanız güçlü VDS ve sanal sunucu paketlerimizi, düzenli ve güvenli yedekleme için yedekleme çözümlerimizi, performans odaklı barındırma için de hosting paketlerimizi inceleyebilirsiniz. Diskiniz de huzurunuz da hep ferah kalsın.