Como atualizar a biblioteca compartilhada sem falhas?

18

Aqui diz que você pode reescrever um arquivo executável e o processo será executado corretamente - será relido quando um processo reiniciar.

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 falham.

Por quê então? Estou esquecendo de algo? Como posso substituir os arquivos binários sem parar / travar um processo?

Sam
fonte
Você pode verificar .soarquivo usando ldd filename.soa dependências de verificação
Rahul Patil
Eu sei as dependências. Eu quero uma maneira de substituir esses arquivos sem afetar os processos em execução. Como a pergunta vinculada implica
Sam:
tempo de inatividade é necessária .. ou você pode fazer como stop app && create symlink of .so && start app
Rahul Patil

Respostas:

21

Conforme mencionado em Por que um pacote de software funciona bem 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 mmap(). Embora MAP_DENYWRITEpossa ser especificado, pelo menos o Glibc no Linux o ignora silenciosamente (de acordo com a página do manual, fique à vontade para verificar as fontes) - verifique este tópico . Portanto, você 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á gerenciar a sua máquina em blocos substituindo a biblioteca.

A maneira correta de atualizar, portanto, é:

  1. remover o arquivo, que remove a referência aos dados do sistema de arquivos, para que não fique acessível para aplicativos recém-gerados que possam querer usá-lo, mantendo os dados acessíveis para quem já os tem aberto (ou mapeado) ;

  2. criando um novo arquivo com conteúdo atualizado.

Os processos criados recentemente usarão o conteúdo atualizado, os aplicativos em execução acessarão a versão antiga. É isso que qualquer utilitário de gerenciamento de pacotes sã faz. Observe que não é completamente sem 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ê deseja estar do lado realmente seguro, desligue o sistema, monte o sistema de arquivos a partir de outra instância do sistema operacional, atualize e abra o sistema atualizado novamente.

peterph
fonte
6

Uma atualização de rpm faz o mesmo - com binários e bibliotecas em execução, enquanto nada falha.

Então qual é a diferença:

  1. desvincular arquivo
  2. 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 está "ocupado" até que o último objeto que o mantém aberto seja concluído. O novo arquivo será criado com um novo número de inode.

Agora scpou cptentará 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.

Nils
fonte