¿Cómo se encuentran archivos grandes que se han eliminado pero que todavía están abiertos en una aplicación? ¿Cómo se puede eliminar dicho archivo, a pesar de que un proceso lo tiene abierto?
La situación es que estamos ejecutando un proceso que está llenando un archivo de registro a una velocidad excelente. Sé el motivo y puedo solucionarlo. Hasta entonces, me gustaría rm o vaciar el archivo de registro sin cerrar el proceso.
Simplemente hacerlo rm output.log
elimina solo las referencias al archivo, pero continúa ocupando espacio en el disco hasta que finaliza el proceso. Peor aún: rm
¡ahora no tengo forma de encontrar dónde está el archivo o qué tan grande es! ¿Hay alguna forma de encontrar el archivo y posiblemente vaciarlo, aunque todavía esté abierto en otro proceso?
Me refiero específicamente a los sistemas operativos basados en Linux como Debian o RHEL.
fuente
lsof -p <pid>
para enumerar sus archivos abiertos y sus tamaños. El archivo eliminado tendrá un al(deleted)
lado. El archivo eliminado se vinculará/proc/<pid>/fd/1
probablemente. No sé cómo hacer que un proceso deje de escribir en su descriptor de archivo sin terminarlo. Creo que eso dependería del proceso.rm
archivos ed que todavía están abiertos?lsof | grep "(deleted)"
. Cuando no haya más procesos que mantengan abierto un archivo eliminado, el núcleo liberará el inodo y los bloques de disco. Los procesos no tienen "controladores" mediante los cuales se les puede notificar que un archivo abierto, esencialmente bloqueado, se ha eliminado del disco.lsof | grep '(deleted)'
funciona en Linux. En Linux, puede recibir notificaciones de eliminación de archivos (incluso archivos que ya no tienen ninguna entrada en ningún directorio que no sea / proc / some-pid / fd) con el mecanismo de inotificación (evento IN_DELETE_SELF)somefile
y lo abrí en VIM, luego lorm
edité en otro proceso bash. Luego ejecutolsof | grep somefile
y no está allí, a pesar de que el archivo está abierto en VIM.Respuestas:
Si no puede eliminar su aplicación, puede truncar en lugar de eliminar el archivo de registro para recuperar el espacio. Si el archivo no estaba abierto en modo de agregado (con
O_APPEND
), el archivo aparecerá tan grande como antes la próxima vez que la aplicación lo escriba (aunque con la parte inicial dispersa y pareciendo que contenía bytes NUL), pero el espacio habrá sido reclamado (eso no se aplica a los sistemas de archivos HFS + en Apple OS / X que no admiten archivos dispersos).Para truncarlo:
Si ya se eliminó, en Linux, aún puede truncarlo haciendo:
¿Dónde
$pid
está la identificación del proceso que tiene el archivo abierto, y$fd
un descriptor de archivo con el que lo tiene abierto (con el que puede consultarlsof -p "$pid"
.Si no conoce el pid y está buscando archivos eliminados, puede hacer lo siguiente:
lsof -nP +L1
, como lo menciona @ user75021 es una opción aún mejor (más confiable y más portátil) (enumere los archivos que tienen menos de 1 enlace).O (en Linux):
O para encontrar los grandes con
zsh
:Una alternativa, si la aplicación está vinculada dinámicamente es adjuntarle un depurador y hacer que llame
close(fd)
seguido de un nuevoopen("the-file", ....)
.fuente
truncate
comando que hace lo mismo de manera más explícita.lsof
probablemente será la solución más cercana a una solución portátil que pueda obtener para enumerar los archivos abiertos. el enfoque del depurador para cerrar el fd debajo de los pies de la aplicación también debería ser bastante portátil.df -k | awk 'NR>1 { print $NF }' | xargs fuser -Vud
(y luego es fácil enviar señales a los delincuentes para obligarlos a liberar el fd)lsof +L1
. Desde la página de manual de lsof: "Una especificación del formulario+L1
seleccionará los archivos abiertos que se han desvinculado. Una especificación del formulario+aL1 <file_system>
seleccionará los archivos abiertos no vinculados en el sistema de archivos especificado". Eso debería ser un poco más confiable que grepping.Mira el inicio rápido aquí:
lsof
Inicio rápidoMe sorprende que nadie haya mencionado el archivo de inicio rápido lsof (incluido con lsof). La sección "3.a" muestra cómo encontrar archivos abiertos no vinculados:
P.ej:
En los sistemas Red Hat para encontrar la copia local del archivo de inicio rápido, generalmente hago esto:
... o esto:
fuente
Depende del controlador del sistema de archivos liberar el espacio asignado, y eso generalmente sucederá solo una vez que se liberen todos los descriptores de archivo que se refieren a ese archivo. Por lo tanto, realmente no puede reclamar el espacio, a menos que haga que la aplicación cierre el archivo. Lo que significa terminarlo o jugar con él "un poco" en un depurador (por ejemplo, cerrar el archivo y asegurarse de que no se abre / escribe de nuevo, o se abre en su
/dev/null
lugar). O podrías hackear el kernel, pero te aconsejaría que no.Truncar el archivo como sugiere Stephane podría ayudar, pero el resultado real también dependerá de su sistema de archivos (por ejemplo, los bloques preasignados probablemente se liberarán solo después de cerrar el archivo en cualquier caso).
La razón detrás de este comportamiento es que el núcleo no sabría qué hacer con las solicitudes de datos (tanto de lectura como de escritura, pero la lectura es realmente más crítica) dirigida a dicho archivo.
fuente
fallocate
Linux 4.9. ¿Puede aclarar bajo qué sistema de archivos y condición truncar un archivo no reclama espacio?