Ilustratie cu un disc Linux plin curatat pentru a elibera spatiu
Linux

Disc plin pe serverul Linux? Elibereaza spatiu in siguranta

De fiecare data incepe cu un simptom mic si confuz. Un deploy pica cu No space left on device, MySQL nu mai accepta scrieri, un site WordPress afiseaza o pagina alba, sau apesi Tab in sesiunea SSH si primesti o eroare ciudata despre un fisier temporar care nu poate fi creat. In spatele tuturor e aceeasi problema: discul e plin. Vestea buna e ca pe un VPS obisnuit spatiul e rar ocupat de datele tale reale. Se duce pe loguri pe care nu le citeste nimeni, pe un jurnal systemd care creste de un an, pe pachete descarcate, pe kerneluri vechi si pe imagini Docker ramase de la deploy-uri de mult uitate. In ghidul asta aflam exact ce ocupa spatiul, apoi il eliberam pas cu pas, fara sa stergem ceva de care serverul inca are nevoie.

Tot ce urmeaza functioneaza pe Debian 13 si Ubuntu 24.04, fie ca serverul e proaspat instalat, fie ca ruleaza de ani de zile, si semnalam fiecare loc in care cele doua distributii se comporta diferit.

De ce un disc plin blocheaza un server Linux

Un filesystem (sistem de fisiere) e structura care organizeaza datele pe o partitie. Pe majoritatea imaginilor de VPS e ext4. El imparte spatiul in blocuri mici (de obicei de 4 KB) si tine evidenta fiecarui fisier printr-un inod (inode), o mica inregistrare cu proprietarul fisierului, permisiunile, dimensiunea si locul unde se afla blocurile lui. Un filesystem poate ramane fara oricare dintre ele: fara blocuri (nu mai e loc pentru date) sau fara inoduri (nu mai poti crea fisiere noi, chiar daca ai gigabytes liberi). Ambele produc acelasi mesaj de eroare, de aceea le verificam mereu pe amandoua.

Fiecare filesystem e atasat la arborele de directoare intr-un punct de montare (mount point). Filesystem-ul radacina e montat la /, iar pe un VPS tipic aproape totul (/var, /home, /usr) se afla pe el. De aceea un singur fisier de log scapat de sub control in /var/log iti poate opri baza de date din /var/lib/mysql: folosesc aceeasi rezerva de spatiu.

Cand rezerva se goleste, lucrurile cad in moduri ciudate. Serviciile nu mai pot scrie loguri sau fisiere PID, PHP nu mai salveaza sesiuni si utilizatorii sunt delogati, bazele de date refuza tranzactii sau se opresc, apt nu mai poate descarca pachete, iar chiar si shell-ul se poate plange, pentru ca scrie fisiere temporare mici pentru tab completion si here-document. Login-ul prin SSH merge de obicei in continuare, si asta ne permite sa reparam situatia.

Inca un detaliu care deruteaza multa lume: ext4 rezerva implicit aproximativ 5% din spatiu pentru utilizatorul root. Asa ca df poate arata Avail 0 si 100% desi Used e putin mai mic decat Size. Serviciile care ruleaza ca utilizatori normali (www-data, mysql, utilizatorul aplicatiei tale) se lovesc primele de perete, in timp ce root mai poate scrie putin, exact marja de care avem nevoie pentru curatenie.

De ce ai nevoie

  • Un server cu Debian 13 sau Ubuntu 24.04, de exemplu un VPS DreamServer proaspat, cu acces SSH ca un utilizator cu drepturi sudo.
  • 15 pana la 30 de minute, mai mult daca e prima curatenie dupa ani de uptime.
  • Un backup recent al datelor importante. Stergem doar lucruri care pot fi regenerate, dar un backup transforma orice greseala intr-un inconvenient minor.
  • Docker e optional: Pasul 6 se aplica doar daca rulezi containere.
  • Daca serverul tau e un container LXC neprivilegiat si nu un VPS KVM, majoritatea pasilor functioneaza la fel. Exceptiile (kerneluri, bind mount, reglaje de filesystem, redimensionare) sunt semnalate acolo unde apar.

Unde se duce de obicei spatiul pe un VPS

Inainte sa atingi ceva, ajuta sa stii care sunt suspectii obisnuiti. Pe serverele mici pe care le avem in grija zilnic, aceleasi cateva directoare explica aproape tot spatiul “misterios”. Graficul de mai jos ilustreaza un VPS mic tipic dupa aproximativ un an, cu doua-trei aplicatii in Docker. Valorile sunt aproximative si la tine vor fi altele, dar ordinea e foarte des aceeasi.

