İçeriğe geç
Approvalens

Rehberler · 8 dk okuma

VPS Disk Doldu: "No space left on device" ve Güvenli Temizlik

Sunucu diski doldu mu? Yeri neyin kapladığını df, du ve lsof ile bul; journal, log, eski kernel, Docker ve yedekleri tek tek, güvenle temizle.

Approvalens ekibi

"No space left on device" hatası, bir yazma işleminin diskte yer kalmadığı için başarısız olduğunu söylüyor. Biten şey bazen bayt, bazen inode; bazen de yer, silinmiş ama hâlâ açık tutulan bir dosyanın elinde. Çözümün şekli hep aynı: ölç, büyüyen bir iki şeyi bul, onları adıyla sil, sonra büyüyen şeye bir sınır koy ki tekrar olmasın.

Yapmaman gereken tek şey, toplu bir temizlik komutu çalıştırıp en iyisini ummak. Bunun nedenini Docker bölümünde anlatıyoruz.

Önce neyin dolduğuna bak

İki komut, on saniye:

df -h
df -i

df -h her dosya sistemindeki alanı, df -i inode'ları (dosya sisteminin tutabileceği dosya sayısını) gösterir. / satırındaki Use% ve IUse% sütunlarına bak; /boot ya da /var ayrı bölümse onlara da.

Burada kafa karıştıran birkaç durum var:

  • Avail 0 ama kullanılan alan Size'ın tamamı değil. ext4, root için bir pay ayırır. tune2fs kılavuz sayfası bu payın yalnızca yetkili süreçlerce kullanılabildiğini, ayrıcalıksız süreçler yazamaz hale geldikten sonra syslogd gibi sistem servislerinin çalışmaya devam edebilmesi için ayrıldığını ve varsayılan oranın "normalde" %5 olduğunu yazıyor. Yani MySQL, PHP ve kendi kullanıcısıyla çalışan uygulaman hata vermeye başladıktan sonra bile root'a ait servisler bir süre yazmaya devam edebilir.
  • Yer var ama hata yine geliyor. Bu inode. df -i çıktısında IUse% %100'dür. Milyonlarca küçük dosya (PHP oturumları, bir önbellek eklentisinin dosyaları, posta kuyruğu) bunu yapar.
  • Sadece /boot dolu. Küçük ve ayrı bir /boot bölümü olan eski kurulumlarda eski kernel'ler burayı doldurur ve apt güncellemeleri yarıda kalır. Aşağıdaki kernel bölümüne bak.

Yeri neyin kapladığını bul

Kökten başla ve her seferinde bir seviye in. -x, du'nun tek dosya sisteminde kalmasını, /proc ya da başka bağlama noktalarına sapmamasını sağlar:

sudo du -xh -d1 / 2>/dev/null | sort -rh | head -15

Sonra en büyük klasörde tekrarla (/var, ardından /var/lib diye), tanıdık bir şeye varana kadar. Tıklayarak gezmeyi seviyorsan ncdu aynı işi etkileşimli yapar (ncdu); küçük bir paket için yer kaldıysa sudo apt install ncdu ile kur ve sudo ncdu -x / çalıştır.

Dolu bir Ubuntu VPS'te terminal oturumu: df -h /dev/vda1 için %100 ve 0 boş alan gösteriyor, / üzerindeki du /var için 21G ve /home için 9.8G veriyor, /var/lib ve /var/log üzerindeki du ise 13G ile /var/lib/docker ve 3.8G ile /var/log/journal klasörünü işaret ediyor
Örnek oturum: suçluyu bulmak için çoğu zaman iki du turu yeter. Burada Docker ve journal öne çıkıyor, hemen arkasında /home altında bir yedek klasörü var.

Inode için aynı mantık, --inodes ile:

sudo du -x --inodes -d1 / 2>/dev/null | sort -rn | head -15

Kök dosya sistemindeki tek tek büyük dosyaları listelemek için (eski yedekler ve veritabanı dökümleri burada çıkar):

sudo find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/null

Yolları bir kenara not et. Aşağıdaki her şey, bunlardan hangisinin gidebileceğine tek tek karar vermekle ilgili.

