Wie deaktiviere ich "apt-daily.service" auf einem Ubuntu-Cloud-VM-Image?

59

Das VM-Image des Ubuntu 16.04-Servers startet anscheinend alle 12 Stunden den "apt-daily.service". Dieser Dienst führt verschiedene APT-bezogene Aufgaben aus, z. B. das Aktualisieren der Liste der verfügbaren Pakete, das Ausführen unbeaufsichtigter Upgrades bei Bedarf usw.

Beim Starten von einem VM "Snapshot" wird der Dienst sofort ausgelöst , da (nehme ich an) systemd schnell erkennt, dass der Timer längst abgelaufen sein sollte.

Ein laufender APT verhindert jedoch, dass andere aptProzesse ausgeführt werden, da er gesperrt ist /var/lib/dpkg. Die Fehlermeldung, die dies anzeigt, sieht folgendermaßen aus:

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?

Ich muss diese automatisierte APT-Aufgabe deaktivieren, bis Ansible die Einrichtung des Computers abgeschlossen hat (was normalerweise die Installation von Paketen umfasst). Weitere Informationen und den Kontext finden Sie unter https://github.com/gc3-uzh-ch/elasticluster/issues/304 .

Ich habe verschiedene Optionen ausprobiert, um die Funktion "Unbeaufsichtigte Upgrades" über ein Skript für "Benutzerdaten" zu deaktivieren cloud-init, aber alle sind bisher fehlgeschlagen.

1. Deaktivieren Sie die Task systemd

systemd task apt-daily.servicewird ausgelöst durch apt-daily.timer. Ich habe versucht, den einen oder den anderen oder beide mit verschiedenen Kombinationen der folgenden Befehle zu deaktivieren. apt-daily.serviceNach wie vor wird das gestartet, sobald die VM bereit ist, SSH-Verbindungen zu akzeptieren:

    #!/bin/bash

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

2. Deaktivieren Sie die Konfigurationsoption APT::Periodic::Enable

Das Skript /usr/lib/apt/apt.systemd.dailyliest einige APT-Konfigurationsvariablen. Die Einstellung APT::Periodic::Enabledeaktiviert die Funktionalität vollständig (Zeilen 331 - 337). Ich habe versucht, es mit dem folgenden Skript zu deaktivieren:

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

Obwohl das Programm über die Befehlszeile APT::Periodic::Enableeinen Wert hat 0(siehe unten), unattended-upgradeswird es dennoch ausgeführt ...

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

3. Entfernen Sie /usr/lib/apt/apt.systemd.dailyinsgesamt

Das folgende cloud-initSkript entfernt das Skript für unbeaufsichtigte Upgrades insgesamt:

    #!/bin/bash

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

Trotzdem läuft die Aufgabe und ich kann sie in der Prozesstabelle sehen! Obwohl die Datei nicht existiert, wenn sie über die Befehlszeile abgefragt wird:

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

Es sieht so aus, als ob das cloud-initSkript (zusammen mit der SSH-Befehlszeile) und der Root-systemd-Prozess in separaten Dateisystemen und Prozessbereichen ausgeführt werden ...

Fragen

Gibt es etwas offensichtliches, was ich vermisse? Oder gibt es eine Namespace-Magie, von der ich nichts weiß?

Am wichtigsten: Wie kann ich das apt-daily.serviceüber ein cloud-initSkript deaktivieren ?

Riccardo Murri
quelle
2
Dies wird Ihnen nicht weiterhelfen, bis es in ein offizielles Paketupdate gerollt wird, aber lesen Sie bitte den Patch, den ich gerade in Debian-Fehler 844453 gepostet habe .
zwol
Möglicherweise haben Sie die --nowMarkierung im systemctl disableBefehl übersehen, damit die Änderung sofort wirksam wird. Das war mein Problem.
Daniel F
@DanielF nein, weil disable --nowgleichbedeutend mit stopgefolgt von disable.
Sourcejedi
1
Anscheinend wurde dies in systemd im Februar 2019 ENDLICH behoben: github.com/systemd/systemd/issues/5659 . So wird es hoffentlich in Ubuntu 20.04 sein.
Snap