Spatiu eliberat aproximativ pe un VPS mic, dupa un an (GB)Imagini Docker + cacheLoguri containereJurnal systemdLoguri rotiteKerneluri vechiCache APT~6.5 GB~2.0 GB~1.5 GB~0.8 GB~0.6 GB~0.4 GB01234567Spatiu eliberat (GB, aproximativ)Curatare
Spatiu recuperat aproximativ prin fiecare tip de curatenie pe un VPS mic tipic, dupa aproximativ un an de utilizare. Valori ilustrative, serverul tau va arata altfel.

Docker castiga de obicei, pentru ca fiecare docker compose pull lasa in urma versiunea anterioara a imaginii, iar logurile containerelor nu au implicit nicio limita de dimensiune. Urmeaza jurnalul, apoi logurile rotite, kernelurile vechi si cache-ul de pachete APT. Datele tale propriu-zise (site-uri, baze de date, upload-uri) sunt rar problema, si sunt singurul lucru pe care nu il atingem.

Linux disk full fix in opt pasi

Impartim treaba in etape. Pasii 1-3 doar se uita: iti spun unde s-a dus spatiul, fara sa schimbe nimic. Pasii 4-6 curata suspectii obisnuiti. Pasii 7 si 8 acopera cele doua cazuri speciale care ii incurca si pe administratorii cu experienta: spatiu tinut ocupat de fisiere sterse si epuizarea inodurilor.

Cauta (1-3), curata (4-6), cazuri speciale (7-8)1Confirmadf -h, df -i2Directoare maridu -xh3Exploreazancdu -rx /4Loguri, jurnalvacuum, truncate5APT, kerneluriclean, autoremove6Dockerprune, limite loguri7Fisiere sterselsof +L18Inoduridu --inodes
Procedura in opt pasi: pasii 1-3 doar analizeaza, pasii 4-6 curata, pasii 7 si 8 trateaza cazurile speciale. Numerele corespund titlurilor pasilor de mai jos.

Daca preferi un arbore de decizie, asa se leaga pasii intre ei, in functie de ce iti arata df la Pasul 1:

No space left on devicePasul 1: df -h si df -iBlocuri pline: Use% 100%Inoduri pline: IUse% 100%Pasii 2-3: du si ncduPasul 8: du --inodesdu mult mai mic decat dfPasul 7: lsof +L1Directoare mari gasitePasii 4-6: curatenieMilioane de fisiere micifind -mtime -delete
Flux de diagnostic: Pasul 1 iti spune daca s-au terminat blocurile sau inodurile, pasii 2 si 3 gasesc spatiul, apoi pasii 4-6, Pasul 7 sau Pasul 8 il elibereaza.

Prim ajutor daca discul e chiar acum la 100%

Daca discul e complet plin, nici macar instalarea unui utilitar de diagnostic nu merge, pentru ca apt are nevoie de spatiu ca sa descarce. Aceste doua comenzi sunt sigure pe orice server Debian sau Ubuntu si iti dau de obicei cateva sute de megabytes cu care sa lucrezi:

sudo apt clean
sudo journalctl --vacuum-size=100M

Prima sterge pachetele descarcate care sunt deja instalate, a doua reduce jurnalul de sistem la aproximativ 100 MB. Pasii 4 si 5 le explica in detaliu. Acum sa gasim adevaratul vinovat.

Pasul 1: Confirma ce s-a umplut cu df

df (disk free) listeaza fiecare filesystem montat, cu dimensiunea si gradul de ocupare. Ascundem filesystem-urile virtuale (tmpfs sta in RAM, squashfs e folosit de snap-uri, overlay apartine de Docker) ca rezultatul sa ramana lizibil:

df -hT -x tmpfs -x devtmpfs -x squashfs -x overlay

-h afiseaza dimensiunile in format usor de citit, iar -T adauga tipul filesystem-ului. Un server cu probleme arata cam asa:

Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/vda1      ext4   39G   37G     0 100% /
/dev/vda15     vfat  124M   12M  113M  10% /boot/efi

Linia care conteaza e cea cu / in coloana “Mounted on”. Observa ca 37G ocupat plus 0 disponibil inseamna mai putin de 39G: asta e spatiul rezervat pentru root despre care vorbeam. Daca ai un /boot separat sau un disc de date montat, de exemplu, la /srv, verifica si acele linii. Un /boot plin e un motiv clasic pentru care actualizarile de kernel esueaza.

Acum verifica inodurile:

df -ih -x tmpfs -x devtmpfs -x squashfs -x overlay
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/vda1        2.5M  311K  2.2M   13% /

Daca Use% e mare, continua cu Pasul 2. Daca IUse% e la sau aproape de 100%, iar Use% arata normal, sari direct la Pasul 8. Pe Ubuntu, daca omiti filtrul -x squashfs, vei vedea cateva dispozitive /dev/loop la 100%. Sunt imagini snap read-only, care sunt mereu “pline” prin design, deci ignora-le.

