Antecedentes: servidor físico, aproximadamente dos años de antigüedad, unidades SATA de 7200 RPM conectadas a una tarjeta RAID 3Ware, ext3 FS montado noatime y data = ordenado, no bajo carga loca, kernel 2.6.18-92.1.22.el5, tiempo de actividad 545 días . El directorio no contiene ningún subdirectorio, solo millones de archivos pequeños (~ 100 bytes), con algunos más grandes (algunos KB).
Tenemos un servidor que se ha vuelto un poco loco en el transcurso de los últimos meses, pero solo lo notamos el otro día cuando comenzó a no poder escribir en un directorio debido a que contenía demasiados archivos. Específicamente, comenzó a arrojar este error en / var / log / messages:
ext3_dx_add_entry: Directory index full!
El disco en cuestión tiene muchos inodos restantes:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 60719104 3465660 57253444 6% /
Supongo que eso significa que llegamos al límite de cuántas entradas pueden estar en el archivo de directorio. No tengo idea de cuántos archivos serían, pero no puede ser más, como puede ver, más de tres millones. ¡No es que eso sea bueno, eso sí! Pero esa es la primera parte de mi pregunta: ¿cuál es exactamente ese límite superior? ¿Es sintonizable? Antes de gritar en Las-Quiero ajustarlo hacia abajo ; Este enorme directorio causó todo tipo de problemas.
De todos modos, rastreamos el problema en el código que estaba generando todos esos archivos, y lo hemos corregido. Ahora estoy atascado con la eliminación del directorio.
Algunas opciones aquí:
rm -rf (dir)
Intenté esto primero. Me di por vencido y lo maté después de que hubiera funcionado durante un día y medio sin ningún impacto perceptible.
- unlink (2) en el directorio: Definitivamente vale la pena considerarlo, pero la pregunta es si sería más rápido eliminar los archivos dentro del directorio a través de fsck que eliminarlos a través de unlink (2). Es decir, de una forma u otra, tengo que marcar esos inodes como no utilizados. Esto supone, por supuesto, que puedo decirle a fsck que no suelte entradas a los archivos en / lost + found; de lo contrario, acabo de mover mi problema. Además de todas las otras preocupaciones, después de leer un poco más sobre esto, resulta que probablemente tenga que llamar a algunas funciones internas de FS, ya que ninguna de las variantes de Unlink (2) que puedo encontrar me permitiría eliminar alegremente un directorio con entradas en el mismo. Pooh
while [ true ]; do ls -Uf | head -n 10000 | xargs rm -f 2>/dev/null; done )
Esta es en realidad la versión abreviada; el verdadero que estoy ejecutando, que solo agrega algunos informes de progreso y una parada limpia cuando nos quedamos sin archivos para eliminar, es:
exportar i = 0; tiempo (mientras [verdadero]; hacer ls -Uf | cabeza -n 3 | grep -qF '.png' || rotura; ls -Uf | cabeza -n 10000 | xargs rm -f 2> / dev / null; exportar i = $ (($ i + 10000)); echo "$ i ..."; hecho )
Esto parece estar funcionando bastante bien. Mientras escribo esto, ha eliminado 260,000 archivos en los últimos treinta minutos más o menos.
- Como se mencionó anteriormente, ¿se puede ajustar el límite de entrada por directorio?
- ¿Por qué tardó "7m9.561s reales / usuario 0m0.001s / sys 0m0.001s" para eliminar un solo archivo que fue el primero en la lista devuelto por
ls -U
, y tardó tal vez diez minutos en eliminar las primeras 10.000 entradas con el comando en el n. ° 3, pero ahora se está transportando muy felizmente. Para el caso, eliminó 260,000 en aproximadamente treinta minutos, pero ahora le tomó otros quince minutos eliminar 60,000 más. ¿Por qué los enormes cambios de velocidad? - ¿Hay una mejor manera de hacer este tipo de cosas? No almacenar millones de archivos en un directorio; Sé que es una tontería, y no habría sucedido en mi reloj. Buscar en Google el problema y mirar SF y SO ofrece muchas variaciones
find
que no van a ser significativamente más rápidas que mi enfoque por varias razones evidentes. Pero, ¿la idea delete-via-fsck tiene piernas? ¿O algo completamente diferente? Estoy ansioso por escuchar el pensamiento fuera de la caja (o dentro de la caja no conocida).
Salida del guión final !:
2970000...
2980000...
2990000...
3000000...
3010000...
real 253m59.331s
user 0m6.061s
sys 5m4.019s
Entonces, tres millones de archivos eliminados en poco más de cuatro horas.
rm -rfv | pv -l >/dev/null
. pv debería estar disponible en el repositorio EPEL .