desarrollo-web-br-bd.com

Encuentra y elimina archivos grandes que están abiertos pero que han sido eliminados

¿Cómo se encuentran los 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 haciendo rm output.log elimina solo las referencias al archivo, pero continúa ocupando espacio en el disco hasta que finaliza el proceso. Peor: después de rming 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.

124
dotancohen

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 escasa y pareciendo que contenía NUL bytes), 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:

: > /path/to/the/file.log

Si ya se eliminó, en Linux, aún puede truncarlo haciendo:

: > "/proc/$pid/fd/$fd"

Donde $pid Es la identificación del proceso que tiene el archivo abierto, y $fd Un descriptor de archivo en el que lo tiene abierto (¡que puede verificar con lsof -p "$pid".

Si no conoce el pid y está buscando archivos eliminados, puede hacer lo siguiente:

lsof -nP | grep '(deleted)'

lsof -nP +L1, como lo menciona @ user75021 es una opción aún mejor (más confiable y más portátil) (lista de archivos que tienen menos de 1 enlace).

O (en Linux):

find /proc/*/fd -ls | grep  '(deleted)'

O para encontrar los grandes con zsh:

ls -ld /proc/*/fd/*(-.LM+1l0)

Una alternativa, si la aplicación está vinculada dinámicamente es adjuntarle un depurador y hacer que llame a close(fd) seguido de un nuevo open("the-file", ....).

146
Stéphane Chazelas

Vea el inicio rápido aquí: lsof Quickstart

Me 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:

lsof -a +L1 *mountpoint*

P.ej.:

[[email protected] ~]# lsof -a +L1 /tmp
COMMAND   PID   USER   FD   TYPE DEVICE    SIZE NLINK  NODE NAME
httpd    2357 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
mysqld   2588  mysql    4u   REG 253,17      52     0  1495 /tmp/ibY0cXCd (deleted)
mysqld   2588  mysql    5u   REG 253,17    1048     0  1496 /tmp/ibOrELhG (deleted)
mysqld   2588  mysql    6u   REG 253,17       0     0  1497 /tmp/ibmDFAW8 (deleted)
mysqld   2588  mysql    7u   REG 253,17       0     0 11387 /tmp/ib2CSACB (deleted)
mysqld   2588  mysql   11u   REG 253,17       0     0 11388 /tmp/ibQpoZ94 (deleted)
httpd    3457   root   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8437 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8438 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8439 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8440 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8441 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8442 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8443 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8444 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   16990 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   19595 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   27495 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   28142 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   31478 Apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)

En los sistemas Red Hat para encontrar la copia local del archivo de inicio rápido, generalmente hago esto:

[[email protected] ~]# locate -i quickstart |grep lsof
/usr/share/doc/lsof-4.78/00QUICKSTART

... o esto:

[[email protected] ~]# rpm -qd lsof
/usr/share/doc/lsof-4.78/00.README.FIRST
/usr/share/doc/lsof-4.78/00CREDITS
/usr/share/doc/lsof-4.78/00DCACHE
/usr/share/doc/lsof-4.78/00DIALECTS
/usr/share/doc/lsof-4.78/00DIST
/usr/share/doc/lsof-4.78/00FAQ
/usr/share/doc/lsof-4.78/00LSOF-L
/usr/share/doc/lsof-4.78/00MANIFEST
/usr/share/doc/lsof-4.78/00PORTING
/usr/share/doc/lsof-4.78/00QUICKSTART
/usr/share/doc/lsof-4.78/00README
/usr/share/doc/lsof-4.78/00TEST
/usr/share/doc/lsof-4.78/00XCONFIG
/usr/share/man/man8/lsof.8.gz
36
user75021

Depende del controlador del sistema de archivos en realidad libre el espacio asignado, y eso generalmente sucederá solo una vez todos los descriptores de archivo que se refieren a ese archivo se liberan. 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 abrir /dev/null en su 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.

1
peterph