Intr-un container LXC neprivilegiat, filesystem-ul radacina poate aparea sub alt nume (un dataset ZFS sau un dispozitiv loop, de exemplu), iar numarul de inoduri poate parea urias sau poate aparea ca o liniuta. E normal, reflecta stocarea de pe host.

Pasul 2: Gaseste directoarele mari cu du

du (disk usage) aduna dimensiunea fisierelor dintr-un director. Ii cerem dimensiunea fiecarui director de pe primul nivel, ramanem pe filesystem-ul radacina cu -x (ca sa sara peste /proc, /sys si alte montari) si sortam rezultatul:

sudo du -xh --max-depth=1 / 2>/dev/null | sort -h | tail -n 15

2>/dev/null ascunde zgomotul de tip “permission denied” de la fisierele speciale, sort -h intelege dimensiuni ca 512M sau 2.3G, iar tail pastreaza cele mai mari intrari, care ajung la final:

16K     /lost+found
1.1G    /home
2.3G    /usr
31G     /var
35G     /

Aici /var e clar problema, asa ca mergem un nivel mai jos si urmam mereu ce e mai mare:

sudo du -xh --max-depth=1 /var 2>/dev/null | sort -h | tail -n 10
410M    /var/cache
2.4G    /var/log
27G     /var/lib
31G     /var

Apoi /var/lib si asa mai departe, pana ajungi la un director pe care il recunosti, cum ar fi /var/lib/docker, /var/log/journal sau /var/lib/mysql. Ca sa listezi fisiere mari individuale de pe tot filesystem-ul, find e foarte util:

sudo find / -xdev -type f -size +200M -exec ls -lh {} + 2>/dev/null | sort -k5 -h

Comanda afiseaza fiecare fisier mai mare de 200 MB, sortat dupa dimensiune. Descoperiri tipice: dump-uri de baze de date uitate, backup-uri .tar.gz vechi intr-un director home, fisiere de log uriase si imagini de discuri virtuale.

Pasul 3: Exploreaza interactiv cu ncdu

Sa rulezi du iar si iar functioneaza, dar ncdu face aceeasi treaba intr-un ecran interactiv prin care navighezi cu sagetile. Se gaseste in depozitele standard atat pe Debian, cat si pe Ubuntu:

sudo apt update
sudo apt install -y ncdu
sudo ncdu -rx /

-x il tine pe un singur filesystem, iar -r il porneste in mod read-only, adica fara posibilitatea de a sterge. Iti recomandam insistent -r la inceput: e mult prea usor sa apesi d in directorul gresit. Dupa scanare primesti o lista sortata:

