desenv-web-rp.com

Como desativar o `apt-daily.service` na nuvem Ubuntu VM image?

O servidor Ubuntu 16.04 VM aparentemente inicia o "apt-daily.service" a cada 12 horas); esse serviço executa várias tarefas relacionadas ao APT, como atualizar a lista de pacotes disponíveis, realizar atualizações autônomas se necessário, etc.

Ao iniciar a partir de um VM "instantâneo", o serviço é acionado ) imediatamente , como (presumo) o systemd percebe rapidamente que o cronômetro deveria ter disparado há muito tempo.

No entanto, uma execução APT impede que outros processos apt _ sejam executados, pois mantém um bloqueio em /var/lib/dpkg. A mensagem de erro indicando isso é assim:

E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?

Preciso desabilitar esta tarefa automatizada APT até que o Ansible conclua a configuração da máquina (que normalmente envolve a instalação de pacotes)); consulte https://github.com/gc3-uzh-ch/elasticluster/issues/304 para mais informações e contexto.

Tentei várias opções para desativar o recurso "atualizações autônomas" por meio de um script "dados do usuário" para cloud-init, mas todos eles falharam até agora.

1. Desative a tarefa systemd

tarefa systemd apt-daily.service é acionado por apt-daily.timer. Tentei desativar um ou outro, ou ambos, com várias cobinações dos seguintes comandos; ainda, o apt-daily.service é iniciado momentos após o VM ficar pronto para aceitar conexões SSH ::

    #!/bin/bash

    systemctl stop apt-daily.timer
    systemctl disable apt-daily.timer
    systemctl mask apt-daily.service
    systemctl daemon-reload

2. Desative a opção de configuração APT::Periodic::Enable

Roteiro /usr/lib/apt/apt.systemd.daily lê algumas APT; a configuração APT::Periodic::Enable desativa completamente a funcionalidade (linhas 331--337). Eu tentei desativá-lo com o seguinte script:

    #!/bin/bash

    # cannot use /etc/apt/apt.conf.d/10periodic as suggested in
    # /usr/lib/apt/apt.systemd.daily, as Ubuntu distributes the
    # unattended upgrades stuff with priority 20 and 50 ...
    # so override everything with a 99xxx file
    cat > /etc/apt/apt.conf.d/99elasticluster <<__EOF
    APT::Periodic::Enable "0";
    // undo what's in 20auto-upgrade
    APT::Periodic::Update-Package-Lists "0";
    APT::Periodic::Unattended-Upgrade "0";
    __EOF

No entanto, apesar de APT::Periodic::Enable tendo valor 0 na linha de comando (veja abaixo), o unattended-upgrades o programa ainda está em execução ...

    [email protected]:~$ apt-config Shell AutoAptEnable APT::Periodic::Enable
    AutoAptEnable='0'

3. Remova /usr/lib/apt/apt.systemd.daily completamente

Os seguintes cloud-init script remove completamente o script de atualizações autônomas:

    #!/bin/bash

    mv /usr/lib/apt/apt.systemd.daily /usr/lib/apt/apt.systemd.daily.DISABLED

Ainda assim, a tarefa é executada e eu posso vê-la na tabela de processos! embora o arquivo não exista se analisado na linha de comando:

[email protected]:~$ ls /usr/lib/apt/apt.systemd.daily
ls: cannot access '/usr/lib/apt/apt.systemd.daily': No such file or directory

Parece que o cloud-init script (junto com a linha de comando SSH) e o processo root systemd são executados em sistemas de arquivos e espaços de processo separados ...

Questões

Há algo óbvio que estou perdendo? Ou existe alguma mágica de namespace em que eu não conheço?

Mais importante: como posso desativar o apt-daily.service através de um cloud-init roteiro?

70
Riccardo Murri

Sim, havia algo óbvio que estava faltando.

Systemd é tudo sobre o início simultâneo de serviços, então o cloud-init script é executado ao mesmo tempo the apt-daily.service é acionado. Quando chegar a hora cloud-init consegue executar a carga útil especificada pelo usuário, apt-get update já está a correr. Portanto, as tentativas 2. e 3. falharam não por causa de alguma mágica no namespace, mas porque alteraram o sistema tarde demais para apt.systemd.daily para captar as alterações.

Isso também significa que basicamente não há como impedirapt.systemd.daily da execução - só é possível matá-lo depois de iniciado.

Este script "dados do usuário" segue esta rota:

#!/bin/bash

systemctl stop apt-daily.service
systemctl kill --kill-who=all apt-daily.service

# wait until `apt-get updated` has been killed
while ! (systemctl list-units --all apt-daily.service | egrep -q '(dead|failed)')
do
  sleep 1;
done

# now proceed with own APT tasks
apt install -y python

Ainda há uma janela de tempo durante a qual os logins SSH ainda são possíveis apt-get não será executado, mas não consigo imaginar outra solução que funcione na imagem da nuvem do Ubuntu 16.04.

43
Riccardo Murri

Nota: Infelizmente parte da solução abaixo não funciona nos sistemas Ubuntu 16.04 (como o do questionador) porque o sugerido systemd-run invocação só funciona no Ubuntu 18.04 e superior (consulte o comentários para obter detalhes ). Deixarei a resposta aqui porque esta pergunta ainda é um sucesso popular, independentemente da versão do Ubuntu que você está usando ...

