Como desativar o `apt-daily.service` na imagem da VM na nuvem do Ubuntu?

60

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

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

No entanto, um APT em execução impede a execução de outros aptprocessos, pois mantém um bloqueio /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 desativar essa tarefa automatizada do 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 obter mais informações e contexto.

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

1. Desative a tarefa systemd

A tarefa systemd apt-daily.serviceé acionada por apt-daily.timer. Tentei desativar um ou outro, ou ambos, com várias cobinações dos seguintes comandos; ainda assim, ele apt-daily.serviceé iniciado momentos após a VM estar pronta 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. Desativar opção de configuração APT::Periodic::Enable

O script /usr/lib/apt/apt.systemd.dailylê algumas variáveis ​​de configuração do APT; a configuração APT::Periodic::Enabledesativa 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::Enableter valor 0na linha de comando (veja abaixo), o unattended-upgradesprograma ainda é executado ...

    ubuntu@test:~$ apt-config shell AutoAptEnable APT::Periodic::Enable
    AutoAptEnable='0'

3. Remova /usr/lib/apt/apt.systemd.dailycompletamente

O cloud-initscript a seguir 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:

ubuntu@test:~$ 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-initscript (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 espaço para nome que eu não conheço?

Mais importante ainda: como posso desativar o apt-daily.serviceatravés de um cloud-initscript?

Riccardo Murri
fonte
2
Isso não vai ajudá-lo até que seja lançada em uma atualização oficial do pacote, mas por favor, veja o patch que acabei de publicar no bug # 844453 do Debian .
Zwol 27/03
Talvez você estivesse perdendo a --nowbandeira no systemctl disablecomando para efetivar a alteração imediatamente. Esse foi o meu problema.
19718 Daniel F
@DanielF não, porque disable --nowé equivalente a stopseguido por disable.
precisa saber é o seguinte
11
Aparentemente, isso foi FINALMENTE corrigido no systemd em fevereiro de 2019: github.com/systemd/systemd/issues/5659 . Então, espero que seja no Ubuntu 20.04.
snap

Respostas:

38

Sim, havia algo óbvio que estava faltando.

Systemd é tudo sobre início simultâneo de serviços, de modo que o cloud-initscript é executado ao mesmo tempo o apt-daily.serviceé acionado. Quando cloud-initchega a hora de executar a carga útil especificada pelo usuário, apt-get updatejá está em execução. Portanto, as tentativas 2. e 3. falharam não por causa de alguma mágica do espaço para nome, mas porque alteraram o sistema tarde demais para apt.systemd.dailycaptar as alterações.

Isso também significa que basicamente não há como impedir a apt.systemd.daily execução - só é possível matá-lo após o início.

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 existe uma janela de tempo durante a qual os logins SSH são possíveis e ainda apt-get não serão executados, mas não consigo imaginar outra solução que funcione na imagem de nuvem do Ubuntu 16.04.

Riccardo Murri
fonte
Isso funcionou para mim no AWS ubuntu 16.04, obrigado pela solução
krisdigitx
Sim, estou seguindo o caminho de criar uma AMI personalizada. Isso também acelera a instalação de serviços comuns.
Giorgiosironi
Isso não parece suficiente, acho que ainda existem casos difíceis deapt-get -o Acquire::http::AllowRedirect=false update
Edward Z. Yang
12

Nota: Infelizmente, parte da solução abaixo não funciona nos sistemas Ubuntu 16.04 (como o do questionador) porque a systemd-runchamada sugerida funciona apenas no Ubuntu 18.04 e superior (veja os comentários para 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.serviceatualiza a lista de pacotes. No entanto, pode haver um segundo apt-daily-upgrade.serviceque realmente instala pacotes críticos de segurança. Uma resposta para a 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 disableambos os serviços e seus temporizadores associados (ie apt-daily.timere 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 serão interrompidas se já estiverem em execução na inicialização atual.

Anon
fonte
2
Excelente resposta, obrigado! Embora, observe que systemd-runno Ubuntu 16.04 é muito antigo para suportar a --waitopção, mas não deve ser realmente necessário para o propósito em questão. (De acordo com a página do homem, --waitaguarda o término de uma unidade, mas é suficiente para esperar o seu início que é o comportamento padrão systemd-run.)
Riccardo Murri
Estou corrigido: o systemd-runencantamento dado não funciona no Ubuntu 16.04; morre com mensagem de erro Atribuição desconhecida Depois = apt-daily.service apt-daily-upgrade.service . Parece que algumas propriedades da unidade não estavam disponíveis systemd-run, veja, por exemplo, aqui
Riccardo Murri
@ riccardo-murri você me pegou :-)! Na verdade, eu estava me perguntando sobre as diferenças de 16.04 / 18.04 (daí o "até dois") e esqueci de colocar a ressalva. Que mudança você sugeriria?
Anon
@ riccardo-murri ah, que pena, vou adicionar um grande aviso ao topo da resposta, dizendo que não pode ser usado no Ubuntu 16.04
Anon
Desativou os serviços e reiniciou e funciona!
Digi6666
4

Você pode desativar isso através do módulo cloud-init "bootcmd". Isso é executado antes da rede ser criada, 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
Karl Pickett
fonte
2

Não seria mais fácil mascarar a unidade

systemctl mask apt-daily.service

?


fonte
Não funciona - consulte a seção 1. Desative a tarefa systemd no texto da pergunta. Mas obrigada mesmo assim pela sugestão! :-)
Riccardo Murri 10/10
2
desativar e mascarar um serviço não é o mesmo. mask crie um Link para / dev / null. ls -al /etc/systemd/system/ | grep alsa lrwxrwxrwx 1 root root 9 Sep 1 13:17 alsa-init.service -> /dev/nullos dados estão vazios.
2
eu me livrei da atualização autônoma sudo dpkg-reconfigure -plow unattended-upgradese a proibi. Portanto, o status da unidade apt-daily.service está morto.
Olá @Bahamut, obrigado por seus esforços! A questão, no entanto, é como desabilitar a apt-daily.servicepartir de um cloud-initscript e antes de iniciar após a reinicialização da VM: isso significa: (1) isso deve ser feito de forma não interativa, (2) deve ser feito antes do apt-daily.servicedisparo pela primeira vez. (Se o meu entendimento do systemd está correta, (2) não pode realmente ser realizado como cloud-inite apt-dailyexecutados simultaneamente -. Ver minha própria resposta para mais)
Riccardo Murri
11
Eu tentei isso em uma máquina física normal (ou seja, não uma VM) e posso confirmar que não funciona. Você também precisa parar o cronômetro: systemctl stop apt-daily.timer; systemctl desabilita o apt-daily.timer
happyskeptic
1

Isso espera 1 segundo em um loop completo 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
Navidzj
fonte