--- / ---------------------------------------------------
   27.1 GiB [##########] /var
    2.3 GiB [          ] /usr
    1.1 GiB [          ] /home

Foloseste sagetile si Enter ca sa deschizi directoare, sageata stanga ca sa te intorci, c ca sa vezi cate fisiere contine fiecare director (util pentru Pasul 8), ? pentru ajutor si q ca sa iesi. Noteaza-ti caile care te surprind.

Pe langa curateniile din pasii urmatori, iata si ceilalti suspecti obisnuiti pe care ncdu ii scoate la iveala:

  • Backup-uri si dump-uri vechi in /root, /home/* sau /srv: fisiere *.sql, *.sql.gz sau *.tar.gz care trebuiau sa fie temporare. Copiaza-le de pe server daca inca ai nevoie de ele, apoi sterge-le.
  • Crash dump-uri in /var/lib/systemd/coredump, daca systemd-coredump e instalat. coredumpctl list le afiseaza, si pot fi sterse cand nu mai ai nevoie sa depanezi crash-ul.
  • Cache-uri de utilizator precum ~/.cache, ~/.npm sau ~/.cache/pip. Se pot sterge fara grija, se reconstruiesc la nevoie.
  • Binary log-uri de baza de date langa datele MySQL sau MariaDB. Nu sterge niciodata aceste fisiere de mana, vezi sectiunea de depanare.

Pasul 4: Curata logurile si jurnalul systemd

Linux tine doua tipuri de loguri. Jurnalul systemd e un log binar gestionat de journald si citit cu journalctl. Logurile text clasice stau in /var/log si sunt rotite (redenumite, comprimate si in final sterse) de logrotate.

Aici distributiile difera. Pe Debian 13, rsyslog nu e instalat implicit, deci jurnalul e logul principal al sistemului, salvat persistent in /var/log/journal, si nu exista /var/log/syslog. Pe Ubuntu 24.04, rsyslog e si el instalat, asa ca majoritatea mesajelor sunt scrise de doua ori: o data in jurnal si o data in /var/log/syslog. Ambele variante pot umple un disc mic daca nimeni nu pune o limita.

Mai intai, vezi cat de mari sunt:

sudo journalctl --disk-usage
sudo du -sh /var/log/* 2>/dev/null | sort -h | tail -n 10
Archived and active journals take up 1.7G in the file system.

Acum micsoreaza jurnalul. --rotate inchide fisierul de jurnal curent ca sa poata fi curatat si el, apoi --vacuum-size sterge cele mai vechi fisiere arhivate pana cand totalul scade sub limita:

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

Rezultatul listeaza fiecare fisier sters si se termina cu o linie de genul Vacuuming done, freed 1.5G of archived journals. Daca preferi sa pastrezi o fereastra de timp in loc de o dimensiune, foloseste --vacuum-time=2weeks.

Vacuum-ul rezolva problema o singura data. Ca limita sa fie permanenta, adauga un mic fisier drop-in in loc sa editezi journald.conf principal (daca ai deja un fisier al tau in acel director, adauga setarea in el in loc sa creezi un al doilea):

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

De acum, journald pastreaza cel mult aproximativ 300 MB. Urmeaza logurile text. Fisierele rotite se termina in .1, .2.gz si asa mai departe, si pot fi sterse fara grija. Mereu fa intai o previzualizare, apoi ruleaza aceeasi comanda cu -delete:

sudo find /var/log -type f \( -name "*.gz" -o -name "*.[0-9]" \) -mtime +7 -print
sudo find /var/log -type f \( -name "*.gz" -o -name "*.[0-9]" \) -mtime +7 -delete

Daca problema e un singur log activ care a crescut enorm, de exemplu access log-ul unui web server, nu il sterge cu rm. Programul inca are fisierul deschis si pastreaza spatiul alocat (Pasul 7 explica de ce). Goleste-l pe loc:

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

Apoi rezolva cauza: o aplicatie ramasa pe logging de debug, un bot care iti bombardeaza site-ul sau o regula de logrotate care lipseste. sudo logrotate -d /etc/logrotate.conf ruleaza logrotate in mod debug, care nu schimba nimic si iti arata ce ar face, un mod rapid sa verifici daca logul tau e acoperit.

Pasul 5: Curata cache-ul APT si kernelurile vechi

Cand apt instaleaza sau actualizeaza pachete, pastreaza fisierele .deb descarcate in /var/cache/apt/archives. Dupa instalare nu mai e nevoie de ele:

sudo du -sh /var/cache/apt
sudo apt clean

apt clean nu afiseaza nimic cand reuseste. E mereu sigura, in cel mai rau caz apt descarca din nou un fisier mai tarziu.

Kernelurile aduc un castig mai mare pe serverele KVM. Fiecare actualizare de kernel instaleaza un pachet nou langa cele vechi, iar fiecare versiune impreuna cu modulele ocupa cateva sute de megabytes. Mai intai vezi ce kernel ruleaza si care sunt instalate:

uname -r
dpkg -l 'linux-image-*' | awk '/^ii/{print $2, $3}'

Daca cel mai nou kernel instalat e mai nou decat cel afisat de uname -r, reporneste intai serverul ca sa ruleze efectiv kernelul nou. Pe Ubuntu, fisierul /var/run/reboot-required exista cand e nevoie de un reboot. Debian nu creeaza intotdeauna acest fisier, asa ca pe Debian reporneste pur si simplu daca de la ultimul boot s-a instalat un pachet linux-image nou. Dupa reboot, lasa apt sa stearga ce nu mai e necesar:

sudo apt autoremove --purge

Citeste lista inainte sa raspunzi Y. Atat Debian, cat si Ubuntu protejeaza kernelul care ruleaza si pe cel mai nou (de multe ori si o versiune anterioara, ca rezerva), deci ar trebui sa vezi doar versiuni vechi de linux-image, linux-modules sau linux-headers si dependente ramase. Nu sterge niciodata kernelul raportat de uname -r.

Intr-un container LXC nu exista deloc pachete de kernel, pentru ca containerul foloseste kernelul host-ului. dpkg -l 'linux-image-*' nu returneaza nimic si poti sari peste aceasta parte.

Pe Ubuntu se aduna si snap-urile, pentru ca snapd pastreaza revizii mai vechi ale fiecarui snap. Poti sterge reviziile dezactivate si ii poti spune lui snapd sa pastreze mai putine pe viitor:

snap list --all | awk '/disabled/{print $1, $3}' | while read -r name rev; do sudo snap remove "$name" --revision="$rev"; done
sudo snap set system refresh.retain=2

Pasul 6: Curata resturile Docker

Daca folosesti Docker, incepe cu propria lui contabilitate:

docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          23        6         9.8GB     7.1GB (72%)
Containers      7         6         210MB     12MB (5%)
Local Volumes   9         5         3.4GB     1.2GB (35%)
Build Cache     41        0         2.3GB     2.3GB

Coloana RECLAIMABLE arata ce poti recupera. Curata in aceasta ordine, fiecare comanda cere confirmare:

docker container prune
docker image prune -a
docker builder prune

docker container prune sterge containerele oprite, deci daca ai un container oprit pe care vrei sa il pornesti din nou, sari peste aceasta comanda. docker image prune -a sterge orice imagine nefolosita de un container existent (fara -a sterge doar imaginile “dangling”, fara tag). docker builder prune goleste cache-ul de build. Fiecare comanda se termina cu o linie Total reclaimed space.

Ai grija cu volumele, pentru ca acolo stau datele containerelor: baze de date, upload-uri, configuratii. Incepand cu Docker Engine 23, docker volume prune sterge doar volumele anonime nefolosite, in timp ce docker volume prune -a le sterge si pe cele cu nume. Ruleaza docker volume ls si afla ce contine fiecare volum inainte sa stergi ceva, si nu sterge niciodata de mana fisiere din /var/lib/docker: foloseste mereu comenzile docker.

Celalalt mare consumator din Docker sunt logurile containerelor. Implicit, fiecare container scrie intr-un fisier JSON fara limita de dimensiune. Gaseste-le pe cele mai mari (e nevoie de sh -c pentru ca doar root poate citi acel director, deci wildcard-ul trebuie expandat ca root):

sudo sh -c 'du -h /var/lib/docker/containers/*/*-json.log' | sort -h | tail -n 5
docker ps -a --no-trunc --format '{{.ID}}  {{.Names}}'

ID-ul lung din cale iti spune despre ce container e vorba. Ca masura de urgenta poti goli un log pe loc cu sudo truncate -s 0 /var/lib/docker/containers/<id>/<id>-json.log. Rezolvarea permanenta e o limita in /etc/docker/daemon.json. Daca fisierul exista deja, adauga aceste chei in el in loc sa il suprascrii:

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

Valideaza si aplica:

sudo dockerd --validate --config-file=/etc/docker/daemon.json
sudo systemctl restart docker

Prima comanda ar trebui sa afiseze configuration OK. Repornirea Docker reporneste pentru scurt timp si containerele, asa ca fa asta intr-un moment linistit. Noua limita se aplica doar containerelor create dupa modificare, deci recreeaza-le din directorul fiecarui proiect Compose cu docker compose up -d --force-recreate. Poti seta aceeasi limita si per serviciu, in compose.yaml:

services:
  app:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

Inca doua observatii. Pe instalarile Docker mai noi, care folosesc containerd image store, datele imaginilor pot sta in /var/lib/containerd in loc de /var/lib/docker, iar comenzile docker de mai sus le curata oricum. Iar daca rulezi Docker intr-un container LXC, verifica docker info --format '{{.Driver}}': daca raspunsul e vfs, fiecare strat de imagine e o copie completa, ceea ce poate ocupa de cateva ori mai mult spatiu decat overlay2.

Pasul 7: Gaseste fisierele sterse care inca ocupa spatiu

Iata cazul care ii surprinde pe toti: df spune ca discul e plin, dar totalurile din du sau ncdu sunt mult mai mici. De obicei, diferenta e facuta de fisiere care au fost sterse in timp ce un program inca le avea deschise.

Pe Linux, stergerea unui fisier elimina doar numele lui din director. Spatiul se elibereaza abia cand ultimul program care tine fisierul deschis il inchide. Deci daca cineva ruleaza rm pe un log de 10 GB in timp ce nginx sau o aplicatie inca scrie in el, numele dispare si du nu il mai numara, dar blocurile raman alocate pana cand acel proces reporneste. lsof listeaza aceste fisiere:

sudo apt install -y lsof
sudo lsof -nP +L1

+L1 inseamna “fisiere cu mai putin de un link”, adica fisiere sterse:

COMMAND  PID     USER   FD   TYPE DEVICE   SIZE/OFF NLINK   NODE NAME
nginx   1234 www-data    5w   REG  252,1 8589934592     0 131090 /var/log/nginx/access.log (deleted)

SIZE/OFF e in bytes, aici 8 GB. Solutia cea mai curata e sa repornesti sau sa reincarci serviciul care tine fisierul:

sudo systemctl restart nginx

Daca nu il poti reporni chiar acum (o baza de date ocupata, de exemplu), poti goli fisierul sters prin descriptorul de fisier al procesului. PID-ul e 1234, iar coloana FD arata 5w, deci numarul descriptorului e 5:

sudo truncate -s 0 /proc/1234/fd/5

Ruleaza din nou df -h / si spatiul s-a intors. Intr-un container LXC, lsof vede doar procesele containerului, exact ce iti trebuie.

Pasul 8: Rezolva epuizarea inodurilor

Daca la Pasul 1 IUse% era la 100%, nu ai prea multe date, ai prea multe fisiere. Fiecare fisier, oricat de mic, foloseste un inod, iar pe ext4 numarul de inoduri e fixat la crearea filesystem-ului. Gaseste directorul cu cele mai multe fisiere:

sudo du --inodes -x --max-depth=1 / 2>/dev/null | sort -n | tail -n 10

Coboara exact ca la Pasul 2, in /var, apoi in /var/lib si asa mai departe. In ncdu, apasa C (majuscula) ca sa sortezi dupa numarul de elemente. Vinovatii tipici sunt fisierele de sesiune PHP dintr-un director de sesiuni personalizat, o coada de mail plina de mesaje care nu pot fi livrate in /var/spool/postfix, directoare de cache ale aplicatiilor cu milioane de fisiere mici si fisiere temporare pe care un script defect nu le sterge niciodata.

Cu milioane de fisiere, rm * esueaza cu “Argument list too long”. Foloseste find, fa intai o previzualizare, si doar intr-un director pe care l-ai identificat clar ca fiind cache sau date temporare:

sudo find /var/www/example/cache -type f -mtime +7 -print | head
sudo find /var/www/example/cache -type f -mtime +7 -delete

Inlocuieste calea cu a ta. Pentru cozile de mail foloseste uneltele serverului de mail, nu find: cu Postfix, sudo postqueue -p afiseaza coada, iar sudo postsuper -d ALL deferred sterge mesajele amanate. Apoi rezolva cauza, de obicei un job de curatenie care lipseste, altfel inodurile se umplu din nou in cateva zile.

Pe Debian si Ubuntu, sesiunile PHP din directorul implicit /var/lib/php/sessions sunt curatate de timer-ul phpsessionclean, dar doar acolo. Daca aplicatia ta salveaza sesiunile in alta parte, nu le curata nimeni in afara de tine.

Cum previi problema pe viitor

Curatenia e doar jumatate din treaba, cealalta jumatate e sa afli de problema la 85%, nu la 100%. Daca ai urmat pasii, ai limitat deja jurnalul (Pasul 4) si logurile Docker (Pasul 6). Acum adauga o mica verificare care te avertizeaza din timp. Scriptul de mai jos scrie un avertisment pentru fiecare filesystem real care depaseste 85% ca spatiu sau ca inoduri:

sudo tee /usr/local/bin/disk-check >/dev/null <<'EOF'
#!/bin/sh
# disk-check: scrie un avertisment cand spatiul sau inodurile depasesc LIMIT procente
LIMIT=85
for mode in "" "-i"; do
  df -P $mode -x tmpfs -x devtmpfs -x squashfs -x overlay 2>/dev/null |
    awk -v limit="$LIMIT" -v mode="$mode" 'NR > 1 {
      use = $5; sub("%", "", use)
      if (use != "-" && use + 0 >= limit) {
        what = (mode == "-i") ? "inoduri" : "spatiu"
        printf "%s %s la %s%%\n", $6, what, use
      }
    }'