En sık suçlular ve her birinin temizliği

VPS diskini dolduran altı yaygın sebebin tablosu: systemd journal, log dosyaları, eski kernel ve apt önbelleği, Docker imajları konteynerleri ve volume'ları, ev klasörlerindeki yedek ve dökümler, silinmiş ama açık dosyalar; her satırda kontrol komutu, güvenli temizlik ve kaçınılacak hata var
Her suçlunun salt okunur bir kontrolü ve hedefli bir temizliği var. Hiçbiri toplu silme gerektirmiyor.

systemd journal

Kontrol:

journalctl --disk-usage

Varsayılan ayarda journal dosya sisteminin %10'una kadar yer kaplayabilir, üst sınır 4G (journald.conf kılavuzu, SystemMaxUse=). 40 GB'lık bir diskte bu, 4 GB'a yakın log demek. Hemen küçültmek için:

sudo journalctl --rotate
sudo journalctl --vacuum-size=500M

--rotate adımı boşuna değil. journalctl kılavuzu, vacuum işlemlerinin yalnızca arşivlenmiş journal dosyalarına dokunduğunu söylüyor; --rotate da etkin dosyaları önce arşive çeviriyor. Kalıcı bir sınır için ana dosyayı düzenlemek yerine bir drop-in ekle:

sudo mkdir -p /etc/systemd/journald.conf.d
printf '[Journal]\nSystemMaxUse=500M\n' | sudo tee /etc/systemd/journald.conf.d/50-size.conf
sudo systemctl restart systemd-journald

/var/log altındaki log dosyaları

sudo find /var/log -type f -size +100M -exec ls -lh {} +

Eski, döndürülmüş dosyaları (access.log.3.gz, syslog.2.gz) listeye baktıktan sonra silebilirsin. Hâlâ yazılan bir log'u ise rm ile silme: süreç dosyayı açık tutar, ad kaybolur ama yer geri gelmez (son maddeye bak). Bunun yerine yerinde boşalt:

sudo truncate -s 0 /var/log/nginx/access.log

