it-swarm.com.de

Wie deaktiviere ich "apt-daily.service" in der Ubuntu Cloud VM Image?

Der Ubuntu 16.04-Server VM Image 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 und das Ausführen unbeaufsichtigter Upgrades bei Bedarf usw.

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

Ein laufendes APT verhindert, dass andere apt Prozesse ausgeführt werden, da es eine Sperre für /var/lib/dpkg Hält. 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 das Maschinen-Setup abgeschlossen hat (was normalerweise die Installation von Paketen umfasst); siehe https://github.com/gc3-uzh-ch/elasticluster/Issues/304 für weitere Informationen und Kontext.

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

1. Deaktivieren Sie die Systemd-Task

die systemd-Task apt-daily.service wird durch apt-daily.timer ausgelöst. Ich habe versucht, das eine oder das andere oder beide mit verschiedenen Kobinationen der folgenden Befehle zu deaktivieren. Trotzdem wird apt-daily.service gestartet, sobald 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.daily Liest einige APT Konfigurationsvariablen; die Einstellung APT::Periodic::Enable Deaktiviert die Funktionalität insgesamt (Zeilen 331--337). Ich habe versucht, sie mit dem zu deaktivieren folgendes Skript ::

    #!/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 APT::Periodic::Enable Den Wert 0 In der Befehlszeile hat (siehe unten), wird das Programm unattended-upgrades Immer noch ausgeführt ...

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

3. Entfernen Sie /usr/lib/apt/apt.systemd.daily Insgesamt

Das folgende cloud-init - Skript 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 geprüft wird ::

[email protected]:~$ 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 würden das Skript cloud-init (Zusammen mit der SSH-Befehlszeile) und der Root-Systemd-Prozess in separaten Dateisystemen und Prozessbereichen ausgeführt ...

Fragen

Gibt es etwas Offensichtliches, das mir fehlt? Oder gibt es eine Namespace-Magie, von der ich nichts weiß?

Am wichtigsten: Wie kann ich apt-daily.service Über ein cloud-init - Skript deaktivieren?

70
Riccardo Murri

Ja, es gab etwas Offensichtliches, das mir fehlte.

Bei Systemd dreht sich alles um den gleichzeitigen Start von Diensten, also das cloud-init script wird ausgeführt gleichzeitig the apt-daily.service wird ausgelöst. Zu der Zeit cloud-init kann die benutzerdefinierte Nutzlast ausführen, apt-get update ist bereits gestartet. Die Versuche 2. und 3. scheiterten also nicht an einer Namespace-Magie, sondern daran, dass sie das System zu spät für apt.systemd.daily, um die Änderungen aufzunehmen.

Dies bedeutet auch, dass es grundsätzlich keine Möglichkeit gibt, zu verhindernapt.systemd.daily vom Laufen - man kann es erst 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 noch ein Zeitfenster, in dem SSH-Anmeldungen noch möglich sind apt-get wird nicht ausgeführt, aber ich kann mir keine andere Lösung vorstellen, die auf dem Ubuntu 16.04-Cloud-Image funktioniert.

43
Riccardo Murri

Hinweis: Leider funktioniert ein Teil der folgenden Lösung auf Ubuntu 16.04-Systemen (wie dem des Fragestellers) nicht, da der vorgeschlagene systemd-run Aufruf funktioniert nur unter Ubuntu 18.04 und höher (siehe Kommentare für Details ). 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 Startzeit beteiligt. Der erste apt-daily.service Aktualisiert die Liste der Pakete. Es kann jedoch einen zweiten apt-daily-upgrade.service Geben, der tatsächlich sicherheitskritische Pakete installiert. Eine Antwort auf die Frage "Beenden und Deaktivieren/Entfernen eines unbeaufsichtigten Upgrades, bevor der Befehl zurückgegeben wird" gibt ein hervorragendes Beispiel dafür, wie Sie warten müssen, bis beide abgeschlossen sind (hier zur Vereinfachung 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 disable Beide Dienste UND die zugehörigen Timer (d. H. apt-daily.timer Und apt-daily-upgrade.timer).

Beachten Sie, dass die Maskierungs-/Deaktivierungstechniken in dieser Antwort das Aktualisieren/Aktualisieren bei zukünftigen Startvorgängen nur verhindern. Sie werden nicht gestoppt, wenn sie bereits im aktuellen Startvorgang ausgeführt werden.

17
Anon

Sie können dies über das Cloud-Init-Modul "bootcmd" deaktivieren. Dies wird ausgeführt, bevor das Netzwerk aufgerufen wird. Dies ist erforderlich, bevor das apt-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 ssh in die Instanz eingegeben haben, sollten Sie auch warten, bis die letzten Phasen von Cloud-Init abgeschlossen sind, da passende 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 das Bootcmd ausgeführt wird:

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

Sie können überprüfen, ob dies wie folgt 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
5
Karl Pickett

Es wäre nicht einfacher, das Gerät zu maskieren

systemctl mask apt-daily.service

?

2
user192526

Basierend auf Anons Lösung habe ich dieses Skript erstellt, das nach dem Ausführen und anschließenden Neustart das Problem für mich löst:

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

Wenn der Zweck darin besteht, den Computer ohne Sperrfehler bereitzustellen, besteht die einfachste und stabilste Lösung darin, den Remotebefehl des Provisioners (oder die apt-bezogenen Befehle) auszuführen, während die apt-daily-Sperrdatei gesperrt wird. Keine Dienstmaskierung/Deaktivierung/Warten usw. usw.

Auf dem Ubuntu-Server werden die Paketaktualisierungsprogramme (apt-daily, unbeaufsichtigte Upgrades, Cloud-init) apt-daily durchlaufen, sodass sich die Lösung darauf konzentrieren kann.

Apt-daily verwendet flock(2) Sperren, die im Gegensatz zu dpkg/apt (die fnctl verwenden) über ein Befehlszeilentool verwaltet werden können, mit der Bequemlichkeit, dass das Warten auf die Sperre unterstützt wird.

Wenn Sie beispielsweise Chef verwenden, ist dies so einfach wie das Ausführen auf den Knoten:

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

und:

  • jeder Chefkoch-Kunde greift zuerst nach dem Schloss, und jeder tägliche Service wartet.
  • oder jeder apt-daily-basierte Service sperrt ihn zuerst, dann wartet chef-clien und wird schließlich ausgeführt, sobald apt-daily abgeschlossen ist.

Wenn der Provisioner nicht auf den Knoten aufgerufen wird, kann die Provisioner-Konfiguration (z. B. Ansible Playbook) so geändert werden, dass sie ausgeführt wird:

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

(oder eine Variation wie sh -c '...' und so weiter)

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

1
Marcus

Dies wartet 1 Sekunde in einer while-Schleife 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
1
Navidzj

Dieser Cloud-Init funktioniert.

#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