Por que atualizar um sistema Linux em execução não é problemático?

25

Faz anos que uso sistemas Linux diariamente e nunca tive grandes problemas ao atualizar um sistema quando estava em execução, mas ainda me pergunto por que isso é possível.

Deixe-me fazer um exemplo.

Suponha que um programa "A" de um determinado pacote esteja sendo executado em um sistema. Este programa, em um determinado momento, precisa abrir outro arquivo ("B") do mesmo pacote. Depois disso, o programa "A" fecha "B" porque não precisa mais. Suponha que agora eu atualize o pacote "A" e "B" pertencem. "A" não é diretamente afetado por essas operações, pelo menos por enquanto, pois está em execução na RAM e a atualização substituiu "A" no disco rígido. Suponha que "B" também tenha sido substituído no sistema de arquivos. Agora "A" precisa ler "B" novamente por algum motivo. A questão é: é possível que "A" possa encontrar uma versão incompatível de "B" e travar ou apresentar mau funcionamento de alguma outra maneira?

Por que ninguém atualiza seus sistemas reiniciando com um CD ao vivo ou algum procedimento semelhante?

Francesco Turco
fonte
Eu tendem a preferir evitar essas atualizações, não por causa da mecânica da atualização (isso pode ser feito muito bem), mas sim pela preferência por testar meus aplicativos e configuração em relação às alterações, primeiro. Então, eu teria um sistema separado agora atualizado para mudar. Mas, além disso, a atualização na área do usuário geralmente não é um problema e, para pequenas ou correções de segurança, eu faria isso.
Skaperen

Respostas:

23

Atualizar o Userland é raramente um problema

Geralmente, você pode atualizar pacotes em um sistema ativo porque:

  1. As bibliotecas compartilhadas são armazenadas na memória, não lidas do disco em cada chamada, portanto as versões antigas permanecerão em uso até que o aplicativo seja reiniciado.
  2. Na verdade, os arquivos abertos são lidos a partir dos descritores de arquivos , e não dos nomes dos arquivos; portanto, o conteúdo do arquivo permanece disponível para os aplicativos em execução, mesmo quando movidos / renomeados / excluídos até que os setores sejam substituídos ou os descritores de arquivos fechados.
  3. Pacotes que requerem recarga ou reinicialização geralmente são tratados adequadamente pelo gerenciador de pacotes, se o pacote tiver sido bem projetado. Por exemplo, o Debian reiniciará certos serviços sempre que a libc6 for atualizada.

Geralmente, a menos que você esteja atualizando seu kernel e não esteja usando o ksplice, talvez seja necessário reiniciar os programas ou serviços para tirar proveito de uma atualização. No entanto, raramente é necessário reiniciar um sistema para atualizar qualquer coisa na área do usuário, embora em desktops às vezes seja mais fácil do que reiniciar serviços individuais.

Veja também

http://en.wikipedia.org/wiki/Ring_%28computer_security%29#Supervisor_mode

CodeGnome
fonte
Mas o que acontecerá se você precisar de toda a memória cache? Nesse caso, a parte-bibliotecas terão de ser carregado novamente a partir do disco ...
Nils
3
Na verdade, a descrição do nº 1 não era tão clara. O conteúdo antigo do arquivo da biblioteca permanece em um inode (original) separado, mesmo que todos os nomes vinculados a ele tenham desaparecido, desde que algum processo tenha o arquivo aberto ou seu conteúdo mapeado, os dados sejam mantidos distintos (e o sistema de arquivos não pode remontar r / o até que a desvinculação do arquivo seja concluída). O processo que mapeou o arquivo original ainda possui mapeamentos de memória para o conteúdo original.
Skaperen
@ Nils Eu não sou especialista, mas se você ficar sem cache, não seria escrito para trocar e reler a partir daí? Se isso estivesse cheio, provavelmente algum processo seria bloqueado antes que pudesse tirar a memória de outro processo que já o esteja usando.
Joe
@ Joe não - swap é ram ​​também. Skaperen descreve o que acontece: a manipulação de arquivo está sendo mantida intacta. Então, basicamente, o programa tem um problema para a biblioteca antiga, que não será excluída até que o identificador seja liberado novamente - isso tudo é no nível do sistema de arquivos - e não no nível da RAM.
Nils
4

Sim, o que você descreveu é possível, mas na maioria das vezes, se o arquivo estiver incluído no pacote, será uma biblioteca ou outro arquivo que será lido uma vez e apenas uma vez (já que não muda, não há razão para leia-o várias vezes). Além disso, se o arquivo for necessário a longo prazo, o aplicativo provavelmente deixará o identificador de arquivo aberto, no qual, mesmo que seja substituído no sistema de arquivos real, o identificador de arquivo aberto manterá a versão antiga aberta.

Na maioria dos casos, todos os dados lidos várias vezes durante a vida do processo são dados de usuário / variável e isso não muda durante uma atualização do pacote. Além disso, como os dados são variáveis, qualquer programador que esteja em sã consciência garantirá que o programa possa lidar com isso alterando de uma leitura para a seguinte.

