¿Cómo deshabilitar `apt-daily.service` en la imagen de VM de nube de Ubuntu?

60

La imagen VM del servidor Ubuntu 16.04 aparentemente inicia el "apt-daily.service" cada 12 horas más o menos; Este servicio realiza varias tareas relacionadas con APT, como actualizar la lista de paquetes disponibles, realizar actualizaciones desatendidas si es necesario, etc.

Al comenzar desde una "instantánea" de VM, el servicio se activa de inmediato , ya que (supongo) systemd se da cuenta rápidamente de que el temporizador debería haberse apagado hace mucho tiempo.

Sin embargo, un APT en ejecución evita que otros aptprocesos se ejecuten ya que mantiene un bloqueo activado /var/lib/dpkg. El mensaje de error que indica esto se ve así:

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?

Necesito deshabilitar esta tarea APT automatizada hasta que Ansible haya completado la configuración de la máquina (que generalmente implica la instalación de paquetes); Consulte https://github.com/gc3-uzh-ch/elasticluster/issues/304 para obtener más información y contexto.

He probado varias opciones para deshabilitar la función de "actualizaciones desatendidas" a través de un script de "datos de usuario" cloud-init, pero todas han fallado hasta ahora.

1. Deshabilitar la tarea systemd

La tarea systemd apt-daily.servicees activada por apt-daily.timer. He intentado deshabilitar uno u otro, o ambos, con varias combinaciones de los siguientes comandos; aún así, apt-daily.servicese inicia momentos después de que la VM esté lista para aceptar conexiones SSH ::

    #!/bin/bash

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

2. Deshabilitar la opción de configuración APT::Periodic::Enable

El script /usr/lib/apt/apt.systemd.dailylee algunas variables de configuración APT; la configuración APT::Periodic::Enabledeshabilita la funcionalidad por completo (líneas 331--337). He intentado deshabilitarlo con el siguiente script ::

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

Sin embargo, a pesar de APT::Periodic::Enabletener valor 0desde la línea de comandos (ver más abajo), el unattended-upgradesprograma aún se ejecuta ...

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

3. Eliminar por /usr/lib/apt/apt.systemd.dailycompleto

El siguiente cloud-initscript elimina por completo el script de actualizaciones desatendidas:

    #!/bin/bash

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

Aún así, la tarea se ejecuta y puedo verla en la tabla de procesos. aunque el archivo no existe si se prueba desde la línea de comando ::

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

Parece que el cloud-initscript (junto con la línea de comandos SSH) y el proceso raíz del sistema se ejecutan en sistemas de archivos y espacios de proceso separados ...

Preguntas

¿Hay algo obvio que me estoy perdiendo? ¿O hay alguna magia de espacio de nombres que no conozco?

Lo más importante es: ¿Cómo puedo desactivar el apt-daily.servicea través de un cloud-initguión?

Riccardo Murri
fuente
2
Esto no lo ayudará hasta que se incluya en una actualización oficial del paquete, pero vea el parche que acabo de publicar en Debian bug # 844453 .
zwol
Tal vez le faltaba la --nowbandera en el systemctl disablecomando para que el cambio sea efectivo de inmediato. Ese fue mi problema.
Daniel F
@DanielF no, porque disable --nowes equivalente a stopseguido por disable.
sourcejedi
1
Aparentemente, esto se solucionó FINALMENTE en systemd en febrero de 2019: github.com/systemd/systemd/issues/5659 . Así que espero que sea en Ubuntu 20.04.
Snap

Respuestas:

38

Sí, había algo obvio que me faltaba.

Systemd tiene que ver con arranque simultáneo de los servicios, por lo que el cloud-initscript se ejecuta al mismo tiempo el apt-daily.servicese dispara. Para cuando cloud-initllega el momento de ejecutar la carga útil especificada por el usuario, apt-get updateya se está ejecutando. Por lo tanto, los intentos 2. y 3. fallaron no debido a alguna magia de espacio de nombres, sino porque alteraron el sistema demasiado tarde para apt.systemd.dailyrecoger los cambios.

Esto también significa que básicamente no hay forma de evitar que se apt.systemd.daily ejecute, solo se puede matar después de que se haya iniciado.

Este script de "datos de usuario" toma esta ruta ::

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

Todavía hay una ventana de tiempo durante la cual los inicios de sesión SSH son posibles, pero apt-get no se ejecutarán, pero no puedo imaginar otra solución que funcione en la imagen de la nube Ubuntu 16.04.

Riccardo Murri
fuente
Esto funcionó para mí en AWS ubuntu 16.04, gracias a la solución
krisdigitx
Sí, voy por el camino de crear un AMI personalizado. Esto también acelera la instalación de servicios comunes.
giorgiosironi
Esto no parece ser suficiente, creo que todavía hay instancias rezagadas deapt-get -o Acquire::http::AllowRedirect=false update
Edward Z. Yang
12