done | while read -r line; do
  logger -t disk-check "AVERTISMENT: $line"
done
EOF
sudo chmod +x /usr/local/bin/disk-check

Ruleaza-l la fiecare 30 de minute cu un timer systemd. Timer-ele functioneaza la fel pe Debian si Ubuntu si nu depind de faptul ca cron e sau nu instalat:

sudo tee /etc/systemd/system/disk-check.service >/dev/null <<'EOF'
[Unit]
Description=Avertisment cand discul se umple

[Service]
Type=oneshot
ExecStart=/usr/local/bin/disk-check
EOF

sudo tee /etc/systemd/system/disk-check.timer >/dev/null <<'EOF'
[Unit]
Description=Ruleaza disk-check la fiecare 30 de minute

[Timer]
OnBootSec=5min
OnUnitActiveSec=30min

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now disk-check.timer

Testeaza cu sudo /usr/local/bin/disk-check, urmat de sudo journalctl -t disk-check. Cat timp totul e sub 85% nu apare nimic, asa ca scade temporar LIMIT daca vrei sa vezi un avertisment. Un avertisment in jurnal ajuta doar daca il citeste cineva, deci leaga-l de monitorizarea pe care o ai deja, de exemplu adaugand in script un apel curl catre URL-ul unui monitor de tip push, sau setand in tool-ul de monitorizare o alerta direct pe ocuparea discului. Ca regula generala, pastreaza cel putin 15-20% din disc liber: bazele de date si actualizarile de pachete au nevoie de loc ca sa functioneze.