Patrick
fonte
O arquivo ainda pode ser lido novamente como "armazenamento de backup" se o mapeamento dele não fizer alterações na memória (que, caso contrário, trocaria o armazenamento de backup para troca, se disponível), e a cópia na memória será descartada devido a outra pressão de demanda para usar memória. Mas isso não é problema, porque o arquivo original ainda está aberto ou mapeado. A biblioteca de substituição é um arquivo novo e diferente que o processo antigo não foi aberto.
Skaperen
1
@ Skaperen Suponho que você esteja falando sobre arquivos mapeados na memória. Estes não são problemas ao atualizar pacotes. Todos os gerenciadores de pacotes criam novos arquivos para substituir os antigos, em vez de substituí-los. De fato, esta é a única maneira de fazê-lo, pois um executável em execução não pode ser modificado, apenas pode ser desvinculado.
Patrick Patrick
4

Suponha que "B" também tenha sido substituído no sistema de arquivos. Agora "A" precisa ler "B" novamente por algum motivo. A questão é: é possível que "A" possa encontrar uma versão incompatível de "B" e travar ou apresentar mau funcionamento de alguma outra maneira?

Isso é possível, mas improvável na maioria dos casos. Se "B" for uma biblioteca de códigos, a versão original normalmente não será fechada. "A" continuaria usando a versão original de "B". Se você executar "A" após a atualização, a nova versão do "B" será usada. Durante a atualização, há algum risco de que versões incompatíveis possam ser carregadas. No entanto, devido à maneira como as bibliotecas de código são carregadas, isso só deve ser um problema se "A" precisar de funcionalidade não presente nas versões de "B" que ele carregou.

Boas práticas de codificação mantêm a interface para funções iguais. Como resultado, não importa muito qual versão é carregada, exceto se houve bugs corrigidos na versão mais recente.

Os arquivos de configuração são um pouco diferentes, mas geralmente são lidos durante a inicialização. Nesse caso, "A" não leria "B" a menos que uma recarga da configuração fosse alterada. Novamente, seria uma prática ruim de codificação alterar o formato ou o significado do arquivo de configuração. Uma versão incompatível do arquivo de configuração deve ter um nome diferente, para não causar problemas.

Por que ninguém atualiza seus sistemas reiniciando com um CD ao vivo ou algum procedimento semelhante?

Desligar e reiniciar a partir de uma versão diferente levaria a uma interrupção do serviço. Para servidores, isso geralmente não é desejado. De qualquer forma, o gerenciador de pacotes no sistema em execução está ciente do software e das versões instaladas. Os CDs ao vivo têm uma lista própria de software instalado, possivelmente com versões diferentes. Isso dificulta a atualização confiável do sistema em execução a partir do CD ao vivo.

Às vezes, os CDs ao vivo são usados ​​quando uma nova versão do sistema operacional está sendo instalada. Nesse caso, a instalação limpa do sistema operacional é geralmente feita. Isso pode limitar a quantidade de arquivos não utilizados da versão anterior que está sendo mantida. Pode ser mais esforço do que atualizar o sistema ativo. No entanto, se diferentes partições raiz forem usadas, isso poderá limitar o risco de travamento com um sistema parcialmente inicializável não inicializável.

BillThor
fonte
0

Existem alguns casos em que isso é um problema:

  • Atualização do JDK enquanto uma VM java está em execução: perguntei ao myselv a mesma pergunta que você fez - eu tinha um tomcat em execução que usa java. Agora, após uma atualização de patch do JDK, ele ainda funcionava sem problemas - pelo que parecia.

Agora a explicação é a memória cache. OK - iniciei um programa de memória-hog para usar toda a RAM disponível - e o tomcat travou (depois de acessar o aplicativo em execução).

  • Atualização do kernel nos sistemas SuSE: no SuSE, o kernel antigo e seus módulos são excluídos logo após a atualização do kernel. Se você quiser usar algo novo, que exija um módulo do kernel, que não foi carregado até agora, o serviço falhará.
Nils
fonte
2
Parece que algumas partes do Tomcat foram reiniciadas ou as bibliotecas dinâmicas foram usadas abaixo do nível do Java (por exemplo, dlopen () e outras)) que podem acabar com uma mistura de APIs ativas.
Skaperen
@Skaperen mesmo quando se usa bibliotecas compartilhadas - se eles se fecharam após o uso de qualquer programa deve ter problemas se o cache está ficando escassa ...
Nils
1
Um descritor de arquivo aberto tem o mesmo poder de reter os dados no disco que um nome para o arquivo em um diretório. O inode original não será excluído enquanto houver um link físico no disco ou um descritor de arquivo aberto. O cache não tem nada a ver com isso. Agora, alguns programas fecham seus descritores de arquivos quando não os estão usando e isso pode deixar os dados desaparecerem.
dmckee
@dmckee Certo. Estamos nos aproximando do núcleo. Então, o que é normal para um programa "normal": abra a biblioteca e mantenha-a aberta ou carregue a biblioteca e feche-a depois?
Nils