Nota: Desafortunadamente, parte de la solución a continuación no funciona en los sistemas Ubuntu 16.04 (como el del interrogador) porque la systemd-runinvocación sugerida solo funciona en Ubuntu 18.04 y superior (ver los comentarios para más detalles ). Dejaré la respuesta aquí porque esta pregunta sigue siendo un éxito popular, independientemente de la versión de Ubuntu que esté utilizando ...

En Ubuntu 18.04 (y superior) puede haber hasta dos servicios involucrados en el tiempo de arranque para actualizar / actualizar. El primero apt-daily.serviceactualiza la lista de paquetes. Sin embargo, puede haber un segundo apt-daily-upgrade.serviceque realmente instale paquetes críticos de seguridad. Una respuesta a la pregunta "Finalizar y deshabilitar / eliminar la actualización desatendida antes de que el comando regrese" ofrece un excelente ejemplo de cómo esperar a que ambos terminen (copiados aquí por conveniencia):

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

(tenga en cuenta que esto debe ejecutarse como root). Si está intentando deshabilitar estos servicios en futuras botas, deberá enmascarar AMBOS servicios:

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

Alternativamente, puede systemctl disableambos servicios Y sus temporizadores asociados (es decir, apt-daily.timery apt-daily-upgrade.timer).

Tenga en cuenta que las técnicas de enmascaramiento / desactivación en esta respuesta solo evitan la actualización / actualización en futuras botas; no las detendrán si ya se están ejecutando en el arranque actual.

Luego
fuente
2
Excelente respuesta, gracias! Aunque, tenga systemd-runen cuenta que en Ubuntu 16.04 es demasiado antiguo para admitir la --waitopción, pero realmente no debería ser necesario para el propósito en cuestión. (De acuerdo con la página del manual, --waitespera la terminación de una unidad, pero es suficiente para esperar su inicio, que es el comportamiento predeterminado de systemd-run).
Riccardo Murri
Estoy corregido: el systemd-runencantamiento dado no funciona en Ubuntu 16.04 en absoluto; muere con mensaje de error Asignación desconocida Después = apt-daily.service apt-daily-upgrade.service . Parece que algunas propiedades de la unidad no estaban disponibles systemd-run, ver por ejemplo aquí
Riccardo Murri
@ riccardo-murri me tienes :-)! De hecho, me preguntaba acerca de las diferencias de 16.04 / 18.04 (de ahí la comadreja "hasta dos") y luego olvidé poner la advertencia. ¿Qué cambio sugeriría?
Anon
@ riccardo-murri ah, eso es una lástima. Agregaré una gran advertencia en la parte superior de la respuesta diciendo que no se puede usar en Ubuntu 16.04
Anon
Deshabilitó los servicios y reinició y funciona!
digz6666
4

Puede deshabilitar esto a través del módulo "bootcmd" cloud-init. Esto se ejecuta antes de que aparezca la red, lo cual es necesario antes de que apt update pueda tener la oportunidad de ejecutarse.

#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

Una vez que ingrese a la instancia, también debe esperar a que finalicen las fases finales de cloud-init, ya que mueve las fuentes / listas aptas.

# 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

Esto también es útil para ver qué tan temprano se ejecuta bootcmd:

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

Puede verificar que esto funcionó de la siguiente manera:

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
fuente
2

No sería más fácil enmascarar la unidad

systemctl mask apt-daily.service

?


fuente
No funciona: consulte la sección 1. Desactive la tarea systemd en el texto de la pregunta. Pero gracias de todos modos por la sugerencia! :-)
Riccardo Murri
2
deshabilitar y enmascarar un servicio no es lo mismo. máscara crear un enlace a / dev / null. ls -al /etc/systemd/system/ | grep alsa lrwxrwxrwx 1 root root 9 Sep 1 13:17 alsa-init.service -> /dev/nullLos datos están vacíos.
2
sudo dpkg-reconfigure -plow unattended-upgradesMe deshago de la actualización desatendida y la pierdo. Entonces el estado de la unidad apt-daily.service está muerto.
Hola @Bahamut, gracias por tus esfuerzos! La pregunta, sin embargo, es cómo deshabilitar apt-daily.serviceun cloud-initscript y antes de que comience después del reinicio de VM: esto significa: (1) debe hacerse de forma no interactiva, (2) debe hacerse antes de los apt-daily.serviceincendios por primera vez. (Si mi comprensión de systemd es correcta, (2) en realidad no se puede lograr cloud-inity apt-dailyejecutar simultáneamente; vea mi propia respuesta para más información.)
Riccardo Murri
1
Intenté esto en una máquina física normal (es decir, no una VM) y puedo confirmar que no funciona. También debe detener el temporizador: systemctl stop apt-daily.timer; systemctl disable apt-daily.timer
happyskeptic
1

Esto espera 1 segundo en un ciclo y comprueba si se libera el bloqueo.

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
fuente