Como um programa de log pode continuar registrando em um arquivo excluído?

10

Do Unix Power Tools, 3ª edição : Em vez de remover um arquivo, Esvazie a seção :

If an active process has the file open (not uncommon for log files), removing the file and creating a new one will not affect the logging program; those messages will just keep going to the file that’s no longer linked. Emptying the file doesn’t break the association, and so it clears the file without affecting the logging program.

( ênfase minha )

Não entendo por que um programa continuará registrando em um arquivo excluído. É porque a entrada do descritor de arquivo não foi removida da tabela de processos?

    
por Geek 28.07.2014 / 09:46

3 respostas

10

Quando você apaga um arquivo, você realmente remove um link para o arquivo (para o inode). Se alguém já tiver esse arquivo aberto, ele poderá manter o descritor de arquivo que possui. O arquivo permanece no disco, ocupando espaço e pode ser gravado e lido se você tiver acesso a ele.

A unlink function é definida com esse comportamento por POSIX:

When the file's link count becomes 0 and no process has the file open, the space occupied by the file shall be freed and the file shall no longer be accessible. If one or more processes have the file open when the last link is removed, the link shall be removed before unlink() returns, but the removal of the file contents shall be postponed until all references to the file are closed.

Este conselho por causa desse comportamento. O daemon terá o arquivo aberto e não notará que ele foi excluído (a menos que esteja monitorando especificamente, o que é incomum). Ele vai continuar escrevendo alegremente para o descritor de arquivo existente: você continuará ocupando (mais) espaço no disco, mas você não poderá ver nenhuma das mensagens que escreve, então você está realmente no pior. dos dois mundos. Se você truncar o arquivo para comprimento zero, o espaço será liberado imediatamente e todas as novas mensagens serão adicionadas na nova extremidade do arquivo, onde você poderá vê-las.

Eventualmente, quando o daemon termina ou close s o arquivo , o espaço será liberado. Ninguém pode abrir o arquivo nesse meio tempo (exceto por meio de interfaces reflexivas específicas do sistema, como /proc/x/fd/... do Linux ). Também é garantido que:

If the link count of the file is 0, when all file descriptors associated with the file are closed, the space occupied by the file shall be freed and the file shall no longer be accessible.

Assim, você não perde seu espaço em disco permanentemente, mas não ganha nada excluindo o arquivo e perde o acesso a novas mensagens.

    
por 28.07.2014 / 09:55
7

Exatamente.

Os arquivos são tripartidos.

  • O conteúdo, isto é, uma matriz simples de bytes, escritos em algum lugar em um disco ou gerados on-the-fly.
  • O nó de índice , ou inode para abreviar, que é uma estrutura de dados preenchida e usada pelo kernel. Ele contém todos os metadados (tamanho, permissão, etc.) sobre o arquivo e também aponta para o local do conteúdo do arquivo.
  • Uma ou mais entradas de diretório , que são locais, manipuladas como caminhos como /home/user/personal_file , que funcionam como identificadores pelos quais você pode usar o arquivo, modificar seu conteúdo , altere seus metadados, etc.

Quando você abre um arquivo, você fornece o caminho para o sistema operacional e retorna um identificador diretamente para o inode. Com esse identificador, chamado de descritor de arquivo, você pode manipular o arquivo como quiser (ou pelo menos, conforme permitido pelo SO).

Você nunca pode apagar diretamente um inode, você tem que dar um caminho ao sistema operacional para exigir a exclusão. Portanto, quando você deseja excluir um arquivo, exclua apenas a entrada do diretório. Se o arquivo tiver outras entradas de diretório, ele continuará sendo acessível e, mesmo que não tenha, seu inode não será excluído enquanto ainda houver descritores de arquivo apontando para ele. @ A resposta de MichaelHomer é mais técnica e mais detalhada sobre este tópico específico.

    
por 28.07.2014 / 10:03
4

As outras duas respostas explicam bem o problema - um arquivo não é "excluído" até que todos os links de diretório para ele e todos os descritores de arquivos abertos tenham desaparecido.

Para evitar isso, é um bom hábito usar

> /var/log/bigfile

em vez de

rm -f /var/log/bigfile

desde que apenas redefina o conteúdo para 0 bytes em vez de excluí-lo, e você ainda pode ver o que está escrito nele.

Se você deletou o arquivo, e está no linux onde você tem um sistema de arquivos / proc / fd, você ainda pode usar

> /proc/12345/fd/3

para zerar o conteúdo do arquivo (supondo que 12345 é o seu id do processo e 3 é o número fd do arquivo grande). Isso pode ser um salva-vidas se o seu disco estiver cheio e você não puder matar o processo que está gravando o seu arquivo de log por algum motivo.

    
por 28.07.2014 / 16:02