Cand curatenia nu e suficienta: mareste discul

Uneori spatiul chiar e ocupat de date reale, iar solutia corecta e un disc mai mare. Pe un VPS KVM, dupa ce discul virtual a fost marit (de exemplu prin trecerea la un plan mai mare), partitia si filesystem-ul trebuie extinse ca sa foloseasca noul spatiu:

lsblk
sudo apt install -y cloud-guest-utils
sudo growpart /dev/vda 1
sudo resize2fs /dev/vda1

lsblk afiseaza discul si partitiile lui ca sa confirmi numele, growpart extinde partitia 1 de pe /dev/vda pana la capatul discului, iar resize2fs mareste filesystem-ul ext4 online, fara demontare. Ajusteaza dispozitivul si numarul partitiei dupa ce iti arata lsblk. Daca filesystem-ul radacina e XFS, foloseste sudo xfs_growfs / in loc de resize2fs, iar cu LVM procedura e diferita. Multe imagini cloud extind automat partitia radacina la boot, asa ca verifica intai df -h dupa upgrade. Fa un backup inainte sa redimensionezi ceva. Intr-un container LXC redimensionarea se face pe host, noua dimensiune apare imediat in container si nu ai nimic de rulat.

Depanare si greseli frecvente

“No space left on device”, dar df arata spatiu liber

