desarrollo-web-br-bd.com

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

El servidor Ubuntu 16.04 VM imagen 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 VM "instantánea", el servicio se activa inmediatamente , ya que (supongo) systemd se da cuenta rápidamente que el temporizador debería haberse disparado hace mucho tiempo.

Sin embargo, una ejecución APT evita que otros procesos apt se ejecuten ya que mantiene un bloqueo en /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 automatizada APT) hasta que Ansible haya completado la configuración de la máquina (que generalmente implica la instalación de paquetes); vea https://github.com/gc3-uzh-ch/elasticluster/issues/304 para más información y contexto.

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

1. Deshabilitar la tarea systemd

tarea systemd apt-daily.service es activado por apt-daily.timer. He intentado deshabilitar uno u otro, o ambos, con varias combinaciones de los siguientes comandos; aún así, el apt-daily.service se inicia momentos después de que el VM se prepara 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. Desactive la opción de configuración APT::Periodic::Enable

Guión /usr/lib/apt/apt.systemd.daily lee algunas APT variables de configuración; la configuración APT::Periodic::Enable desactiva 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 APT::Periodic::Enable que tiene valor 0 desde la línea de comando (ver abajo), el unattended-upgrades el programa aún se ejecuta ...

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

3. Eliminar /usr/lib/apt/apt.systemd.daily por completo

El seguimiento cloud-init script elimina el script de actualizaciones desatendidas por completo ::

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

[email protected]:~$ 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-init script (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: ¿cómo puedo desactivar el apt-daily.service a través de un cloud-init script?

70
Riccardo Murri

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

Systemd tiene que ver con el inicio simultáneo de servicios, por lo que el cloud-init el script se ejecuta al mismo tiempo the apt-daily.service se activa. Para el momento cloud-init consigue ejecutar la carga útil especificada por el usuario, apt-get update ya se está ejecutando. Entonces, los intentos 2. y 3. fallaron no por alguna magia de espacio de nombres, sino porque alteraron el sistema demasiado tarde para apt.systemd.daily para recoger los cambios.

Esto también significa que básicamente no hay forma de prevenirapt.systemd.daily de la ejecución: 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 todavía apt-get no se ejecutará, pero no puedo imaginar otra solución que funcione en la imagen de la nube Ubuntu 16.04.

43
Riccardo Murri

Nota: Desafortunadamente, parte de la solución a continuación no funciona en los sistemas Ubuntu 16.04 (como la del interrogador) porque la sugerencia systemd-run invocación solo funciona en Ubuntu 18.04 y superior (vea 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.service actualiza la lista de paquetes. Sin embargo, puede haber un segundo apt-daily-upgrade.service que realmente instala paquetes críticos de seguridad. Un 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 (copiado 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, puedes systemctl disable ambos servicios Y sus temporizadores asociados (es decir, apt-daily.timer y apt-daily-upgrade.timer).

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

17
Anon

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
5
Karl Pickett

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

systemctl mask apt-daily.service

?

2
user192526

Basado en la solución de Anon, creé este script, que después de ejecutarlo y luego reiniciarlo, resuelve el problema para mí:

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

Si el propósito es aprovisionar la máquina sin incurrir en un error de bloqueo, la solución más simple y estable es ejecutar el comando remoto del aprovisionador (o los comandos relacionados con apt) mientras se bloquea el archivo de bloqueo apt-daily. Sin servicio de enmascaramiento/desactivación/espera, etc.etc.

En el servidor Ubuntu, los programas de actualización de paquetes (apt-daily, desatendido-actualizaciones, cloud-init), pasan por apt-daily, por lo que la solución puede centrarse en él.

Apt-daily usa los bloqueos flock(2), que, a diferencia de dpkg/apt (que usan fnctl), se pueden administrar mediante una herramienta de línea de comandos, con la conveniencia de que admite esperar en el bloqueo.

Por lo tanto, si uno, por ejemplo, usa Chef, es tan simple como correr, en los nodos:

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

y:

  • cualquier chef-cliente tomará la cerradura primero, y cualquier servicio basado en apt-daily esperará;
  • o cualquier servicio basado en apt-daily lo bloqueará primero, luego chef-clien esperará y finalmente se ejecutará una vez que apt-daily se complete.

Si no se invoca el aprovisionador en los nodos, es posible modificar la configuración del aprovisionador (por ejemplo, Ansible Playbook) para ejecutar:

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

(o cualquier variación, como sh -c '...' y así)

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

1
Marcus

Esto espera 1 segundo en un bucle while 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
1
Navidzj

Este cloud-init funciona.

#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