Comment faire en sorte qu'un gestionnaire de paquets attende si une autre instance d'APT est en cours d'exécution?

45

J'ai vu de nombreux logiciels tels que Update Manager et Synaptic Package Manager. Ils attendent si un autre programme utilise le /var/lib/dpkg/lock et est verrouillé. Comment pouvons-nous faire cela via le terminal? J'ai vu le manuel de apt-get mais je n'ai rien trouvé d'utile.

    
posée Piyush 05.05.2012 - 15:09
la source

8 réponses

31

Vous pouvez utiliser la commande aptdcon mettre en file d'attente les tâches du gestionnaire de paquets en communiquant avec aptdaemon au lieu d'utiliser apt-get directement.

Donc, en gros, vous pouvez simplement faire sudo aptdcon --install chromium-browser ou quoi que ce soit et tant que cette commande est exécutée, vous pouvez l'exécuter à nouveau, mais installer différents packages et apt-daemon les mettra en file d'attente au lieu d'être erronés.

Ceci est particulièrement utile si vous effectuez une mise à niveau longue ou autre et que vous souhaitez continuer à installer des packages ou si vous écrivez quelque chose ensemble et que vous voulez vous assurer que l'installation sera plus fiable.

    
réponse donnée Jorge Castro 22.12.2012 - 21:55
la source
41

Vous pouvez faire en sorte que apt-get apprenne à attendre si un autre gestionnaire de logiciels est en cours d'exécution. Quelque chose de similaire avec le comportement de la prochaine distribution d'écran:

Commentjel'aifait?

Jecréeunnouveauscriptappeléapt-get(wrapperpourapt-get)danslerépertoire/usr/local/sbinaveclecodebashsuivant:

#!/bin/bash i=0 tput sc while fuser /var/lib/dpkg/lock >/dev/null 2>&1 ; do case $(($i % 4)) in 0 ) j="-" ;; 1 ) j="\" ;; 2 ) j="|" ;; 3 ) j="/" ;; esac tput rc echo -en "\r[$j] Waiting for other software managers to finish..." sleep 0.5 ((i=i+1)) done /usr/bin/apt-get "[email protected]"

N'oubliez pas de le rendre exécutable:

sudo chmod +x /usr/local/sbin/apt-get

Avant de tester, vérifiez si tout va bien. La sortie de la commande which apt-get devrait maintenant être /usr/local/sbin/apt-get . La raison en est que: par défaut, le répertoire /usr/local/sbin est placé avant le répertoire /usr/bin dans l'utilisateur ou la racine PATH .

    
réponse donnée Radu Rădeanu 10.11.2013 - 17:27
la source
20

Outre l'évidente && , vous pouvez rechercher aptdcon . Cet outil est capable de détecter d'autres instances d'apt et d'attendre qu'elles se terminent:

sudo aptdcon --safe-upgrade
[/]  11% Waiting for other software managers to quit Waiting for aptitude

(J'utilise aptitude ailleurs)

L’avantage de cet outil est que vous pouvez stocker plusieurs actions de manière consécutive sans vous inquiéter de ce que vous ferez ensuite. aptdcon est idéal pour les scripts sans assistance et l’installation d’interfaces graphiques, car vous pouvez autoriser l’exécution de l’outil en arrière-plan sans bloquer votre interface.

Les opérations supportées par aptdcon sont:

  • --refresh , -c : C'est l'équivalent de apt-get update . Il met à jour votre liste de paquets.
  • --install , --remove , --upgrade , --purge , --downgrade . Chacun fait comme son nom l'indique. Le nom du ou des colis est obligatoire. -i , -r , -u , -p : ce sont les options abrégées pour toutes les personnes sauf la rétrogradation, qui n'en ont pas.
  • --safe-upgrade , --full-upgrade sont les contreparties de apt-get , de upgrade / dist-upgrade et de aptitude , de safe-upgrade / full-upgrade . Ceux-ci n'ont pas besoin de paramètres.
  • Il existe plusieurs autres opérations, qui peuvent être trouvées dans le manuel. Mais ce sont les utilisateurs les plus utilisés par aptd . Certaines options chevauchent ce que apt-key , apt-cache , dpkg do.

apt-get lui-même ne supporte pas de telles méthodes (pour attendre d'autres instances d'apt), donc aptdcon est la solution préférée par les gestionnaires de paquets de l'interface graphique: USC utilise aptd en tant que back-end, comme Synaptic. Une autre solution est packagekit , mais elle ne prend pas en charge la fonction que vous recherchez (pour le moment).

    
réponse donnée Braiam 09.11.2013 - 13:19
la source
16

Une approche très simple consisterait en un script qui attendait que le verrou ne soit pas ouvert. Appelons-le waitforapt et collez-le dans /usr/local/bin :

#!/bin/sh

while sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock >/dev/null 2>&1; do
   sleep 1
done

Ensuite, lancez sudo waitforapt && sudo apt-get install whatever . Vous pouvez ajouter des exceptions dans sudoers pour vous permettre de l'exécuter sans avoir besoin d'un mot de passe (vous en aurez besoin pour le apt-get , donc ce n'est pas un gain considérable).

Malheureusement, cela ne fait pas la queue. Etant donné que certaines opérations d'apt sont interactives ("Êtes-vous sûr de vouloir supprimer tous ces paquets?!"), Je ne vois pas comment contourner ce problème ...

    
réponse donnée Oli 09.11.2013 - 13:50
la source
3

Vous pouvez utiliser une technique d'interrogation:

$ time (while ps -opid= -C apt-get > /dev/null; do sleep 1; done); \
  apt-get -y install some-other-package
    
réponse donnée malthe 09.12.2013 - 23:29
la source
3

J'ai créé un script qui fait ceci:

#!/bin/bash

# File path to watch
LOCK_FILE='/var/lib/dpkg/lock'

# tput escape codes
cr="$(tput cr)"
clr_end="$(tput el)"
up_line="$(tput cuu 1)"

CLEAN(){
    # Cleans the last two lines of terminal output,
    # returns the cursor to the start of the first line
    # and exits with the specified value if not False

    echo -n "$cr$clr_end"
    echo
    echo -n "$cr$clr_end$up_line"
    if [[ ! "$1" == "False" ]]; then
        exit $1
    fi
}

_get_cmdline(){
    # Takes the LOCKED variable, expected to be output from 'lsof',
    # then gets the PID and command line from '/proc/$pid/cmdline'.
    #
    # It sets '$open_program' to a user friendly string of the above.

    pid="${LOCKED#p}"
    pid='echo $pid | sed 's/[\n\r ].*//''
    cmdline=()
    while IFS= read -d '' -r arg; do
        cmdline+=("$arg")
    done < "/proc/${pid}/cmdline"
    open_program="$pid : ${cmdline[@]}"
}

# Default starting value
i=0

# Checks if the file is locked, writing output to $FUSER
while LOCKED="$(lsof -F p "$LOCK_FILE" 2>/dev/null)" ; do
    # This will be true if it isn't the first run
    if [[ "$i" != 0 ]]; then
        case $(($i % 4)) in
            0 ) s='-'
                i=4
                _get_cmdline # Re-checks the command line each 4th iteration
            ;;
            1 ) s=\ ;;
            2 ) s='|' ;;
            3 ) s='/' ;;
        esac
    else
        # Traps to clean up the printed text and cursor position
        trap "CLEAN False; trap - SIGINT ; kill -SIGINT $$" SIGINT
        trap 'CLEAN $((128+15))' SIGTERM
        trap 'CLEAN $((128+1))' SIGHUP
        trap 'CLEAN $((128+3))' SIGQUIT

        # Default starting character
        s='-'

        _get_cmdline
        echo -n "$save_cur"
    fi
    # Prints the 2nd line first so the cursor is at the end of the 1st line (looks nicer)
    echo
    echo -n "$cr$clr_end$open_program"
    echo -n "$up_line$res_cur$cr$clr_end[$s] Waiting for other package managers to finish..."
    #echo -en "$cr$clr_end[$s] Waiting for other package managers to finish..."
    #echo -en "\n$cr$clr_end$open_program$cr$up_line"
    ((i++))
    sleep 0.025
