Ipoteza: fișiere șterse, dar încă deschise
Având în vedere informațiile furnizate până acum și sugerând prezența unui volum mare de fișiere legate de docker, aș bănui că acest lucru este cauzat de fișierele șterse, dar încă deschise, adică fișierele care sunt create de un program, apoi programul șterge calea sistemului de fișiere în timp ce descriptorul de fișier este încă deschis.
Acesta poate fi rezultatul activității Docker pe sistemul de fișiere.
Principiul soluției
- Dezvăluie fișierele șterse care sunt încă referite de procese (vezi mai jos pentru o modalitate).
- În mod ideal, dezvăluiți numele proceselor și/sau ID-ul, astfel încât să aveți indicii despre ceea ce se întâmplă.
- Închideți acele procese, observați că spațiul este eliberat.
- Dacă toate celelalte nu reușesc, pur și simplu reporniți mașina. Dacă spațiul este eliberat, acest lucru este în concordanță cu ipoteza.
Cum să dezvăluiți informațiile
Comenzile de mai jos vor testa ipoteza prin găsirea și afișarea spațiului folosit de ce fișier.
Prima privire
Pentru o privire de bază, puteți emite acest lucru:
lsof -n | egrep -w „șters|^COMANDĂ”
Dar aceasta va enumera și o mulțime de pseudo-fișiere doar în memorie care nu ocupă spațiu de stocare real.
Exemplu:
COMANDĂ PID TID TASKCMD UTILIZATOR TIP FD DIMENSIUNEA DISPOZITIV/OPRIT NUMELE NODULUI
Xorg 1183 root 78u REG 0,1 4 2058 /memfd:xshmfence (șters)
Xorg 1183 root 85u REG 0,1 4 7182 /memfd:xshmfence (șters)
Xorg 1183 root 92u REG 0,1 4 7137 /memfd:xshmfence (șters)
Xorg 1183 root 94u REG 0,1 4 7870 /memfd:xshmfence (șters)
Listă simplă filtrată
Aceasta filtrează și arată în mare parte fișiere reale:
lsof -F "sn" -lnPX -M | sed -n 's|^n/|/|p' | grep șters | egrep -v '^/(dev/shm|memfd:|proc)' | LC_ALL=C sortare -n | unic
Exemplu:
/tmp/#someinodenumber (șters)
Informații complete, cu dimensiunea, procesul și numele sarcinii
Acest lucru este mai interesant: va lista toate fișierele împreună cu spațiul pe care îl ocupă în octeți și nu numai.
În primul rând, partea lentă, adună date
# Poate doriți să rulați această parte ca root pentru a vă asigura că totul este raportat
lsof -F "ctsupMin" -lnPX -M >|/tmp/lfosoutput
Apoi procesați și formatați pentru un afișaj frumos, complet și sortat prin creșterea dimensiunii
# Poate fi rulat ca utilizator obișnuit, nu este nevoie de root
{ echo "SIZE^UID^PID^PROCESS NAME^TASK NAME^INODE^PATH"
</tmp/lfosoutput \
python3 -c $'import sys ; f={}
def g(c): return f.get(c,"(necunoscut)")
pentru linia în sys.stdin:
c=linie[0]; r=linie[1:].rstrip() ; f[c]=r
dacă c=="n" și f["t"]=="REG" \
și „(șters)” în f[”n”] \
și nu f["n"].startswith("/memfd:") \
și nu f["n"].startswith("/dev/shm"):
print(f'\''{g("s")}^{g("u")}^{g("p")}^\"{g("c")}\"^\"{ g("M")}\"^{g("i")}^{g("n")}'\'')
f={}' \
| LC_ALL=C sortare -n | unic
echo "SIZE^UID^PID^PROCESS NAME^TASK NAME^INODE^PATH"
} | coloana -t -s '^'
Exemplu de ieșire: un fișier de 36 de megaocteți utilizat de Firefox
DIMENSIUNE UID PID NUME PROCES NUME SARCINA INODE CALEA
36012032 1234 12345 „Isolated Web Co” „StyleThread#2” 1234567 /tmp/mozilla-temp-12345 (șters)
DIMENSIUNE UID PID NUME PROCES NUME SARCINA INODE CALEA
(De fapt, există multe linii ca acestea, aceasta este doar o linie de probă.)
Testarea dacă scriptul dezvăluie într-adevăr astfel de fișiere prin crearea unuia
Într-un alt terminal, copiați și lipiți asta:
# Rulați interpretul interactiv Python
python3
# Acum în Python
n="/tmp/whatever_file_name_you_want"
f=open(n,mode='a')
import os
os.unlink(n)
f.write(„o propoziție”)
f.flush()
# Nu ieși acum sau fișierul va dispărea cu adevărat
În primul terminal puteți rula ambii pași de mai sus (lsof lentă, apoi partea de formatare).
Și atâta timp cât procesul python de mai sus este viu, această linie este raportată:
DIMENSIUNE UID PID NUME PROCES NUME SARCINA INODE CALEA
13 1000 1387343 „python3” „gdbus” 1308894 /tmp/whatever_file_name_you_want (șters)
DIMENSIUNE UID PID NUME PROCES NUME SARCINA INODE CALEA
Puteți apoi să părăsiți interpretul Python de mai sus (apăsați Control-D
sau tip ieșire(0)
). Dacă rulați ambele părți (lsof lentă apoi partea de formatare) veți observa că fișierul de test nu mai apare.
Scriptul de mai sus poate fi modificat pentru a scrie cantități uriașe de date (cum ar fi sute de gigaocteți) și folosind instrumentele obișnuite, veți vedea că spațiul este într-adevăr eliberat numai după ce procesul de creare a închis descriptorul fișierului. Încheierea procesului este suficientă pentru a vă asigura că descriptorul fișierului este închis.
Înapoi la cazul tău
Rulând acest lucru, cel mai probabil veți vedea nume de proces, nume de sarcini și fișiere. Fie câteva fișiere mari, cum ar fi imaginile pe care Docker le-a preluat din rețea, sau un număr mare de fișiere mici, din nou din Docker.
Sau altceva.
Vă rugăm să spuneți dacă acest lucru vă ajută.