Como encontrar arquivos grandes que foram excluídos, mas ainda estão abertos em um aplicativo? Como remover um arquivo desse tipo, mesmo que um processo o abra?
A situação é que estamos executando um processo que está preenchendo um arquivo de log a uma taxa fantástica. Eu sei o motivo e posso corrigi-lo. Até então, eu gostaria de rm ou esvaziar o arquivo de log sem desligar o processo.
Simplesmente rm output.log
remove apenas referências ao arquivo, mas continua ocupando espaço no disco até que o processo seja finalizado. Pior: depois de rm
ing agora não tenho como descobrir onde o arquivo está ou qual o tamanho dele! Existe alguma maneira de encontrar o arquivo e possivelmente esvaziá-lo, mesmo que ainda esteja aberto em outro processo?
Refiro-me especificamente a sistemas operacionais baseados em Linux, como Debian ou RHEL.
fonte
lsof -p <pid>
listar seus arquivos abertos e seus tamanhos. O arquivo excluído terá um(deleted)
próximo a ele. O arquivo excluído será/proc/<pid>/fd/1
provavelmente vinculado . Não sei como fazer com que um processo pare de gravar no descritor de arquivo sem finalizá-lo. Eu pensaria que isso dependeria do processo.rm
arquivos ed que ainda estão abertos?lsof | grep "(deleted)"
. Quando não houver mais processos mantendo um arquivo excluído aberto, o kernel liberará os blocos de inode e disco. Os processos não têm "manipuladores" pelos quais eles podem ser notificados de que um arquivo aberto, essencialmente bloqueado, foi removido do disco.lsof | grep '(deleted)'
funciona no Linux. No Linux, você pode ser notificado sobre a exclusão de arquivos (mesmo os arquivos que já não têm mais nenhuma entrada em nenhum diretório que não seja o / proc / some-pid / fd) com o mecanismo inotify (evento IN_DELETE_SELF)somefile
e abri no VIM erm
editei em outro processo do bash. Em seguida, corrolsof | grep somefile
e ele não está lá, mesmo que o arquivo esteja aberto no VIM.Respostas:
Se você não conseguir eliminar seu aplicativo, poderá truncar em vez de excluir o arquivo de log para recuperar o espaço. Se o arquivo não foi aberto no modo de acréscimo (com
O_APPEND
), o arquivo aparecerá tão grande quanto antes na próxima vez que o aplicativo gravar nele (embora com a parte principal esparsa e parecendo conter NUL bytes), mas o espaço terá sido recuperado (que não se aplica aos sistemas de arquivos HFS + no Apple OS / X que ainda não suportam arquivos esparsos).Para truncá-lo:
Se já foi excluído, no Linux, você ainda pode truncá-lo fazendo:
Onde
$pid
está a identificação do processo que abriu o arquivo e$fd
um descritor de arquivo em que foi aberto (com o qual você pode verificarlsof -p "$pid"
.Se você não conhece o pid e está procurando por arquivos excluídos, pode:
lsof -nP +L1
, como mencionado por @ user75021, é uma opção ainda melhor (mais confiável e mais portátil) (listar arquivos com menos de 1 link).Ou (no Linux):
Ou para encontrar os grandes com
zsh
:Uma alternativa, se o aplicativo estiver vinculado dinamicamente, é anexar um depurador a ele e fazer com que ele seja
close(fd)
seguido por um novoopen("the-file", ....)
.fonte
truncate
comando que faz a mesma coisa mais explicitamente.lsof
provavelmente será o mais próximo de uma solução portátil que você pode listar arquivos abertos. a abordagem do depurador para fechar o fd sob os pés do aplicativo também deve ser bastante portátil.df -k | awk 'NR>1 { print $NF }' | xargs fuser -Vud
(e então fácil para enviar sinais para os infratores para forçá-los a liberar a fd)lsof +L1
. Na página man lsof: "Uma especificação do formulário+L1
selecionará arquivos abertos que foram desvinculados. Uma especificação do formulário+aL1 <file_system>
selecionará arquivos abertos não vinculados no sistema de arquivos especificado.". Isso deve ser um pouco mais confiável que o grepping.Confira o início rápido aqui:
lsof
Início rápidoEstou 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:
Por exemplo:
Nos sistemas Red Hat para encontrar a cópia local do arquivo de início rápido, geralmente faço o seguinte:
... ou isto:
fonte
Depende do driver do sistema de arquivos liberar realmente o espaço alocado, e isso geralmente acontecerá apenas quando todos os descritores de arquivo referentes a esse arquivo forem liberados. Portanto, você não pode realmente recuperar o espaço, a menos que faça com que o aplicativo feche o arquivo. O que significa encerrá-lo ou brincar com ele "um pouco" em um depurador (por exemplo, fechando o arquivo e certificando-se de que ele não seja aberto / gravado novamente ou abrindo
/dev/null
). Ou você pode invadir o kernel, mas eu desaconselharia 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 serão liberados somente depois que você fechar o arquivo, em qualquer caso).
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.
fonte
fallocate
no Linux 4.9. Você pode esclarecer em que sistema de arquivos e condição o truncamento de um arquivo não recupera espaço?