done

CLEAN False

# This allows saving the script under a different name (e.g. 'apt-wait')
# and running it. It only imitates 'apt-get' if it was launched as such
if [[ "${0##*/}" == 'apt-get' ]]; then
    exec /usr/bin/apt-get "[email protected]"
    exit $?
fi

Enregistrez ce qui précède dans /usr/local/sbin/apt-get . apt-get attendra ensuite si une autre instance est déjà en cours d'exécution.

Sinon, enregistrez-le sous /usr/local/sbin/apt-wait , exemple d'utilisation:

apt-wait && aptitude

qui exécutera aptitude après la fin du processus en cours contenant le verrou.

Example run:

  1. First, an apt-get command is run, for example:

    $ sudo apt-get remove some_package
    
  2. Then, in another terminal, another command is run:

    $ sudo apt-get install some_other_package
    

    It will wait for the first command to finish then run. Output while waiting:

    [/] Waiting for other package managers to finish...
          28223 : /usr/bin/apt-get remove some_package
    
    
réponse donnée kiri 19.01.2014 - 05:32
la source
2

Malheureusement, l’unité de fusion ne fait pas grand chose pour vous lorsque vous utilisez plusieurs conteneurs d’espace de noms non privilégiés comme lxc.

En outre, aptdcon n’est pas installé par défaut (au moins le 18.04) et met votre tâche en arrière-plan dans une file d’attente afin que vous perdiez la sérialisation. Ce n'est pas insurmontable, mais cela signifie que votre automatisation doit avoir un moyen d'éviter les erreurs de flock dans apt lors de l'installation d'aptdcon, et vous aurez besoin d'une sorte de boucle d'attente pour tout ce que vous devez sérialiser après avoir installé des paquets via aptdcon. sauf s'il existe déjà une sorte de drapeau pour cela.

Qu'est-ce que le travail est troupeau. Cela devrait également fonctionner sur NFS, etc., car il utilise le verrouillage de système de fichiers de la même façon qu'apt, mais avec le paramètre -w secondes, il attendra sur votre verrou au lieu de générer une erreur.

En suivant le modèle de wrapper, ajoutez ceci en tant que apt-get dans / usr / local / bin / et partagez-le.

Cela présente également l’avantage de limiter les E / S en ne permettant pas le parallélisme sur apt pour que vous puissiez laisser cron déclencher les mises à jour à minuit partout sans frapper le disque.

#!/bin/bash
exec /usr/bin/flock -w 900 -F --verbose /var/cache/apt/archives/lock /usr/bin/apt-get [email protected]  

Une demande de fonctionnalité simple et agréable pour apt-get serait un drapeau -w permettant de passer à un verrou bloquant / en attente.

    
réponse donnée 07.09.2018 - 20:02
la source
0

Une ligne basée sur la réponse d'Oli :

while sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock >/dev/null 2>&1; do sleep 1; done
    
réponse donnée Menasheh 27.02.2018 - 07:55
la source

Lire d'autres questions sur les étiquettes