Antworten:

37

Ja, da war etwas offensichtlich, was mir fehlte.

Bei Systemd dreht sich alles um den gleichzeitigen Start von Diensten, sodass das cloud-initSkript zur gleichen Zeit ausgeführt wird, zu der apt-daily.servicees ausgelöst wird. Bis die Zeit cloud-initzur Ausführung der benutzerdefinierten Nutzlast kommt, apt-get updateläuft bereits. Die Versuche 2. und 3. scheiterten also nicht an irgendeiner Namespace-Magie, sondern daran, dass sie das System zu spät änderten apt.systemd.daily, um die Änderungen zu übernehmen.

Dies bedeutet auch, dass es im Grunde keine Möglichkeit gibt , das apt.systemd.daily Laufen zu verhindern - man kann es nur töten, nachdem es gestartet wurde.

Dieses "Benutzerdaten" -Skript nimmt diesen Weg:

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

Es gibt immer noch ein Zeitfenster, in dem SSH-Anmeldungen möglich sind, die apt-get jedoch nicht ausgeführt werden, aber ich kann mir keine andere Lösung vorstellen, die auf dem Standard-Ubuntu 16.04-Cloud-Image funktioniert.

Riccardo Murri
quelle
das hat bei mir auf aws ubuntu 16.04
geklappt
Ja, ich bin dabei, ein benutzerdefiniertes AMI zu erstellen. Dies beschleunigt auch die Installation von gemeinsamen Diensten.
Giorgiosironi
Dies scheint nicht genug zu sein, ich finde, es gibt immer noch stragulierende Fälle vonapt-get -o Acquire::http::AllowRedirect=false update
Edward Z. Yang
11

Hinweis: Leider funktioniert ein Teil der unten aufgeführten Lösung nicht auf Ubuntu 16.04-Systemen (wie dem des Fragestellers), da der vorgeschlagene systemd-runAufruf nur auf Ubuntu 18.04 und höher funktioniert ( Details finden Sie in den Kommentaren ). Ich werde die Antwort hier lassen, da diese Frage immer noch ein beliebter Hit ist, unabhängig davon, welche Ubuntu-Version Sie verwenden ...

Unter Ubuntu 18.04 (und höher) sind möglicherweise bis zu zwei Dienste an der Aktualisierung / Aktualisierung der Boot-Zeit beteiligt. Der erste apt-daily.serviceaktualisiert die Liste der Pakete. Es kann jedoch eine Sekunde geben, in apt-daily-upgrade.serviceder tatsächlich sicherheitskritische Pakete installiert werden. Die Antwort auf die Frage "Unbeaufsichtigtes Upgrade beenden und deaktivieren / entfernen, bevor der Befehl zurückgegeben wird" gibt ein hervorragendes Beispiel dafür, wie Sie darauf warten können, dass beide beendet werden (hier aus Gründen der Benutzerfreundlichkeit kopiert):

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

(Beachten Sie, dass dies als root ausgeführt werden muss). Wenn Sie versuchen, diese Dienste bei zukünftigen Starts zu deaktivieren, müssen Sie BEIDE Dienste maskieren:

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

Alternativ können Sie systemctl disablesowohl Dienste als auch die zugehörigen Timer (dh apt-daily.timerund apt-daily-upgrade.timer) verwenden.

Beachten Sie, dass die Maskierungs- / Deaktivierungstechniken in dieser Antwort nur das Aktualisieren / Aktualisieren zukünftiger Starts verhindern. Sie werden nicht gestoppt, wenn sie bereits im aktuellen Start ausgeführt werden.