Verifica intai inodurile (Pasul 8). Apoi tine minte ca eroarea se refera la filesystem-ul in care scria programul, care poate fi un /boot, /tmp sau disc de date separat, nu /. Ruleaza df -h /calea/care/a/esuat ca sa vezi filesystem-ul corect. In fine, un serviciu care ruleaza ca utilizator normal se loveste de limita celor 5% rezervati, in timp ce root inca vede putin spatiu liber.

df si du nu se potrivesc

In majoritatea cazurilor e vorba de Pasul 7. Daca lsof +L1 nu arata nimic, spatiul poate fi ascuns sub un punct de montare: fisierele scrise intr-un director inainte ca un disc sa fie montat peste el sunt invizibile pentru du. Un bind mount al lui / iti permite sa te uiti dedesubt (inlocuieste /srv cu punctul tau de montare):

sudo mkdir -p /mnt/rootonly
sudo mount --bind / /mnt/rootonly
sudo du -sh /mnt/rootonly/srv
sudo umount /mnt/rootonly

Bind mount-urile nu sunt permise in containerele LXC neprivilegiate, asa ca aceasta verificare merge doar pe servere KVM.

Vacuum-ul jurnalului n-a eliberat aproape nimic

Probabil ai sarit peste journalctl --rotate, asa ca fisierul activ nu a putut fi curatat. Daca journalctl --disk-usage mentioneaza /run/log/journal, jurnalul e tinut in RAM si nu e deloc problema discului tau.

Spatiul nu revine dupa ce stergi fisiere

Un proces care ruleaza inca le tine deschise (Pasul 7). Pe btrfs sau ZFS, si snapshot-urile pastreaza datele sterse pana cand snapshot-ul e eliminat.

Cel mai mare director e o baza de date

Nu sterge niciodata fisiere din /var/lib/mysql sau /var/lib/postgresql. Pentru binary log-urile MySQL sau MariaDB, conecteaza-te cu sudo mysql (autentificare prin socket, implicita pentru MariaDB pe Debian si Ubuntu) sau cu credentiale dintr-un fisier de optiuni precum ~/.my.cnf, niciodata cu -p<parola> in linia de comanda, apoi ruleaza PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY; si seteaza binlog_expire_logs_seconds ca sa nu se mai repete. La PostgreSQL, un pg_wal urias inseamna de obicei un replication slot blocat sau o comanda de arhivare care esueaza: investigheaza cauza in loc sa stergi fisiere WAL.

Sa reduc spatiul rezervat de ext4?

Il poti vedea cu sudo tune2fs -l "$(findmnt -no SOURCE /)" | grep -i 'reserved block count'. Lasa cei 5% pe filesystem-ul radacina, sunt marja ta de siguranta. Pe un disc mare, folosit doar pentru date, e rezonabil sa il reduci la 1% cu sudo tune2fs -m 1 /dev/vdb1. In containere LXC nu se poate.

