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?

Riccardo Murri
źródło
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.

Riccardo Murri
źródło
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.

Zaraz
źródło
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
Karl Pickett
źródło
2

Nie byłoby łatwiej maskować urządzenia

systemctl mask apt-daily.service

?


źródło
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
Navidzj
źródło