Anon
quelle
2
Ausgezeichnete Antwort, danke! Beachten Sie jedoch, dass systemd-runUbuntu 16.04 zu alt ist, um die --waitOption zu unterstützen , dies sollte jedoch für den vorliegenden Zweck nicht unbedingt erforderlich sein. (Laut Manpage --waitwartet man auf die Beendigung einer Einheit, aber es reicht, auf den Start zu warten, was das Standardverhalten von ist systemd-run.)
Riccardo Murri
Ich stehe korrigiert da: Die gegebene systemd-runBeschwörung funktioniert überhaupt nicht auf Ubuntu 16.04; es stirbt mit Fehlermeldung Unbekannte Zuordnung After = apt-daily.service apt-daily-upgrade.service . Es sieht so aus, als wären einige Einheiten in nicht verfügbar systemd-run, siehe zum Beispiel hier
Riccardo Murri
@riccardo-murri du hast mich erwischt :-)! Eigentlich habe ich mich über 16.04 / 18.04 Unterschiede gewundert (daher das Wiesel "bis zu zwei") und dann vergessen, die Einschränkung einzulegen. Welche Änderung würden Sie vorschlagen?
Anon
@ Riccardo-Murri Ah, das ist schade, ich werde eine große Warnung an den Anfang der Antwort setzen, die besagt, dass es nicht auf Ubuntu 16.04
Anon
Deaktiviert die Dienste und neu gestartet und es funktioniert!
Digz6666
3

Sie können dies über das Cloud-Init-Modul "bootcmd" deaktivieren. Dieser Vorgang wird ausgeführt, bevor das Netzwerk gestartet wird. Dies ist erforderlich, bevor ein passendes Update ausgeführt werden kann.

#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

Sobald Sie sich in der Instanz befinden, sollten Sie auch warten, bis die letzten Phasen von cloud-init abgeschlossen sind, da hierdurch geeignete Quellen / Listen verschoben werden.

# 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

Dies ist auch hilfreich, um zu sehen, wie früh die bootcmd ausgeführt wird:

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

Sie können überprüfen, ob dies folgendermaßen funktioniert hat:

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
quelle
1

Es wird nicht einfacher sein, das Gerät zu maskieren

systemctl mask apt-daily.service

?


quelle
Funktioniert nicht - siehe Abschnitt 1. Deaktivieren Sie die Task systemd im Fragentext . Aber trotzdem danke für den Vorschlag! :-)
Riccardo Murri
2
Deaktivieren und Maskieren eines Dienstes ist nicht dasselbe. Maske erstellen Sie einen Link zu / dev / null. ls -al /etc/systemd/system/ | grep alsa lrwxrwxrwx 1 root root 9 Sep 1 13:17 alsa-init.service -> /dev/nullDie Daten sind leer.
2
Ich werde unbeaufsichtigt Upgrade los sudo dpkg-reconfigure -plow unattended-upgradesund verbiete es. Der Status der Einheit apt-daily.service ist also gestorben.
Hi @ Bahamut, danke für deine Bemühungen! Die Frage ist jedoch, wie apt-daily.serviceein cloud-initSkript deaktiviert werden kann und bevor es nach dem Neustart der VM gestartet wird: Dies bedeutet: (1) es muss nicht interaktiv erfolgen, (2) es muss vor apt-daily.servicedem ersten Auslösen erfolgen. (Wenn mein Verständnis von systemd korrekt ist, (2) kann nicht wirklich als erreicht werden cloud-initund apt-dailygleichzeitig laufen -. Meine eigene Antwort für mehr sehen)
Riccardo Murri
1
Ich habe dies auf einer normalen physischen Maschine (dh keiner VM) versucht und kann bestätigen, dass es nicht funktioniert. Sie müssen auch den Timer stoppen: systemctl stop apt-daily.timer; systemctl deaktiviere apt-daily.timer
happyskeptic
0

Dieser wartet in einer Schleife 1 Sekunde und prüft, ob die Sperre aufgehoben ist.

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
quelle