Come disabilitare `apt-daily.service` sull'immagine VM cloud di Ubuntu?


60

L'immagine della VM del server Ubuntu 16.04 apparentemente avvia "apt-daily.service" ogni 12 ore circa; questo servizio esegue varie attività relative ad APT come aggiornare l'elenco dei pacchetti disponibili, eseguire aggiornamenti automatici se necessario, ecc.

Quando si parte da uno "snapshot" della macchina virtuale, il servizio viene attivato immediatamente , poiché (presumo) systemd si rende conto rapidamente che il timer dovrebbe essere scaduto molto tempo fa.

Tuttavia, un APT in esecuzione impedisce l'esecuzione di altri aptprocessi poiché contiene un blocco /var/lib/dpkg. Il messaggio di errore che indica questo è simile al seguente:

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?

Devo disabilitare questa attività APT automatizzata fino a quando Ansible non avrà completato l'installazione della macchina (che in genere comporta l'installazione di pacchetti); vedi https://github.com/gc3-uzh-ch/elasticluster/issues/304 per maggiori informazioni e contesto.

Ho provato varie opzioni per disabilitare la funzione "Aggiornamenti non presidiati" tramite uno script "Dati utente" per cloud-init, ma finora tutti hanno fallito.

1. Disabilitare l'attività di systemd

l'attività di systemd apt-daily.serviceè attivata da apt-daily.timer. Ho provato a disabilitare l'uno o l'altro, o entrambi, con varie combinazioni dei seguenti comandi; tuttavia, apt-daily.serviceviene avviato pochi istanti dopo che la VM è pronta per accettare le connessioni SSH:

    #!/bin/bash

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

2. Disabilita l'opzione di configurazione APT::Periodic::Enable

Lo script /usr/lib/apt/apt.systemd.dailylegge alcune variabili di configurazione APT; l'impostazione APT::Periodic::Enabledisabilita completamente la funzionalità (righe 331--337). Ho provato a disabilitarlo con il seguente 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

Tuttavia, nonostante APT::Periodic::Enableabbia valore 0dalla riga di comando (vedi sotto), il unattended-upgradesprogramma è ancora in esecuzione ...

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

3. Rimuovere del /usr/lib/apt/apt.systemd.dailytutto

Il seguente cloud-initscript rimuove del tutto lo script degli aggiornamenti non presidiati ::

    #!/bin/bash

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

Tuttavia, l'attività viene eseguita e posso vederla nella tabella dei processi! sebbene il file non esista se sondato dalla riga di comando ::

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

Sembra che lo cloud-initscript (insieme alla riga di comando SSH) e il processo root systemd vengano eseguiti in filesystem e spazi di processo separati ...

Domande

C'è qualcosa di ovvio che mi manca? O c'è qualche magia dello spazio dei nomi in corso di cui non sono a conoscenza?

Ancora più importante: come posso disabilitare il apt-daily.servicetramite uno cloud-initscript?


2
Questo non ti aiuterà fino a quando non verrà inserito in un aggiornamento ufficiale del pacchetto, ma per favore vedi la patch che ho appena pubblicato nel bug Debian # 844453 .
zwol,

Forse ti mancava la --nowbandiera nel systemctl disablecomando per rendere immediatamente effettiva la modifica. Questo era il mio problema.
Daniel F,

@DanielF no, perché disable --nowequivale a stopseguito da disable.
sourcejedi,

1
Apparentemente, questo è stato FINALMENTE risolto in systemd nel febbraio 2019: github.com/systemd/systemd/issues/5659 . Quindi speriamo che sia in Ubuntu 20.04.
scatto il

Risposte:


38

Sì, c'era qualcosa di ovvio che mi mancava.

Systemd è tutto di inizio concomitante dei servizi, in modo che lo cloud-initscript viene eseguito allo stesso tempo l' apt-daily.serviceviene attivato. Al momento cloud-initdi eseguire il payload specificato dall'utente, apt-get updateè già in esecuzione. Quindi i tentativi 2. e 3. fallirono non a causa della magia dello spazio dei nomi, ma perché alterarono il sistema troppo tardi per apt.systemd.dailyraccogliere le modifiche.

Questo significa anche che praticamente non c'è modo di impedire l' apt.systemd.daily esecuzione: uno può ucciderlo solo dopo che è stato avviato.

Questo script "dati utente" utilizza questa route:

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

C'è ancora una finestra temporale durante la quale sono possibili accessi SSH ma apt-get non funzioneranno, ma non riesco a immaginare un'altra soluzione in grado di funzionare sull'immagine cloud di Ubuntu 16.04.


questo ha funzionato per me su aws ubuntu 16.04, grazie per la soluzione
krisdigitx

Sì, sto andando sulla strada della creazione di un AMI personalizzato. Ciò accelera anche l'installazione di servizi comuni.
giorgiosironi,

Questo non sembra essere abbastanza, trovo che ci siano ancora esempi sconcertanti diapt-get -o Acquire::http::AllowRedirect=false update
Edward Z. Yang

