Як відключити `apt-daily.service` на зображенні хмари VM у хмарі Ubuntu?


60

Зображення VM сервера Ubuntu 16.04, очевидно, запускає "apt-daily.service" кожні 12 годин або близько того; ця служба виконує різні завдання, пов’язані з APT, такі як оновлення списку доступних пакетів, виконання необхідних оновлень при необхідності тощо.

Починаючи з "знімку" VM, послуга запускається негайно , оскільки (я вважаю) systemd швидко розуміє, що таймер повинен був давно вимкнутися.

Однак запущений APT заважає виконувати інші aptпроцеси, оскільки він фіксує блокування /var/lib/dpkg. Повідомлення про помилку, що вказує на це, виглядає приблизно так:

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?

Мені потрібно відключити цю автоматизовану задачу APT, поки Ansible не завершить налаштування машини (що, як правило, передбачає встановлення пакетів); див. https://github.com/gc3-uzh-ch/elasticluster/isissue/304 для отримання додаткової інформації та контексту.

Я спробував різні варіанти відключення функції "без нагляду оновлень" за допомогою сценарію "користувацькі дані" для cloud-init, але всі вони поки не вдалися.

1. Вимкніть системну задачу

завдання системи apt-daily.serviceспрацьовує apt-daily.timer. Я намагався відключити одну чи іншу чи обидві різні комбінації наступних команд; все-таки apt-daily.serviceрозпочаті моменти після того, як VM готова прийняти SSH-з'єднання ::

    #!/bin/bash

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

2. Вимкнути параметр конфігурації APT::Periodic::Enable

Сценарій /usr/lib/apt/apt.systemd.dailyчитає кілька змінних параметрів APT; налаштування APT::Periodic::Enableвзагалі вимикає функціональність (рядки 331--337). Я спробував відключити його за допомогою наступного сценарію ::

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

Однак, незважаючи APT::Periodic::Enableна значення 0в командному рядку (див. Нижче), unattended-upgradesпрограма все ще працює ...

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

3. Видаліть /usr/lib/apt/apt.systemd.dailyзовсім

Наступний cloud-initскрипт повністю видаляє без нагляду сценарій оновлення ::

    #!/bin/bash

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

Все-таки завдання виконується, і я бачу його в таблиці процесів! хоча файл не існує, якщо він перевіряється з командного рядка ::

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

Схоже, що cloud-initсценарій (разом із командним рядком SSH) та кореневий системний процес виконуються в окремих файлових системах та процесному просторі ...

Запитання

Щось явне я пропускаю? Або відбувається якась магія простору імен, про яку я не знаю?

Найголовніше: як я можу відключити скрипт apt-daily.serviceчерез cloud-init?


2
Це не допоможе вам, поки воно не перетвориться на офіційне оновлення пакета, але, будь ласка, дивіться патч, який я щойно опублікував на Debian bug # 844453 .
zwol

Можливо, вам не вистачало --nowпрапора в systemctl disableкоманді, щоб негайно зробити зміни ефективними. Це було моє питання.
Даніель Ф

@DanielF немає, тому що disable --nowеквівалентно stopнаступному disable.
sourcejedi

1
Мабуть, це було КІНЦЕВІ зафіксовано у systemd у 2019 році лютого: github.com/systemd/systemd/isissue/5659 . Тож сподіваємось, це буде в Ubuntu 20.04.
оснащення

Відповіді:


38

Так, було щось очевидне, що я бракував.

Systemd все про паралельному запуску послуг, тому cloud-initскрипт запускається одночасноapt-daily.service спрацьовує. До моменту, коли cloud-initнастає виконання визначеної користувачем корисної навантаження, apt-get updateвже працює. Отже, спроби 2. і 3. провалилися не через якусь магію простору імен, а тому, що вони занадто пізно змінили систему, apt.systemd.dailyщоб підняти зміни.

Це також означає, що в основному немає можливості запобігти apt.systemd.daily запуску - вбити його можна лише після його запуску.

Цей сценарій "дані про користувачів" бере цей маршрут ::

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

Є ще часове вікно, протягом якого можливі входи в SSH, але apt-get вони не запускаються, але я не можу уявити іншого рішення, яке може працювати на зображенні хмари Ubuntu 16.04.


це працювало для мене на aws ubuntu 16.04, дякую за рішення
krisdigitx

Так, я йду шляхом створення користувацького AMI. Це також прискорює встановлення загальних служб.
giorgiosironi

Це здається недостатньою, я вважаю, що все ще існують важкі випадкиapt-get -o Acquire::http::AllowRedirect=false update
Едвард Я. Ян

12

