Jak wyłączyć `apt-daily.service` na obrazie VM maszyny w chmurze Ubuntu?


60

Obraz maszyny Wirtualnej serwera Ubuntu 16.04 najwidoczniej uruchamia „apt-daily.service” co około 12 godzin; ta usługa wykonuje różne zadania związane z APT, takie jak odświeżanie listy dostępnych pakietów, wykonywanie nienadzorowanych aktualizacji w razie potrzeby itp.

Rozpoczynając od „migawki” maszyny wirtualnej, usługa jest uruchamiana natychmiast , ponieważ (jak sądzę) systemd szybko zdaje sobie sprawę, że licznik powinien był zadziałać dawno temu.

Jednak działający APT uniemożliwia uruchomienie innych aptprocesów, ponieważ blokuje /var/lib/dpkg. Komunikat o błędzie wskazujący to wygląda następująco:

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?

Muszę wyłączyć to automatyczne zadanie APT, dopóki Ansible nie zakończy konfiguracji komputera (co zwykle wiąże się z instalacją pakietów); zobacz https://github.com/gc3-uzh-ch/elasticluster/issues/304, aby uzyskać więcej informacji i kontekst.

Próbowałem różnych opcji, aby wyłączyć funkcję „nienadzorowanej aktualizacji” za pomocą skryptu „danych użytkownika” cloud-init, ale jak dotąd wszystkie zawiodły.

1. Wyłącz zadanie systemowe

Zadanie systemd apt-daily.servicejest uruchamiane przez apt-daily.timer. Próbowałem wyłączyć jedno lub drugie, lub oba, przy pomocy różnych poleceń następujących poleceń; nadal apt-daily.servicejest uruchamiany chwilę po tym, jak maszyna wirtualna będzie gotowa do przyjmowania połączeń SSH:

    #!/bin/bash

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

2. Wyłącz opcję konfiguracji APT::Periodic::Enable

Skrypt /usr/lib/apt/apt.systemd.dailyodczytuje kilka zmiennych konfiguracyjnych APT; ustawienie APT::Periodic::Enablecałkowicie wyłącza funkcjonalność (wiersze 331--337). Próbowałem wyłączyć go za pomocą następującego skryptu:

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

Jednak pomimo APT::Periodic::Enablewartości 0z wiersza poleceń (patrz poniżej) unattended-upgradesprogram jest nadal uruchomiony ...

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

3. Usuń /usr/lib/apt/apt.systemd.dailycałkowicie

Poniższy cloud-initskrypt całkowicie usuwa skrypt nienadzorowanej aktualizacji:

    #!/bin/bash

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

Mimo to zadanie działa i widzę je w tabeli procesów! chociaż plik nie istnieje, jeśli sondowany z linii poleceń:

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

Wygląda na to, że cloud-initskrypt (wraz z wierszem poleceń SSH) i proces systemowy wykonywany są w osobnych systemach plików i przestrzeniach procesów ...

pytania

Czy brakuje mi czegoś oczywistego? A może dzieje się jakaś magia przestrzeni nazw, o której nie wiem?

Co najważniejsze: w jaki sposób można wyłączyć apt-daily.serviceza pomocą cloud-initskryptu?


2
To ci nie pomoże, dopóki nie zostanie wprowadzone do oficjalnej aktualizacji pakietu, ale proszę zobaczyć łatkę, którą właśnie opublikowałem na błąd Debian # 844453 .
— zwolnienie

Być może brakowało --nowflagi w systemctl disablepoleceniu, aby zmiana odniosła skutek natychmiastowy. To był mój problem.
— Daniel F

@DanielF nie, ponieważ disable --nowjest równoważne z stopnastępującą po disable.
— sourcejedi

1
Widocznie ten został wreszcie rozwiązany w Systemd w 2019 lut: github.com/systemd/systemd/issues/5659 . Mamy nadzieję, że będzie to w Ubuntu 20.04.
— snap

Odpowiedzi:


38

Tak, coś oczywistego mi brakowało.

Systemd polega na równoczesnym rozpoczęciem usługi, więc cloud-initskrypt jest uruchamiany jednocześnieapt-daily.service jest uruchomiony. Do czasu, cloud-initaby wykonać ładunek określony przez użytkownika, apt-get updatejuż działa. Tak więc próby 2. i 3. nie powiodły się nie z powodu pewnej magii przestrzeni nazw, ale dlatego, że zbyt późno zmieniły system, aby można apt.systemd.dailybyło zauważyć zmiany.

Oznacza to również, że w zasadzie nie ma możliwości uniemożliwienia apt.systemd.daily uruchomienia - można go zabić dopiero po uruchomieniu.

Ten skrypt „danych użytkownika” podąża tą drogą:

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

Nadal istnieje okno czasowe, w którym logowanie SSH jest możliwe, ale jeszcze apt-get się nie uruchomi, ale nie wyobrażam sobie innego rozwiązania, które może działać na standardowym obrazie w chmurze Ubuntu 16.04.


to zadziałało dla mnie na aws ubuntu 16.04, dzięki za rozwiązanie
— krisdigitx

Tak, idę drogą tworzenia niestandardowego AMI. Przyspiesza to także instalację wspólnych usług.
— giorgiosironi,

To nie wydaje się wystarczające, uważam, że wciąż istnieją zmagające się przypadkiapt-get -o Acquire::http::AllowRedirect=false update
— Edwarda Z. Yang

12

