Encontre e remova arquivos grandes que estão abertos mas foram apagados

103

Como alguém encontra arquivos grandes que foram excluídos, mas ainda estão abertos em um aplicativo? Como se pode remover esse arquivo, mesmo que um processo o abra?

A situação é que estamos executando um processo que está preenchendo um arquivo de log a uma taxa ótima. Eu sei o motivo e posso consertar. Até então, eu gostaria de rm ou esvaziar o arquivo de log sem desligar o processo.

A simples execução de rm output.log remove apenas as referências ao arquivo, mas continua ocupando espaço no disco até que o processo seja encerrado. Pior: depois de rm ing agora não tenho como encontrar onde está o arquivo ou quão grande ele é! Existe alguma maneira de encontrar o arquivo e, possivelmente, esvaziá-lo, mesmo que ele ainda esteja aberto em outro processo?

Eu especificamente me refiro a sistemas operacionais baseados em Linux como o Debian ou o RHEL.

    
por dotancohen 20.03.2013 / 08:31

3 respostas

123

Se você não conseguir matar seu aplicativo, poderá truncar em vez de excluir o arquivo de log para recuperar o espaço. Se o arquivo não estava aberto no modo de acréscimo (com O_APPEND ), o arquivo aparecerá tão grande quanto antes da próxima vez que o aplicativo gravar nele (embora com a parte principal esparso e parecendo conter bytes NUL), mas o espaço terá sido recuperado (isso não se aplica aos sistemas de arquivos HFS + no Apple OS / X que não suportam arquivos esparsos).

Para truncá-lo:

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

Se já foi excluído, no Linux, você ainda pode truncá-lo fazendo:

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

Em que $pid é o ID do processo que tem o arquivo aberto e $fd um descritor de arquivo no qual ele foi aberto (que você pode verificar com lsof -p "$pid" .

Se você não conhece o pid e está procurando por arquivos excluídos, pode fazer:

lsof -nP | grep '(deleted)'

lsof -nP +L1 , como mencionado por @ user75021 é uma opção ainda melhor (mais confiável e mais portátil) (lista de arquivos com menos de um link).

Ou (no Linux):

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

Ou para encontrar os grandes com zsh :

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

Uma alternativa, se o aplicativo for vinculado dinamicamente, é anexar um depurador a ele e chamá-lo de close(fd) seguido por um novo open("the-file", ....) .

    
por 20.03.2013 / 09:42
25

Confira o início rápido aqui: lsof início rápido

Estou surpreso que ninguém tenha mencionado o arquivo lsof quickstart (incluído no lsof). A seção "3.a" mostra como encontrar arquivos abertos e desvinculados:

lsof -a +L1 *mountpoint*

Por exemplo:

[root@enterprise ~]# 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)

Nos sistemas da Red Hat para encontrar a cópia local do arquivo de início rápido, geralmente faço isso:

[root@enterprise ~]# locate -i quickstart |grep lsof
/usr/share/doc/lsof-4.78/00QUICKSTART

... ou isto:

[root@enterprise ~]# 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
    
por 10.07.2014 / 00:15
1

Cabe ao driver do sistema de arquivos, na verdade, liberar o espaço alocado, o que geralmente ocorre somente uma vez que todos descritores de arquivos referentes a esse arquivo sejam liberados. Então você não pode realmente recuperar o espaço, a menos que você faça o aplicativo fechar o arquivo. O que significa terminá-lo ou brincar com ele "um pouco" em um depurador (por exemplo, fechando o arquivo e certificando-se de que não seja aberto / gravado novamente ou abrindo /dev/null ). Ou você poderia hackear o kernel, mas eu aconselharia contra isso.

Truncar o arquivo como Stephane sugere pode ajudar, mas o resultado real também dependerá do seu sistema de arquivos (por exemplo, blocos pré-alocados provavelmente só serão liberados depois que você fechar o arquivo).

A lógica por trás desse comportamento é que o kernel não saberia o que fazer com solicitações de dados (leitura e gravação, mas a leitura é realmente mais crítica) visando esse arquivo.

    
por 20.03.2013 / 09:42