Примітка. На жаль, частина рішення нижче не працює в системах Ubuntu 16.04 (наприклад, у запитувача), оскільки запропоноване systemd-runвиклик працює лише на Ubuntu 18.04 і вище (детальніше див. У коментарях ). Я залишу відповідь тут, тому що це питання все ще є популярним хітом незалежно від того, яку версію Ubuntu ви використовуєте ...

У Ubuntu 18.04 (і вище) може бути до двох служб, що беруть участь у оновленнях та оновленнях часу завантаження. Перший apt-daily.serviceоновлює список пакунків. Однак може бути секунда, apt-daily-upgrade.serviceяка фактично встановлює критичні для безпеки пакети. Відповідь на «Terminate і відключити / видалити без нагляду поновлення , перш ніж команда повертає» питання дає відмінний приклад того , як чекати , поки обидва з них , щоб закінчити (скопійований тут для зручності):

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

(зауважте, це має бути запущено як root). Якщо ви намагаєтесь відключити ці сервіси на майбутніх черевиках, вам потрібно буде замаскувати ОСНОВНІ послуги:

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

Ви також можете systemctl disableобидва сервіси та пов'язані з ними таймери (тобто apt-daily.timerі apt-daily-upgrade.timer).

Зверніть увагу, що методи маскування / відключення у цій відповіді лише запобігають оновлення / оновлення майбутніх черевиків - вони не зупинять їх, якщо вони вже запущені в поточному завантаженні.


2
Відмінна відповідь, дякую! Хоча зауважте, що systemd-runUbuntu 16.04 занадто старий, щоб підтримувати цю --waitопцію, але це дійсно не повинно бути необхідним для потрібної мети. (За повідомленням людини, --waitчекає закінчення підрозділу, але достатньо дочекатися його запуску, що є поведінкою за замовчуванням systemd-run.)
Ріккардо Муррі

Я виправлюся: дана systemd-runчаклунство ніяк НЕ працює на Ubuntu 16.04 взагалі; воно вмирає з повідомленням про помилку Невідоме призначення Після = apt-daily.service apt-daily-upgrade.service . Схоже, деякі одиниці властивостей були недоступні systemd-run, див. Наприклад тут
Ріккардо Муррі

@ riccardo-murri ти мене отримав :-)! Мені насправді було цікаво про відмінності 16.04 / 18.04 (отже, чудово "до двох"), а потім забув поставити застереження. Яку зміну ви б запропонували?
Анон

@ riccardo-murri ах, це дуже погано, я додам велике попередження до початку відповіді, сказавши, що його не можна використовувати на Ubuntu 16.04
Anon

Вимкнули послуги та перезапустили, і це працює!
digz6666

4

Ви можете вимкнути це через модуль "bootcmd" та хмара-init. Це запускається до того, як мережа підведена, що потрібно, перш ніж вдале оновлення зможе отримати можливість запуску.

#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

Після того, як ви ssh в екземпляр, вам слід також дочекатися завершення завершальних фаз хмари-init, оскільки він переміщує влучні джерела / списки навколо.

# 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

Це також корисно для того, щоб побачити, як рано працює bootcmd:

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

Ви можете переконатися, що це спрацювало так:

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

Не було б простіше замаскувати пристрій

systemctl mask apt-daily.service

?


Не працює - див. Розділ 1. Вимкнення системного завдання в тексті запитання. Але все-таки дякую за пропозицію! :-)
Ріккардо Муррі

2
відключити та замаскувати послугу - це не те саме. маска створити Посилання на / dev / null. ls -al /etc/systemd/system/ | grep alsa lrwxrwxrwx 1 root root 9 Sep 1 13:17 alsa-init.service -> /dev/nullДані порожні.

2
я позбувся без нагляду оновлення sudo dpkg-reconfigure -plow unattended-upgradesта заборонив його. Тож статус підрозділу apt-daily.service мертвий.

Привіт @Bahamut дякую за ваші зусилля! Питання, однак, полягає в тому , як відключити apt-daily.serviceвід cloud-initсценарію і до того , як починається після VM перезавантаження: це означає , що : (1) воно повинно бути зроблено не інтерактивно, (2) воно повинно бути зроблено до apt-daily.serviceпожеж в перший раз. (Якщо моє розуміння systemd правильне, (2) насправді не можна досягти як cloud-initі apt-dailyзапустити одночасно - див. Мою власну відповідь для отримання додаткової інформації.)
Ріккардо Муррі

1
Я спробував це на звичайній фізичній машині (тобто не VM) і можу підтвердити, що вона не працює. Вам також потрібно зупинити таймер: systemctl зупинити apt-daily.timer; systemctl відключити apt-daily.timer
happyyskeptic

1

Він чекає 1 сек у циклі whil і ​​перевіряє, чи заблоковано замок.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.