Uwaga: Niestety część poniższego rozwiązania nie działa na systemach Ubuntu 16.04 (takich jak pytający), ponieważ sugerowane systemd-runwywołanie działa tylko na Ubuntu 18.04 i nowszych ( szczegółowe informacje można znaleźć w komentarzach ). Pozostawię tutaj odpowiedź, ponieważ to pytanie jest wciąż popularnym hitem, niezależnie od używanej wersji Ubuntu ...

W systemie Ubuntu 18.04 (i nowszych wersjach) mogą występować maksymalnie dwie usługi związane z aktualizacją / aktualizacją w czasie rozruchu. Pierwszy apt-daily.serviceodświeża listę pakietów. Może jednak istnieć sekunda, apt-daily-upgrade.servicektóra faktycznie instaluje pakiety o krytycznym znaczeniu dla bezpieczeństwa. Odpowiedź na „Zakończ i wyłączyć / usunąć nienadzorowanej uaktualnienie przed zwrotów komenda” pytanie daje doskonały przykład tego, jak czekać na oba te skończyć (skopiowany tutaj dla wygody):

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

(zwróć uwagę, że należy to uruchomić jako root). Jeśli próbujesz wyłączyć te usługi przy przyszłych rozruchach, musisz zamaskować OBIE usługi:

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

Alternatywnie możesz systemctl disablezarówno usługi ORAZ powiązane z nimi liczniki (tj. apt-daily.timerI apt-daily-upgrade.timer).

Zwróć uwagę, że techniki maskowania / wyłączania zawarte w tej odpowiedzi zapobiegają tylko aktualizacji / aktualizacji w przyszłych uruchomieniach - nie zatrzymają ich, jeśli są już uruchomione w bieżącym rozruchu.


2
Doskonała odpowiedź, dziękuję! Chociaż zauważ, że systemd-runw Ubuntu 16.04 jest zbyt stary, aby obsługiwać tę --waitopcję, ale tak naprawdę nie powinien być konieczny do zamierzonego celu. (Według strony podręcznika, --waitczeka na zakończenie jednostki, ale wystarczy poczekać na jej uruchomienie, co jest domyślnym zachowaniem systemd-run).
— Riccardo Murri

Poprawiłem się: podana systemd-runinkantacja w ogóle nie działa na Ubuntu 16.04; umiera z komunikatem o błędzie Nieznane przypisanie After = apt-daily.service apt-daily-upgrade.service . Wygląda na to, że niektóre właściwości jednostek nie były dostępne systemd-run, patrz na przykład tutaj
— Riccardo Murri

@ riccardo-murri masz mnie :-)! Właściwie sam zastanawiałem się nad różnicami 16.04 / 18.04 (stąd łasica „do dwóch”), a potem zapomniałem wprowadzić zastrzeżenie. Jaką zmianę byś zaproponował?
— Anon,

@ riccardo-murri ah to szkoda, dodam duże ostrzeżenie na górze odpowiedzi, mówiąc, że nie można jej używać na Ubuntu 16.04
— Anon

Wyłączyłem usługi i uruchomiłem ponownie i działa!
— digz6666,

4

Możesz to wyłączyć za pomocą modułu inicjującego chmurę „bootcmd”. Działa to przed uruchomieniem sieci, co jest wymagane, zanim apt update może uzyskać szansę na uruchomienie.

#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

Gdy wpiszesz ssh do instancji, powinieneś także poczekać na zakończenie końcowych faz inicjowania chmury, ponieważ przenosi on odpowiednie źródła / listy.

# 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

Jest to również pomocne, aby zobaczyć, jak wcześnie uruchamia się bootcmd:

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

Możesz to sprawdzić w następujący sposób:

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

Nie byłoby łatwiej maskować urządzenia

systemctl mask apt-daily.service

?


Nie działa - patrz sekcja 1. Wyłącz zadanie systemowe w tekście pytania. Ale i tak dziękuję za sugestię! :-)
— Riccardo Murri,

2
wyłącz i zamaskuj usługę to nie to samo. maska ​​utwórz link do / dev / null. ls -al /etc/systemd/system/ | grep alsa lrwxrwxrwx 1 root root 9 Sep 1 13:17 alsa-init.service -> /dev/nulldane są puste.

2
pozbywam się nienadzorowanej aktualizacji sudo dpkg-reconfigure -plow unattended-upgradesi zabraniam jej. Zatem status jednostki apt-daily.service jest martwy.

Cześć @Bahamut dzięki za twoje wysiłki! Pytanie brzmi jednak, jak wyłączyć apt-daily.serviceze cloud-initskryptu i zanim uruchomi się on po ponownym uruchomieniu VM: oznacza to: (1) należy to zrobić nieinteraktywnie, (2) należy to zrobić przed apt-daily.servicepierwszym uruchomieniem. (Jeśli moje rozumienie systemd jest poprawne, (2) nie można faktycznie osiągnąć cloud-initi apt-dailyuruchomić jednocześnie - więcej informacji znajduje się w mojej odpowiedzi.)
— Riccardo Murri,

1
Próbowałem tego na normalnej maszynie fizycznej (tj. Nie na maszynie wirtualnej) i mogę potwierdzić, że to nie działa. Musisz także zatrzymać stoper: systemctl stop apt-daily.timer; systemctl wył. apt-daily.timer
— happyskeptic

1

To czeka 1 sekundę w pętli whil i sprawdza, czy zamek jest zwolniony.

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.