No Ubuntu 18.04 (ou superior), pode haver até dois serviços envolvidos no tempo de inicialização para atualizar/atualizar. O primeiro apt-daily.service atualiza a lista de pacotes. No entanto, pode haver um segundo apt-daily-upgrade.service que realmente instala pacotes críticos de segurança. Uma pergunta resposta à pergunta "Terminar e desativar/remover a atualização autônoma antes do retorno do comando" fornece um excelente exemplo de como aguardar a conclusão de ambos (copiada aqui por conveniência):

systemd-run --property="After=apt-daily.service apt-daily-upgrade.service" --wait /bin/true

(observe que isso deve ser executado como root). Se você estiver tentando desativar esses serviços em futuras botas, precisará mascarar AMBOS os serviços:

systemctl mask apt-daily.service apt-daily-upgrade.service

Como alternativa, você pode systemctl disable ambos os serviços E seus cronômetros associados (ou seja, apt-daily.timer e apt-daily-upgrade.timer).

Observe que as técnicas de mascaramento/desativação nesta resposta impedem apenas a atualização/atualização em futuras botas - elas não as pararão se já estiverem em execução na inicialização atual.

17
Anon

Você pode desativar isso através do módulo cloud-init "bootcmd". Isso é executado antes da criação da rede, o que é necessário antes que o apt update possa ter a chance de ser executado.

#cloud-config
bootcmd:
    - echo 'APT::Periodic::Enable "0";' > /etc/apt/apt.conf.d/10cloudinit-disable
    - apt-get -y purge update-notifier-common ubuntu-release-upgrader-core landscape-common unattended-upgrades
    - echo "Removed APT and Ubuntu 18.04 garbage early" | systemd-cat

Depois de fazer o ssh na instância, você também deve aguardar o término das fases finais do cloud-init, pois ele move as fontes/listas apt.

# Wait for cloud-init to finish moving apt sources.list around... 
# a good source of random failures
# Note this is NOT a replacement for also disabling apt updates via bootcmd
while [ ! -f /var/lib/cloud/instance/boot-finished ]; do
    echo 'Waiting for cloud-init to finish...'
    sleep 3
done

Isso também é útil para ver com que antecedência o bootcmd é executado:

# Show microseconds in systemd journal
journalctl -r -o short-precise

Você pode verificar se funcionou da seguinte maneira:

apt-config dump | grep Periodic

# Verify nothing was updated until we run apt update ourselves.
cd /var/lib/apt/lists
Sudo du -sh .   # small size
ls -ltr         # old timestamps
5
Karl Pickett

Não seria mais fácil mascarar a unidade

systemctl mask apt-daily.service

?

2
user192526

Com base na solução da Anon, criei este script, que após ser executado e depois reiniciado, resolve o problema para mim:

#!/bin/sh

systemctl mask apt-daily.service apt-daily-upgrade.service
systemctl disable apt-daily.service apt-daily-upgrade.service
systemctl disable apt-daily.timer apt-daily-upgrade.timer
1
nemesisfixx

Se o objetivo é provisionar a máquina sem incorrer em um erro de bloqueio, a solução mais simples e mais estável é executar o comando remoto do provisionador (ou os comandos relacionados ao apt) enquanto bloqueia o arquivo de bloqueio apt-daily. Nenhum serviço mascarando/desativando/aguardando etc. etc.

No servidor Ubuntu, os programas de atualização de pacotes (apt-daily, upgrades autônomos, cloud-init) passam pelo apt-daily, para que a solução possa ser centrada nele.

O Apt-daily usa flock(2) locks, que, diferentemente do dpkg/apt (que usa fnctl), pode ser gerenciado através de uma ferramenta de linha de comando, com a conveniência de suportar a espera no bloqueio.

Portanto, se um, por exemplo, usa o Chef, é tão simples quanto executar nos nós:

$ Sudo flock /var/lib/apt/daily_lock chef-client

e:

  • qualquer chef-cliente pegará a trava primeiro e qualquer serviço baseado no apt-diariamente esperará;
  • ou qualquer serviço baseado no apt-daily irá bloqueá-lo primeiro, depois o chef-clien esperará e, finalmente, será executado assim que o apt-daily for concluído.

Se o provisionador não for chamado nos nós, é possível modificar a configuração do provisionador (por exemplo, manual Ansible) para executar:

$ Sudo flock /var/lib/apt/daily_lock apt update
$ Sudo flock /var/lib/apt/daily_lock apt upgrade

(ou qualquer variação, como sh -c '...' e assim por diante)

Fonte: https://saveriomiroddi.github.io/Handling-the-apt-lock-on-ubuntu-server-installations .

1
Marcus

Isso aguarda 1 segundo em um loop while e verifica se o bloqueio foi liberado.

while : ; do
                sleep 1
                echo $( ps aux | grep -c lock_is_held ) processes are using apt.
                ps aux | grep -i apt
                [[ $( ps aux | grep -c lock_is_held ) > 2 ]] || break
        done
        echo Apt released
1
Navidzj

Este cloud-init funciona.

#cloud-config
apt:
  conf: |
    APT {
      Periodic {
        Update-Package-Lists "0";
      };
    };
    Unattended-Upgrade {
      Package-Blacklist {
        "*";
      };
    };
runcmd:
  - [ systemctl, stop, apt-daily.timer, apt-daily-upgrade.timer ]
  - [ systemctl, disable, apt-daily.timer, apt-daily-upgrade.timer ]

0
Alexander