Note de securitate

  • Previzualizeaza inainte sa stergi. Foloseste -print inainte de -delete, porneste ncdu cu -r si evita rm -rf cu variabile sau wildcard-uri ca root. Un spatiu ratacit intr-o cale transforma o stergere tintita intr-un dezastru.
  • Logurile sunt dovezi. Un disc care se umple brusc poate fi semnul unei compromiteri: un val de brute-force in logurile SSH, un script de spam care umple coada de mail, un crypto miner care lasa fisiere in /tmp. Inainte sa stergi loguri suspecte, arhiveaza-le si copiaza-le de pe server (inlocuieste calea cu logurile care te intereseaza):
sudo tar -czf ~/logs-evidence.tar.gz /var/log/nginx
sudo chown "$USER": ~/logs-evidence.tar.gz

chown conteaza pentru ca o arhiva creata cu sudo apartine lui root, iar utilizatorul tau normal nu ar putea-o copia cu scp altfel. Pe Debian 13, unde login-urile SSH ajung in jurnal, exporta-le cu sudo journalctl -u ssh --since "2 days ago" > ~/ssh-journal.txt. Copiaza fisierele pe calculatorul tau, apoi sterge-le de pe server.

  • Nu umbla in bazele de date ale sistemului. Nu sterge niciodata nimic din /var/lib/dpkg, /var/lib/docker sau din directoarele de date ale bazelor de date. Foloseste apt, docker si comenzile proprii ale bazei de date.
  • Fa backup volumelor inainte de prune. Un volum Docker cu nume sters din greseala nu mai poate fi recuperat, nu exista cos de gunoi.
  • Limiteaza logging-ul, nu il dezactiva. Daca opresti logurile ca sa castigi spatiu, ramai orb la urmatorul incident.
  • Lucreaza ca utilizator sudo, nu intr-un shell de root permanent, ca fiecare comanda distructiva sa fie un sudo constient.

Deci, ai discul sub control?

Acum ai o rutina pe care o poti repeta pentru orice linux disk full fix: confirmi cu df, localizezi cu du si ncdu, cureti jurnalul, logurile, cache-ul APT, kernelurile vechi si resturile Docker, si verifici cele doua cazuri speciale, fisierele sterse dar deschise si epuizarea inodurilor. Cu journald si logurile Docker limitate si cu o mica verificare a discului care ruleaza la fiecare 30 de minute, urmatorul “No space left on device” ar trebui sa vina ca un avertisment din timp, nu ca o cadere.

Daca discul actual iti ramane mic, un VPS de la noi are loc de crestere si poate fi marit odata cu datele tale. Iar daca preferi sa nu mai urmaresti deloc ocuparea discului, echipa noastra de administrare servere iti poate configura limitele de loguri, monitorizarea si curateniile, si le poate tine sub observatie pentru tine.

Intrebari frecvente

E sigur sa sterg fisiere din /var/log?

Fisierele rotite si comprimate (.1, .gz) pot fi sterse fara grija. Logurile active trebuie golite cu truncate -s 0, nu sterse cu rm, altfel spatiul ramane ocupat pana cand programul reporneste. Nu sterge niciodata de mana directorul /var/log/journal, foloseste journalctl --vacuum-size.

Cat spatiu liber ar trebui sa pastreze un server Linux?

Tinteste spre cel putin 15-20%. Bazele de date au nevoie de loc pentru tabele temporare si loguri de tranzactii, iar actualizarile de pachete despacheteaza fisiere inainte sa le inlocuiasca pe cele vechi. Un server tinut permanent peste 90% va cadea pana la urma in cel mai prost moment posibil.

apt clean sau apt autoremove pot strica ceva?

apt clean sterge doar pachetele descarcate, deci e mereu sigura. apt autoremove --purge elimina pachetele de care nu mai depinde nimic, inclusiv kernelurile vechi, protejand kernelul care ruleaza. Citeste lista afisata inainte sa confirmi, mai ales daca ai instalat software manual.

De ce df arata 100% cand du arata mult mai putin?

Cel mai des, un proces tine inca deschis un fisier sters, vezi Pasul 7 si lsof +L1. Mai rar, fisierele sunt ascunse sub un punct de montare, sau snapshot-uri btrfs ori ZFS pastreaza datele sterse.

Pot sterge /var/lib/docker/overlay2 ca sa eliberez spatiu?

Nu. Stergerea manuala a fisierelor de acolo strica evidenta pe care Docker o tine despre imagini si containere. Foloseste docker system df ca sa vezi ce se poate recupera si comenzile docker ... prune de la Pasul 6 ca sa eliberezi spatiul in siguranta.

Avem Incredere & Suntem Membri

Suntem membri ai principalelor organizatii de infrastructura internet.

RIPE NCC MANRS PeeringDB RoTLD DSIX SBIX 4IXP LOCIX Euro-IX RIPE NCC MANRS PeeringDB RoTLD DSIX SBIX 4IXP LOCIX Euro-IX