Aquidiz que você pode reescrever um arquivo executável e o processo funcionará perfeitamente - ele será relido quando um processo for reiniciado.
No entanto, quando tento substituir um arquivo binário enquanto o processo está em execução (com scp, do dev para o servidor de teste), ele diz 'arquivo ocupado'. E se eu substituir um arquivo de biblioteca compartilhada (*.so), todos os processos que o vinculam travam.
Por quê então? Estou esquecendo de algo? Como posso substituir os arquivos binários sem parar/travar um processo?
Responder1
Como mencionado emPor que um pacote de software funciona perfeitamente mesmo quando está sendo atualizado?, o bloqueio é colocado no inode e não no nome do arquivo. Quando você carrega e executa um binário, o arquivo é marcado como ocupado - e é por isso que você recebe o erro ETXTBSY (arquivo ocupado) ao tentar gravar nele.
Agora, para bibliotecas compartilhadas é um pouco diferente: as bibliotecas são mapeadas na memória no espaço de endereço do processo com mmap()
. Embora MAP_DENYWRITE
possa ser especificado, pelo menos o Glibc no Linux o ignora silenciosamente (de acordo com a página de manual, sinta-se à vontade para verificar as fontes) - verifique istofio. Portanto, você realmente tem permissão para gravar o arquivo e, como ele é mapeado na memória, quaisquer alterações são visíveis quase imediatamente - o que significa que se você se esforçar o suficiente, poderá conseguir tijolosua máquina substituindo a biblioteca.
A maneira correta de atualizar, portanto, é:
remover o arquivo, que remove a referência aos dados do sistema de arquivos, para que não fique acessível para nenhum aplicativo recém-gerado que queira usá-lo, enquanto mantém os dados acessíveis para qualquer pessoa que já os tenha aberto (ou mapeado) ;
criando um novo arquivo com conteúdo atualizado.
Os processos recém-criados usarão o conteúdo atualizado, os aplicativos em execução acessarão a versão antiga. Isso é o que qualquer utilitário de gerenciamento de pacotes sensato faz. Observe que isso não é totalmente isento de perigo - por exemplo, aplicativos que carregam código dinamicamente (usando dlsym()
e amigos) terão problemas se a API da biblioteca mudar silenciosamente.
Se você quer estar no sério,realmentelado seguro, desligue o sistema, monte o sistema de arquivos de outra instância do sistema operacional, atualize e abra o sistema atualizado novamente.
Responder2
Uma atualização rpm faz o mesmo - executando binários e bibliotecas enquanto nada trava.
Então qual é a diferença:
- desvincular arquivo
- escreva um novo arquivo com o mesmo nome
Isso NÃO substituirá o arquivo no local: O inode referente ao binário em uso ainda estará "ocupado" até que o último objeto que o mantém aberto termine. O novo arquivo será criado com um novo número de inode.
Agora scp
ou cp
tentará substituir o arquivo no local - o que alteraria o conteúdo ao qual o inode está se referindo. Isso não funciona - como você descreveu.