Sonra neden bu kadar büyüdüğünü bul. Genelde ya logrotate çalışmıyordur ya da o dosya için kuralı yoktur. systemctl status logrotate.timer çalışıp çalışmadığını gösterir; sudo logrotate -d /etc/logrotate.conf de deneme çalıştırması yapar (logrotate: hata ayıklama kipinde log'lara dokunulmaz, durum dosyası da güncellenmez). wp-content içinde açık unutulmuş bir WordPress debug.log'u ya da kendi log'unu döndürme kuralı olmadan yazan bir uygulama, sık görülen iki örnek.

Eski kernel'ler ve apt önbelleği

uname -r
dpkg --list 'linux-image*' | grep ^ii
du -sh /var/cache/apt/archives

sudo apt-get clean paket önbelleğini boşaltır; apt-get kılavuzuna göre /var/cache/apt/archives/ içinden kilit dosyası dışında her şeyi siler. Güvenli; gerekirse paketler yeniden iner.

sudo apt autoremove, başka paketlerin bağımlılığı olarak otomatik kurulmuş ve artık gerekmeyen paketleri kaldırır. Ubuntu'da buna artık gerekmediği işaretlenen kernel'ler de dahil. y demeden önce yazdığı listeyi oku. Kullandığın bir şeyi kaldırmak istiyorsa "hayır" de ve o paketi sudo apt-mark manual <paket> ile elle kurulmuş olarak işaretle.

Disk bir güncelleme sırasında dolduysa dpkg yarıda kalmış olabilir. Yer açtıktan sonra sudo dpkg --configure -a, ardından sudo apt -f install çalıştır.

Docker: imajlar, konteynerler, volume'lar ve konteyner log'ları

Önce bak. Bu komutlar yalnızca okur:

docker system df
docker ps -a --size
docker image ls
docker volume ls
sudo sh -c 'du -sh /var/lib/docker/containers/*/*-json.log' | sort -rh | head

Sonra adını verebildiğin şeyleri sil:

docker rm eski-staging-web            # bir daha başlatmayacağından emin olduğun durmuş konteyner
docker image rm uygulama:2026-08-01   # artık geri dönmeyeceğin eski bir etiket
docker ps -a --filter volume=pgdata   # bu volume'u kim kullanıyor? silmeden önce bak
docker volume rm test-yuklemeler      # ancak üstteki satır önemli bir şey göstermiyorsa

Neden docker system prune, docker image prune -a ya da docker volume prune değil? Çünkü bunlar senin yerine karar verir. Docker'ın pruning sayfası açıkça yazıyor: docker container prune "This will remove all stopped containers" uyarısı veriyor, docker image prune -a en az bir konteynere bağlı olmayan bütün imajları siliyor, volume'lar için de "Volumes are never removed automatically, because to do so could destroy data." deniyor. Bakım için durdurduğun bir veritabanı konteyneri de "durmuş konteyner"dir. O gidince volume'unun bağlı olduğu konteyner kalmaz ve bir volume prune onu kullanılmıyor sayar. Geri dönüş için sakladığın imajın da konteyneri yoktur. Disk temizliği böyle yedekten geri yüklemeye dönüşür. Adıyla silmek beş dakika fazla sürer ama sürpriz çıkmaz.

Konteyner log'ları ikinci büyük kalem. json-file sürücüsünde max-size varsayılan olarak -1, yani sınırsız (JSON File logging driver); geveze bir konteynerin log'u sonsuza kadar büyür. Docker bu dosyaların yalnızca Docker daemon tarafından kullanılmak üzere tasarlandığını söylüyor; elle kesmek yerine /etc/docker/daemon.json içine sınır koy:

{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" }
}

Docker'ı yeniden başlat ve konteyneri yeniden oluştur (docker compose up -d --force-recreate <servis>). Mevcut konteynerler sen bunu yapana kadar eski ayarla çalışır.

Ev klasörlerindeki yedekler ve dökümler

Yukarıdaki find -size +500M listesi bunları genelde gösterir: /root altında yedek-2026-07.tar.gz, /home/ubuntu altında bir site.sql dökümü, wp-content altında bir eklentinin yedek klasörü. Aynı diskteki yedek, o disk gittiğinde zaten işe yaramaz. En yenisini başka bir yere kopyala, kopyanın açıldığını kontrol et, sonra eskileri adıyla sil. Bunları bir yedekleme işi oluşturuyorsa sabit sayıda kopya tutacak ve sunucu dışına yazacak şekilde ayarla.

Silinmiş ama hâlâ açık dosyalar

df disk dolu diyor ama du toplamı çok daha az çıkıyorsa, bir süreç silinmiş dosyaları tutuyordur:

sudo lsof +L1

lsof kılavuzu: "+L1 will select open files that have been unlinked." Çıktıda süreç adını, PID'sini ve boyutu görürsün. Yer, süreç dosyayı kapatınca geri gelir; o yüzden servisi yeniden başlat (sudo systemctl restart nginx, php8.3-fpm, hangisiyse). Canlı bir log'u rm ile silmenin klasik sonucu budur.

Disk dolunca ne bozulur?

Yer açtıktan sonra hasarı kontrol ederken işine yarar:

  • MySQL / MariaDB. MyISAM tabloları ve binary log için MySQL dakikada bir yer olup olmadığına bakar, on dakikada bir de log'a uyarı yazar; ALTER TABLE, OPTIMIZE TABLE ya da REPAIR TABLE sırasında ise geçici dosyalarını silip tabloyu çökmüş (crashed) olarak işaretleyebilir (How MySQL Handles a Full Disk). O sayfa MyISAM ve binary log'u anlatıyor; motor hangisi olursa olsun, yer açtıktan sonra MySQL hata log'unu oku ve değiştirilmekte olan tablolarda CHECK TABLE çalıştır.
  • PHP oturumları ve yüklemeler. Oturumları dosyada tutan siteler kimseyi giriş yaptıramaz, dosya yüklemeleri başarısız olur. Inode bittiyse sebebi çoğu zaman oturum klasörünün kendisidir.
  • Sertifika yenileme. Certbot yeni sertifikayı ve log'larını diske yazmak zorunda. Dolu diskte çalışan yenileme başarısız olur ve bunu eski sertifikanın süresi dolunca öğrenirsin. Temizlikten sonra sudo certbot renew --dry-run çalıştır; gerisini SSL sertifikası süresi doldu rehberi anlatıyor.
  • Web sunucusu. Nginx log'larını ve büyük isteklerin gövdesini geçici dosya olarak diske yazar. Önbellekteki sayfalar açılmaya devam ederken formlar ve yüklemeler bozulabilir. Dışarıdan rastgele hatalar gibi görünür; sitem çökmüş mü rehberi ve ücretsiz site çalışıyor mu aracı, "kapalı" ile "yarı bozuk" arasındaki farkı ayırmana yardım eder.
  • apt ve dpkg. Yarıda kalan güncellemeler; yukarıda anlattık.

Tam çöküşten önce genelde sayfalar yavaşlar, çünkü veritabanı yer için bekler. İlk gördüğün belirti buysa, hikâyenin diğer yarısı yavaş sunucu yanıtı (TTFB) rehberinde.

Tekrar olmasın diye

Yukarıdaki temizlik bugünü kurtarır. Tekrarı önleyenler şunlar:

  • Journal'a (SystemMaxUse=) ve Docker log'larına (max-size) sınır koy.
  • Her uygulama log'unun bir logrotate kuralı olsun, logrotate.timer da etkin olsun.
  • Yedekleri sunucunun dışına taşı ve sabit sayıda tut.
  • Haberi %100'de değil, %85-90'da al. Bir ziyaretçi sana yazdığında MySQL çoktan beklemeye başlamış olur.

Disk dolmadan e-posta al

Approvalens sunucu ajanı, bir dosya sistemi %90'ı geçtiğinde ya da gidişata göre 48 saat içinde dolacaksa sana e-posta atar; inode'ları da aynı şekilde izler.

Sık sorulan sorular

Dosyaları sildim ama df hâlâ disk dolu diyor. Neden?

Çalışan bir süreç onları hâlâ açık tutuyor. sudo lsof +L1 ile süreci bul ve o servisi yeniden başlat. Dosya kapanınca yer geri gelir.

/var/log içindeki her şeyi silmek güvenli mi?

Hayır. Döndürülmüş eski dosyaları (.1, .gz) listeledikten sonra sil, etkin log'ları truncate -s 0 ile boşalt. Bazı servisler log klasörü yoksa başlamaz.

Küçük bir VPS'te ne kadar boş yer kalmalı?

Resmi bir sayı yok. Biz %80'i bakma, %90'ı harekete geçme noktası sayardık; tek bir yedek, güncelleme ya da log patlaması kalan yeri bir saatte bitirebilir.

docker system prune çalıştırsam olmaz mı?

Olur, ama durmuş bütün konteynerleri ve sarkan (dangling) imajları tek tek sormadan siler; --volumes ile daha da ileri gider. Durmuş bir veritabanı konteyneri ya da geri dönüş imajı olan bir sunucuda bu, istediğin veridir. docker system df ile listele, adıyla sil.

Disk bayt yüzünden değil inode yüzünden dolu. Şimdi ne yapacağım?

En çok dosya barındıran klasörü bulmak için du -x --inodes -d1 / çalıştır. PHP oturum klasörleri, önbellek eklentileri ve posta kuyrukları en sık sebepler. Yalnızca o klasördeki eski dosyaları sil (örneğin yolu kontrol ettikten sonra bir günden eski oturumları find <klasör> -type f -mmin +1440 -delete ile) ve onları temizlemeyi bırakan şeyi düzelt.

Eskimiş ya da yanlış bir şey mi gördün? Bize yaz, düzeltelim.

Bu rehberi İngilizce oku →

Kendi sitende kontrol et. Ücretsiz, kayıt yok.

Bunun için ücretsiz araçlar

Ücretsiz tarama

Kendi siteni kontrol et

Ücretsiz tarama ilk 50 sayfayı okur; puanını ve bulduğu tüm sorunları gösterir.

İlk 50 sayfa ücretsiz · üyelik yok · kart gerekmez

Tüm rehberler