Sfondo: server fisico, circa due anni, unità SATA 7200-RPM connesse a una scheda RAID 3Ware, no3 tempo montato su ext3 FS e dati = ordinati, non sotto carico, kernel 2.6.18-92.1.22.el5, uptime 545 giorni . La directory non contiene alcuna sottodirectory, solo milioni di file piccoli (~ 100 byte), con alcuni più grandi (pochi KB).
Abbiamo un server che è diventato un po 'cuculo nel corso degli ultimi mesi, ma l'abbiamo notato solo l'altro giorno quando ha iniziato a non essere in grado di scrivere in una directory perché conteneva troppi file. In particolare, ha iniziato a lanciare questo errore in / var / log / messages:
ext3_dx_add_entry: Directory index full!
Il disco in questione ha molti inode rimanenti:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 60719104 3465660 57253444 6% /
Quindi suppongo che ciò significhi che abbiamo raggiunto il limite di quante voci possono essere nel file di directory stesso. Non ho idea di quanti file sarebbero, ma non può essere più, come puoi vedere, di circa tre milioni. Non che va bene, intendiamoci! Ma questa è la prima parte della mia domanda: che cos'è esattamente quel limite superiore? È sintonizzabile? Prima di sgridato-voglio sintonizzare giù ; questa enorme directory ha causato tutti i tipi di problemi.
Ad ogni modo, abbiamo rintracciato il problema nel codice che stava generando tutti quei file e lo abbiamo corretto. Ora sono bloccato con l'eliminazione della directory.
Alcune opzioni qui:
rm -rf (dir)
L'ho provato prima io. Ho rinunciato e l'ho ucciso dopo che era corso per un giorno e mezzo senza alcun impatto evidente.
- unlink (2) nella directory: vale sicuramente la pena considerare, ma la domanda è se sarebbe più veloce eliminare i file all'interno della directory tramite fsck che eliminarli tramite unlink (2). Cioè, in un modo o nell'altro, devo contrassegnare quegli inode come inutilizzati. Ciò presuppone, ovviamente, che posso dire a fsck di non rilasciare le voci nei file in / lost + found; altrimenti, ho appena spostato il mio problema. Oltre a tutte le altre preoccupazioni, dopo aver letto un po 'di più su questo, si scopre che probabilmente dovrei chiamare alcune funzioni interne di FS, poiché nessuna delle varianti unlink (2) che riesco a trovare mi permetterebbe di cancellare solo allegramente una directory con le voci al suo interno. Pooh.
while [ true ]; do ls -Uf | head -n 10000 | xargs rm -f 2>/dev/null; done )
Questa è in realtà la versione abbreviata; quello vero che sto correndo, che aggiunge solo alcuni rapporti sui progressi e un punto fermo quando finiamo i file da eliminare, è:
esportazione i = 0; tempo (while [true]; do ls -Uf | capo -n 3 | grep -qF '.png' || rompere; ls -Uf | head -n 10000 | xargs rm -f 2> / dev / null; esporta i = $ (($ i + 10000)); echo "$ i ..."; fatto )
Questo sembra funzionare piuttosto bene. Mentre scrivo, negli ultimi trenta minuti circa ha eliminato 260.000 file.
- Come accennato in precedenza, è possibile regolare il limite di voci per directory?
- Perché ci sono voluti "7m9.561s reali / utente 0m0.001s / sys 0m0.001s" per eliminare un singolo file che era il primo nell'elenco restituito
ls -U
e ci sono voluti forse dieci minuti per eliminare le prime 10.000 voci con il comando in # 3, ma ora si trascina abbastanza felicemente? Del resto, ha eliminato 260.000 in circa trenta minuti, ma ora sono necessari altri quindici minuti per eliminarne altri 60.000. Perché le enormi oscillazioni di velocità? - C'è un modo migliore per fare questo genere di cose? Non archiviare milioni di file in una directory; So che è sciocco e non sarebbe successo sul mio orologio. Cercare su Google il problema e guardare attraverso SF e SO offre molte varianti
find
che non saranno significativamente più veloci del mio approccio per diverse ragioni evidenti. Ma l'idea di eliminare-via-fsck ha delle gambe? O qualcos'altro interamente? Sono ansioso di sentire il pensiero fuori dagli schemi (o dentro-non-ben-conosciuto-scatola).
Output dello script finale !:
2970000...
2980000...
2990000...
3000000...
3010000...
real 253m59.331s
user 0m6.061s
sys 5m4.019s
Quindi, tre milioni di file eliminati in poco più di quattro ore.
rm -rfv | pv -l >/dev/null
. pv dovrebbe essere disponibile nel repository EPEL .