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?


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.


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.


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

2

Não seria mais fácil mascarar a unidade

systemctl mask apt-daily.service

?


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.