Disk je poln, du pa ne pokaže, kaj ga zaseda: kaj je lahko vzrok?

Linux Branje: 5 min

Zgodi se, da je disk po df -h poln (ali skoraj poln), seštevek velikosti map z ukazom du pa kaže precej manj in ni mogoče najti, kaj zaseda manjkajoči prostor. O uporabi obeh ukazov govori članek Kako preverim porabo diska na strežniku Linux (ukaza du in df)?. Razlika ima nekaj tipičnih vzrokov; dobro jih je pregledati po vrsti.

1. Izbrisane, a še odprte datoteke

Najpogostejši vzrok: izbrisal si veliko datoteko (običajno dnevniško), tekoči program (spletni strežnik, podatkovna baza, proces PHP) pa jo še drži odprto. V Linuxu se vsebina datoteke v tem primeru ne sprosti, dokler je program ne zapre: datoteka v imeniku ni več vidna, zato je du ne šteje, po df pa še vedno zaseda prostor.

Seznam izbrisanih, a odprtih datotek v določenem datotečnem sistemu (tu v korenu):

sudo lsof -a +L1 /

+L1 izbere že izbrisane datoteke (brez povezave), / korenski datotečni sistem, -a pa določa, da morata biti izpolnjena oba pogoja. Brez -a sta pogoja povezana z „ali” in lsof izpiše vse odprte datoteke korena. Deluje tudi navaden sudo lsof +L1, vendar je v preizkusu izpisal tudi datoteke, ki jih sistem hrani v pomnilniku (/memfd:…) in ne zasedajo prostora na disku.

ali, če lsof ni nameščen (sudo dnf install lsof / sudo apt install lsof):

sudo find /proc/*/fd -ls 2>/dev/null | grep '(deleted)'

Na testnem računalniku z AlmaLinux 10 smo izbrisali 600 MB veliko datoteko error_log Apacheja, medtem ko je storitev tekla. Po df se zasedeni prostor ni zmanjšal (ostal je 2,0 GB), po du je imenik dnevnikov postal prazen, lsof pa je pokazal, kdo jo še drži odprto:

Izbrisana, a še odprta dnevniška datoteka v sistemu AlmaLinux 10: po df je zasedenih 2,0 GB, po du je imenik /var/log/httpd 0, po lsof -a +L1 / pa pet procesov httpd drži odprto izbrisano datoteko error_log

Stolpec COMMAND pokaže program, SIZE/OFF pa velikost datoteke v bajtih (tu 629 146 459 bajtov, torej 600 MB). Isto datoteko držita odprto glavni proces spletnega strežnika (root) in njegovi delovni procesi (apache). Za sprostitev prostora znova zaženi prizadeto storitev:

sudo systemctl restart httpd

Če storitve ni mogoče znova zagnati, lahko vsebino datoteke izprazniš tudi prek opisnika datoteke procesa. Iz števil v stolpcih PID in FD (brez črke, na zgornji sliki 2848 in 2):

sudo truncate -s 0 /proc/2848/fd/2

V preizkusu je to takoj sprostilo 600 MB (df se je zmanjšal z 2,0 GB na 1005 MB), po ponovnem zagonu storitve pa je izbrisana datoteka izginila tudi s seznama lsof. Če isto datoteko drži odprto več procesov, jo je dovolj izprazniti prek enega od njih, saj gre za isto datoteko.

Kako se temu naslednjič izogneš?

Dnevniške datoteke, ki je v uporabi, ne briši (rm), temveč jo izprazni:

sudo truncate -s 0 /var/log/httpd/error_log

Tako lahko program vanjo piše naprej, prostor pa se takoj sprosti. O iskanju velikih dnevniških datotek: Kako v Linuxu najdeš in odstraniš velike datoteke error_log.

2. Zmanjkalo je inodov

Če je kljub napaki „No space left on device” po df -h prostora dovolj, je v datotečnem sistemu morda omejitev doseglo število datotek. To pokaže stikalo -i:

df -i

V preizkusu se je po izčrpanju inodov na majhnem datotečnem sistemu ext4 touch ustavil s tem: touch: cannot touch '/mnt/kis/f94': No space left on device, čeprav je bilo po df -h prostih 88 MB, po df -i pa je bil IUse% 100 %.

Če je stolpec IUse% blizu 100 %, je na disku ogromno drobnih datotek, običajno datotek sej (sessions), predpomnilnika ali nedostavljenih sporočil. Kateri imenik ima največ datotek:

sudo du --inodes -x / 2>/dev/null | sort -n | tail -n 20

O pojmu inode preberi v članku Kaj pomeni inode?.

3. Prostor, rezerviran za root (ext4)

Datotečni sistem ext4 privzeto rezervira 5 % prostora za uporabnika root, da sistem ostane delujoč, tudi če uporabniki napolnijo disk. Zato je vsota Used in Avail po df manjša od vrednosti Size, navaden uporabnik pa vidi „poln” disk že, ko root še lahko piše.

Na podatkovnem disku (ne na sistemskem) je rezervirani prostor mogoče zmanjšati, na primer na 1 %:

sudo tune2fs -m 1 /dev/vdb1

Trenutno vrednost pokaže sudo tune2fs -l /dev/vdb1 | grep -i 'reserved block count'; v preizkusu je bilo na sveže formatiranem datotečnem sistemu ext4 od 102 400 blokov rezerviranih 5120 (5 %), po tune2fs -m 1 pa 1024.

Datotečni sistem XFS (privzet v AlmaLinux in Rocky Linux) takšnega prostora ne rezervira.

4. Datoteke, prekrite s točko priklopa

Če si v imenik (na primer /mnt/data ali /home) priklopil drug disk, priklopljeni disk prekrije datoteke, ki so bile prej v imeniku: du jih ne vidi, na sistemskem disku pa zasedajo prostor. To se običajno zgodi, če se drugi disk po ponovnem zagonu ni priklopil, programi pa so medtem pisali na sistemski disk.

Prekrite datoteke si ogledaš tako, da korenski datotečni sistem priklopiš še na drugo mesto:

sudo mkdir /mnt/rootfs
sudo mount --bind / /mnt/rootfs
sudo du -sh /mnt/rootfs/mnt/data

V preizkusu smo 50 MB veliko datoteko zapisali v imenik /mnt/data, preden smo tja priklopili drug disk: du -sh /mnt/data je pokazal 15 KB, du -sh /mnt/rootfs/mnt/data pa 50 MB. Če tu najdeš podatke, jih premakni na priklopljeni disk, nato odstrani vezavo:

sudo umount /mnt/rootfs

5. Drugi vzroki

  • Dnevnik systemd: preveriš ga z ukazom journalctl --disk-usage, zmanjšaš pa z ukazom journalctl --vacuum-size=500M (glej: Branje dnevniških datotek v Linuxu).
  • Stara jedra in predpomnilnik upravitelja paketov: sudo dnf clean all ali sudo apt clean in sudo apt autoremove.
  • Docker: neuporabljene slike in vsebniki lahko pod /var/lib/docker zasedajo veliko prostora; docker system df ga pokaže, docker system prune pa počisti.
  • Binarni dnevniki podatkovne baze: replikacijski dnevniki MariaDB/MySQL (binlog) lahko rastejo neomejeno, če nimajo nastavljenega roka poteka.

Če je prostora trajno premalo, je disk mogoče povečati (glej: Kako povečam vire svojega paketa VPS? in Kako povečam datotečni sistem po povečanju diska VPS?).

Nazaj: Linux – članki (76)