Como o Linux atualiza pacotes que estão em uso?

3

Estou usando o Arch Linux e posso fazer uma atualização do sistema enquanto navego na net, por exemplo. Como o pacote do navegador pode ser atualizado se o próprio programa estiver em uso? Ou o Kernel por exemplo? O executável não precisa ser interrompido para ser substituído por um novo? Ou isso acontece na próxima reinicialização?

    
por nuhaga 11.01.2015 / 10:01

2 respostas

8

Os arquivos do navegador no disco são substituídos. O programa em execução (se não estiver completamente na memória) mantém os arquivos executáveis antigos abertos até que o programa seja fechado (mas até então esses não são mais os arquivos executáveis que você obtém por meio das entradas de diretório). Na próxima reinicialização do navegador, você obtém a versão.

Nenhuma reinicialização é necessária, exceto o programa que é carregado na reinicialização (ou seja, o kernel). Há programas que corrigem o kernel no lugar, sem exigir uma reinicialização para isso, mas isso não é a mesma coisa.

    
por 11.01.2015 / 10:11
7

Como você suspeitava, sistemas semelhantes ao Unix impedem que a maioria dos arquivos que estão sendo executados sejam sobrescritos. Veja o que a norma diz sobre a chamada do sistema aberta:

The open() function may fail if:

[ETXTBSY] The file is a pure procedure (shared text) file that is being executed and oflag is O_WRONLY or O_RDWR.

Mas um arquivo sendo executado ainda pode ser desvinculado , e é assim que os gerenciadores de pacotes fazem seu trabalho.

Veja o que o dpkg no Debian e no Ubuntu faz ao instalar a nova versão do /bin/cpio que acabou de sair:

open("/bin/cpio.dpkg-new", O_WRONLY|O_CREAT|O_EXCL, 0) = 10
// lots of reads and writes omitted from this listing.
// It's copying the new version into dpkg-new
fchown(10, 0, 0)                  = 0 
fchmod(10, 0755)                  = 0 
close(10)                         = 0 
rename("/bin/cpio.dpkg-new", "/bin/cpio") = 0 

Em detalhes, isso:

  • copia a nova versão para cpio.dpkg-new no mesmo diretório que cpio .
  • define as permissões de proprietário e arquivo para o que o pacote disser que deve ser
  • renomeia cpio.dpkg-new para cpio

A maneira de instalar com segurança uma nova versão de um arquivo sem estar na posição do arquivo que não existe, mesmo que por um instante, é usar o renomear chamada de sistema. Isso requer que ambos os arquivos estejam no mesmo sistema de arquivos, e é por isso que o dpkg criou a nova versão do cpio no mesmo diretório da versão antiga. O padrão diz:

int rename(const char *old, const char *new);

The rename() function shall change the name of a file. The old argument points to the pathname of the file to be renamed. The new argument points to the new pathname of the file.

If the link named by the new argument exists, it shall be removed and old renamed to new. In this case, a link named new shall remain visible to other processes throughout the renaming operation and refer either to the file referred to by new or old before the operation began.

A terminologia pode ser um pouco confusa porque os arquivos old e novos dados para rename aqui são a nova versão do cpio e a versão antiga do cpio , respectivamente.

Por fim, aqui está a chave para responder sua pergunta:

If the link named by the new argument exists and the file's link count becomes 0 when it is removed 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 rename() returns, but the removal of the file contents shall be postponed until all references to the file are closed.

A última frase significa que, se algum processo tiver cpio aberto (ou estiver sendo executado) quando o rename for concluído, ele continuará a ver o conteúdo anterior do arquivo até que ele feche o arquivo (ou saia).

O pacman do Arch parece fazer praticamente a mesma coisa:

snprintf(checkfile, len, "%s.paccheck", filename);
...
if(perform_extraction(handle, archive, entry, checkfile, entryname_orig)) {
    errors++;
    goto needbackup_cleanup;
}
...
if(try_rename(handle, checkfile, filename)) {
    errors++;
}

Não obstante os esforços dos gerenciadores de pacotes para instalar novos arquivos com segurança, pode haver alguns problemas quando um programa é atualizado enquanto estiver em uso. O pacote firefox, por exemplo, tem mais de uma dúzia de executáveis e objetos compartilhados. Alguém executando uma versão antiga do firefox durante uma atualização pode descobrir que uma extensão que ele chama após a conclusão da atualização é incompatível com a versão antiga do Firefox. Atualizei recentemente o firefox no Ubuntu e o apt-get foi impresso:

Please restart all running instances of firefox, or you will experience problems.

Se você é um administrador de sistema de um sistema multiusuário, é uma boa ideia anunciar atualizações pendentes para a comunidade de usuários.

    
por 11.01.2015 / 20:21