12

Nota: purtroppo parte della soluzione di seguito non funziona sui sistemi Ubuntu 16.04 (come quello dell'interrogatore) perché l' systemd-runinvocazione suggerita funziona solo su Ubuntu 18.04 e versioni successive (vedere i commenti per i dettagli ). Lascerò la risposta qui perché questa domanda è ancora un successo popolare indipendentemente da quale versione di Ubuntu stai usando ...

Su Ubuntu 18.04 (e versioni successive) potrebbero esserci fino a due servizi coinvolti nell'aggiornamento / aggiornamento del tempo di avvio. Il primo apt-daily.serviceaggiorna l'elenco dei pacchetti. Tuttavia, potrebbe esserci un secondo apt-daily-upgrade.serviceche installa effettivamente i pacchetti critici per la sicurezza. Una risposta alla domanda "Termina e disabilita / rimuovi aggiornamento automatico prima della restituzione del comando" fornisce un eccellente esempio di come attendere il completamento di entrambi (copiato qui per comodità):

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

(nota che questo deve essere eseguito come root). Se stai provando a disabilitare questi servizi su stivali futuri dovrai mascherare ENTRAMBI i servizi:

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

In alternativa è possibile utilizzare systemctl disableentrambi i servizi E i relativi timer associati (ovvero apt-daily.timere apt-daily-upgrade.timer).

Nota che le tecniche di mascheramento / disabilitazione in questa risposta impediscono l'aggiornamento / upgrade solo su boot futuri: non li fermeranno se sono già in esecuzione nel boot corrente.


2
Ottima risposta, grazie! Tuttavia, si noti che systemd-runsu Ubuntu 16.04 è troppo vecchio per supportare l' --waitopzione, ma non dovrebbe essere realmente necessario per lo scopo in questione. (Secondo la pagina man, --waitattende la fine di un'unità, ma è sufficiente attendere il suo inizio, che è il comportamento predefinito di systemd-run.)
Riccardo Murri,

Sono corretto: l' systemd-runincantesimo dato non funziona affatto su Ubuntu 16.04; muore con messaggio di errore Assegnazione sconosciuta After = apt-daily.service apt-daily-upgrade.service . Sembra che alcune proprietà dell'unità non siano disponibili in systemd-run, vedi ad esempio qui
Riccardo Murri il

@ riccardo-murri mi hai preso :-)! In realtà mi stavo chiedendo delle differenze tra il 16.04 / 18.04 (da qui il "weaselly" fino a due ") e poi ho dimenticato di mettere in guardia. Quale cambiamento suggeriresti?
Anon,

@ riccardo-murri ah è un peccato che aggiungerò un grosso avvertimento all'inizio della risposta dicendo che non può essere usato su Ubuntu 16.04
Anon,

Disabilitato i servizi e riavviato e funziona!
digz6666,

4

Puoi disabilitarlo tramite il modulo cloud-init "bootcmd". Questo viene eseguito prima dell'attivazione della rete, necessaria prima che l'aggiornamento apt possa avere la possibilità di funzionare.

#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 volta immesso nell'istanza, dovresti anche attendere il completamento delle fasi finali di cloud-init, poiché sposta le fonti / gli elenchi apt.

# 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

Questo è utile anche per vedere quanto è in esecuzione bootcmd:

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

Puoi verificarlo nel modo seguente:

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

Woud non è più facile mascherare l'unità

systemctl mask apt-daily.service

?


Non funziona - vedere la sezione 1. Disabilitare l'attività systemd nel testo della domanda. Ma grazie comunque per il suggerimento! :-)
Riccardo Murri,

2
disabilitare e mascherare un servizio non è lo stesso. maschera crea un collegamento a / dev / null. ls -al /etc/systemd/system/ | grep alsa lrwxrwxrwx 1 root root 9 Sep 1 13:17 alsa-init.service -> /dev/nulli dati sono vuoti.

2
mi libero l'aggiornamento incustodito sudo dpkg-reconfigure -plow unattended-upgradese lo proibisco. Quindi lo stato dell'unità apt-daily.service è morto.

Ciao @Bahamut grazie per i tuoi sforzi! La domanda, tuttavia, è come disabilitare apt-daily.serviceda uno cloud-initscript e prima che inizi dopo il riavvio della VM: questo significa: (1) deve essere fatto in modo non interattivo, (2) deve essere fatto prima degli apt-daily.serviceincendi per la prima volta. (Se la mia comprensione di systemd è corretta, (2) in realtà non può essere realizzato cloud-inite apt-dailyeseguito contemporaneamente - vedere la mia risposta per ulteriori informazioni.)
Riccardo Murri,

1
Ho provato questo su una normale macchina fisica (cioè non una VM) e posso confermare che non funziona. È necessario arrestare anche il timer: systemctl stop apt-daily.timer; systemctl disable apt-daily.timer
happyskeptic

1

Questo attende 1 secondo in un ciclo continuo e controlla se il blocco viene rilasciato.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.