Comment désactiver `apt-daily.service` sur l'image de la machine virtuelle du cloud Ubuntu?

60

L'image de la machine virtuelle du serveur Ubuntu 16.04 démarre apparemment le "apt-daily.service" toutes les 12 heures environ; Ce service effectue diverses tâches liées à APT, telles que l'actualisation de la liste des packages disponibles, l'exécution de mises à niveau sans assistance si nécessaire, etc.

Lorsque vous démarrez à partir d'une "capture instantanée" de machine virtuelle, le service est immédiatement déclenché , car (je présume), systemd réalise rapidement que la minuterie aurait dû sonner depuis longtemps.

Cependant, un APT en cours d'exécution empêche d'autres aptprocessus de s'exécuter car il est verrouillé /var/lib/dpkg. Le message d'erreur indiquant ceci ressemble à ceci:

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?

Je dois désactiver cette tâche APT automatisée jusqu'à ce qu'Ansible ait terminé la configuration de la machine (ce qui implique généralement l'installation de packages). voir https://github.com/gc3-uzh-ch/elasticluster/issues/304 pour plus d'informations et le contexte.

J'ai essayé diverses options pour désactiver la fonctionnalité "Mises à niveau sans surveillance" via un script "Données utilisateur" cloud-init, mais toutes ont échoué jusqu'à présent.

1. Désactiver la tâche systemd

La tâche systemd apt-daily.serviceest déclenchée par apt-daily.timer. J'ai essayé de désactiver l'un ou l'autre, ou les deux, avec divers cobinations des commandes suivantes; cependant, il apt-daily.serviceest démarré quelques instants après que la VM soit prête à accepter les connexions SSH:

    #!/bin/bash

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

2. Désactiver l'option de configuration APT::Periodic::Enable

Le script /usr/lib/apt/apt.systemd.dailylit quelques variables de configuration APT; le paramètre APT::Periodic::Enabledésactive complètement la fonctionnalité (lignes 331 à 337). J'ai essayé de le désactiver avec le script suivant:

    #!/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

Cependant, malgré APT::Periodic::Enablesa valeur 0depuis la ligne de commande (voir ci-dessous), le unattended-upgradesprogramme est toujours exécuté ...

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

3. Supprimer /usr/lib/apt/apt.systemd.dailycomplètement

Le cloud-initscript suivant supprime complètement le script de mises à niveau sans assistance ::

    #!/bin/bash

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

Malgré tout, la tâche est exécutée et je peux la voir dans la table de processus! bien que le fichier n'existe pas s'il est interrogé à partir de la ligne de commande ::

ubuntu@test:~$ ls /usr/lib/apt/apt.systemd.daily
ls: cannot access '/usr/lib/apt/apt.systemd.daily': No such file or directory

Il semble que le cloud-initscript (avec la ligne de commande SSH) et le processus racine de systemd s'exécutent dans des systèmes de fichiers et des espaces de processus distincts ...

Des questions

Y a-t-il quelque chose d'évident qui me manque? Ou y a-t-il une magie de l'espace de noms en cours dont je ne suis pas au courant?

Plus important encore: comment puis-je désactiver le apt-daily.servicevia un cloud-initscript?

Riccardo Murri
la source
2
Cela ne vous aidera pas tant que cela n'aura pas été intégré à la mise à jour officielle d'un paquet, mais veuillez consulter le correctif que je viens de publier pour le bogue n ° 844453 de Debian .
Zwol
Il vous manquait peut-être le --nowdrapeau dans la systemctl disablecommande pour que le changement prenne effet immédiatement. C'était mon problème.
Daniel F
@DanielF non, car disable --nowest équivalent à stopsuivi de disable.
sourcejedi
1
Apparemment, cela a finalement été résolu dans systemd en 2019: github.com/systemd/systemd/issues/5659 . J'espère donc que ce sera dans Ubuntu 20.04.
Snap

Réponses:

38

Oui, il y avait quelque chose d'évident qui me manquait.

Systemd concerne le démarrage simultané des services. Le cloud-initscript est donc exécuté en même temps que le apt-daily.servicedéclenchement. Au moment où cloud-initdoit exécuter la charge utile spécifiée par l'utilisateur, apt-get updateest déjà en cours d'exécution. Ainsi, les tentatives 2. et 3. ont échoué, non pas à cause de la magie de l'espace de noms, mais parce qu'elles ont modifié le système trop tard pour que apt.systemd.dailyles modifications soient prises en compte.

Cela signifie également qu'il n'y a fondamentalement aucun moyen d' empêcher apt.systemd.daily de courir - on peut seulement le tuer après l'avoir démarré.

Ce script "données utilisateur" emprunte cette route:

#!/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

Il existe encore une fenêtre de temps pendant laquelle les connexions SSH sont possibles mais apt-get ne s'exécutent pas, mais je ne peux pas imaginer une autre solution pouvant fonctionner sur l'image stock d'Ubuntu 16.04.

Riccardo Murri
la source
cela a fonctionné pour moi sur aws 16.04, merci pour la solution
krisdigitx
Oui, je vais créer une AMI personnalisée. Cela accélère également l'installation de services communs.
giorgiosironi
Cela ne semble pas être suffisant, je trouve qu'il y a encore des instances éparses deapt-get -o Acquire::http::AllowRedirect=false update
Edward Z. Yang
12

Remarque: Malheureusement, une partie de la solution ci - dessous ne fonctionne pas sur les systèmes Ubuntu 16.04 (comme celui de l'interrogateur) car l' systemd-runinvocation suggérée ne fonctionne que sur Ubuntu 18.04 et les versions ultérieures (voir les commentaires pour plus de détails ). Je laisse la réponse ici car cette question est toujours populaire, quelle que soit la version d'Ubuntu que vous utilisez ...

Sur Ubuntu 18.04 (et plus), il peut y avoir jusqu’à deux services impliqués dans le démarrage et la mise à jour / mise à niveau. Le premier apt-daily.serviceactualise la liste des packages. Cependant, il peut y avoir une seconde apt-daily-upgrade.servicequi installe réellement des paquets critiques pour la sécurité. Une réponse à la question "Arrêtez et désactivez / supprimez la mise à niveau automatique avant que la commande ne retourne" donne un excellent exemple de la procédure à suivre pour attendre la fin de ces deux opérations (copiée ici pour plus de commodité):

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

(notez que ceci doit être exécuté en tant que root). Si vous essayez de désactiver ces services lors de futurs démarrages, vous devrez masquer les deux services:

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

Vous pouvez également systemctl disableutiliser les services ET leurs minuteurs associés (c. apt-daily.timer-à- d. Et apt-daily-upgrade.timer).

Notez que les techniques de masquage / désactivation dans cette réponse empêchent uniquement la mise à jour / mise à niveau lors de futurs démarrages - elles ne les arrêteront pas si elles sont déjà en cours d'exécution dans le démarrage actuel.

Anon
la source
2
Excellente réponse, merci! Bien que, notez que systemd-runsur Ubuntu 16.04 est trop vieux pour supporter l’ --waitoption, mais cela ne devrait pas vraiment être nécessaire pour le but recherché. (Selon la page de manuel, --waitattend la fin d'une unité, mais il suffit d'attendre son début, ce qui est le comportement par défaut de systemd-run.)
Riccardo Murri
Je me tiens corrigé: l' systemd-runincantation donnée ne fonctionne pas du tout sur Ubuntu 16.04; il meurt avec un message d'erreur Affectation inconnue après = apt-daily.service apt-daily-upgrade.service . Il semble que certaines propriétés de l'unité ne sont pas disponibles à systemd-run, voir par exemple ici
Riccardo Murri
@ riccardo-murri tu m'as eu :-)! En fait, je me posais des questions sur les différences 16.04 / 18.04 (d’où le "jusqu'à deux") et puis j'ai oublié de mettre l’avertissement en jeu. Quel changement suggéreriez-vous?
Anon
@ riccardo-murri ah c'est dommage, je vais ajouter un gros avertissement en haut de la réponse, disant qu'il ne peut pas être utilisé sous Ubuntu 16.04
Anon
Désactivé les services et redémarré et ça marche!
digz6666
4

Vous pouvez le désactiver via le module cloud-init "bootcmd". Cela s'exécute avant que le réseau soit mis en place, ce qui est nécessaire avant que apt update puisse avoir une chance de s'exécuter.

#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

Une fois que vous avez intégré SSH à l'instance, vous devez également attendre la fin des phases finales de cloud-init, car celle-ci déplace les sources / listes.

# 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

Ceci est également utile pour voir à quelle heure le bootcmd s'exécute:

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

Vous pouvez vérifier que cela fonctionne comme suit:

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
la source
2

Ne serait pas plus facile de masquer l'unité

systemctl mask apt-daily.service

?


la source
Ne fonctionne pas - voir section 1. Désactivez la tâche systemd dans le texte de la question. Mais merci quand même pour la suggestion! :-)
Riccardo Murri
2
désactiver et masquer un service n'est pas la même chose. mask crée un lien vers / dev / null. ls -al /etc/systemd/system/ | grep alsa lrwxrwxrwx 1 root root 9 Sep 1 13:17 alsa-init.service -> /dev/nullles données sont vides.
2
Je me débarrasse de la mise à niveau sans surveillance sudo dpkg-reconfigure -plow unattended-upgradeset l'utilise. Donc, le statut de l'unité apt-daily.service est mort.
Bonjour @Bahamut, merci pour vos efforts! La question, cependant, est de savoir comment désactiver apt-daily.serviceun cloud-initscript et avant qu'il ne démarre après le redémarrage de la machine virtuelle: cela signifie: (1) cela doit être fait de manière non interactive, (2) cela doit être fait avant apt-daily.servicele premier déclenchement. (Si ma compréhension de systemd est correcte, (2) ne peut pas réellement être accompli en tant que cloud-initet apt-dailys'exécute simultanément - voir ma propre réponse pour plus.)
Riccardo Murri
1
J'ai essayé ceci sur une machine physique normale (c.-à-d. Pas une VM) et peux confirmer que cela ne fonctionne pas. Vous devez également arrêter le minuteur: systemctl stop apt-daily.timer; systemctl désactiver apt-daily.timer
happyskeptic
1

Cela attend 1 seconde dans une boucle complète et vérifie si le verrou est libéré.

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
la source