substituição de cp vs rm e cp

18

Quando tento sobrescrever um arquivo binário que é iniciado no momento, cpnão sobrescreve, mas é possível fazer rmisso cp. Por exemplo:

user@poste:~$ cp binaryFile /tmp
user@poste:~$ sudo cp /tmp/binaryFile binaryFile 
[sudo] password for user:
cp: cannot create regular file `binaryFile`: Text file busy
user@poste:~$ sudo rm binaryFile 
user@poste:~$ sudo cp /tmp/binaryFile  binaryFile 
user@poste:~$ file binaryFile 
binaryFile : ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x7ce005d9eb50e2574246b6a881e625802f7e49f2, not stripped

Alguma idéia do porquê?

M4rty
fonte
2
Pouco interessante, mas deve estar no Unix / Linux.SE IMO.
underscore_d

Respostas:

41

No primeiro caso, você está tentando substituir o conteúdo de um arquivo que está sendo executado atualmente como um programa. O Linux não permite isso - se o fizesse, você sobrescreveria o código exatamente como o sistema operacional o executava; a primeira diferença poderia travar o programa ou causar um mau funcionamento.

Mas no segundo caso, você não está realmente alterando o conteúdo do arquivo antigo - você está criando um novo arquivo em seu lugar, enquanto o antigo perde o nome do arquivo, mas mantém o conteúdo intocado.

(Lembre-se de que tecnicamenterm não exclui arquivos, apenas remove os links do diretório - semelhante à maneira como adiciona mais links ao mesmo arquivo. Somente quando um arquivo não possui links e nenhuma referência a arquivos abertos, ele é excluído automaticamente.)ln

O sistema faz referência aos arquivos em uso por seu inode, portanto, não importa se eles têm o mesmo nome de arquivo - ainda é o arquivo antigo que permanece aberto pelo sistema e, embora não tenha mais links, será excluído uma vez que todos os programas fechem.

gravidade
fonte
7
Outro truque geralmente usado com a mesma lógica: abra um arquivo (temporário) no seu software e exclua-o imediatamente, sem fechar o arquivo primeiro. Seu programa ainda pode usá-lo da maneira que quiser e quando o programa o fecha (controlado) ou esquece de fechá-lo (por exemplo, seu programa travou sem limpeza), ele será automaticamente removido pelo sistema operacional. (Fim do programa, não importa como isso aconteceu, libera todas as referências ao programa teve para o arquivo.)
Tonny
2
Isso é também porque quando você excluir algum arquivo de log de um processo executando o comando df não retornar o tamanho corrigido até que você parar o processo
M4rty
Existe alguma maneira de um programa externo (com privilégios de root) encontrar e criar um novo identificador para esse inode pendente? Eu imagino que existem programas que usam isso como um "recurso de segurança", por isso é interessante entender a história completa.
BenPen 28/10
3
@BenPen: No Linux, sim - use /proc/*/fdpara acessá-lo e, opcionalmente, linkat () para adicionar um novo link ao sistema de arquivos.
grawity
3
@BenPen e grawity: Na verdade, você não pode vincular um inode de volta à estrutura de diretórios se ele tiver zero links, mesmo que linkat()por razões de segurança . (Exceção a esta regra: a menos que tenha sido criada com open(O_TMPFILE)e iniciada com zero links.) Se você tentar, linkat()retornará ENOENT, mesmo como root. Veja minha resposta nessa pergunta para que um script perl seja realmente executado linkate prove que ele não funciona, mesmo como root: /
Peter Cordes