Как заставить диспетчер пакетов ждать, будет ли запущен другой экземпляр APT?

45

Я видел много программ, таких как Update Manager и Synaptic Package Manager, они ждут, если какая-либо другая программа использует /var/lib/dpkg/lock и заблокирована. Как мы можем это сделать через Терминал? Я видел руководство apt-get , но не нашел ничего полезного.

    
задан Piyush 05.05.2012 в 13:09
источник

8 ответов

31

Вы можете использовать команду aptdcon , чтобы ставить задачи диспетчера пакетов, связываясь с aptdaemon вместо прямого использования apt-get.

Таким образом, вы можете просто сделать sudo aptdcon --install chromium-browser или что-то еще, и пока эта команда работает, вы можете запустить ее снова, но установить разные пакеты, а apt-daemon просто остановит их, вместо того, чтобы выходить из строя.

Это особенно полезно, если вы делаете длинный апгрейд или что-то еще, и хотите продолжать установку пакетов, или если вы что-то пишете вместе, и хотите, чтобы установка была более надежной.     

ответ дан Jorge Castro 22.12.2012 в 20:55
источник
40

Вы можете сделать apt-get , чтобы научиться ждать, если будет запущен другой менеджер программного обеспечения. Что-то похожее на поведение из следующего экрана:

Какяэтосделал?

Ясоздаюновыйскриптсименемapt-get(wrapperдляapt-get)вкаталоге/usr/local/sbinсоследующимкодомbashвнутри:

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

Не забудьте сделать его выполнимым:

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

Прежде чем тестировать, проверьте, все ли в порядке. Результат команды which apt-get теперь должен быть /usr/local/sbin/apt-get . Причина такова: по умолчанию каталог /usr/local/sbin помещается перед /usr/bin в каталоге пользователя или root PATH .

    
ответ дан Radu Rădeanu 10.11.2013 в 16:27
20

Помимо очевидного && , вы можете искать aptdcon . Этот инструмент способен обнаруживать другие экземпляры apt и ждать их завершения:

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

(Я использую aptitude в другом месте)

Преимущество этого инструмента заключается в том, что вы можете выполнять несколько действий последовательно, не беспокоясь о том, что вы будете делать дальше. aptdcon идеально подходит для автономных скриптов и установки графического интерфейса, поскольку вы можете позволить инструменту работать в фоновом режиме, чтобы не блокировать внешний интерфейс.

Операциями, поддерживаемыми aptdcon , являются:

  • --refresh , -c : Это эквивалентно apt-get update . Он обновляет список пакетов.
  • --install , --remove , --upgrade , --purge , --downgrade . Каждый из них делает, как говорят их имена. Название пакета (ов) является обязательным. -i , -r , -u , -p : это короткие варианты для всех, кроме понижения, у кого их нет.
  • --safe-upgrade , --full-upgrade являются аналогами apt-get upgrade / dist-upgrade и aptitude safe-upgrade / full-upgrade . Им не нужны параметры.
  • Есть несколько других операций, которые можно найти в руководстве. Но они наиболее часто используются пользователями, заинтересованными в aptd . Есть варианты, которые перекрываются с тем, что apt-key , apt-cache , dpkg делают.

apt-get сам не поддерживает такие методы (ждать других экземпляров apt), поэтому aptdcon является предпочтительным решением для менеджеров пакетов GUI: USC использует aptd как back-end, то же, что и Synaptic. Другое решение - packagekit , но оно не поддерживает функцию, которую вы ищете (пока).

    
ответ дан Braiam 09.11.2013 в 12:19
16

Очень простой подход - это сценарий, который ждал, что блокировка не будет открыта. Назовем его waitforapt и вставьте его в /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

Затем просто запустите sudo waitforapt && sudo apt-get install whatever . Вы можете добавить исключения в sudoers , чтобы вы могли запускать его без необходимости пароля (вам понадобится его для apt-get , поэтому он не имеет большого выигрыша).

К сожалению, это не помещает в очередь вещи. Учитывая, что некоторые из операций apt являются интерактивными («Вы уверены, что хотите удалить все эти пакеты ?!»), я не вижу в этом хорошего пути ...

    
ответ дан Oli 09.11.2013 в 12:50
3

Вы можете использовать метод опроса:

$ time (while ps -opid= -C apt-get > /dev/null; do sleep 1; done); \
  apt-get -y install some-other-package
    
ответ дан malthe 09.12.2013 в 22:29
3

Я сделал скрипт, который делает это:

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

Сохраните выше в /usr/local/sbin/apt-get . apt-get будет ждать, если другой экземпляр уже запущен.

В качестве альтернативы сохраните его как /usr/local/sbin/apt-wait , пример использования:

apt-wait && aptitude

, который будет запускать aptitude после того, как завершился текущий процесс, удерживающий блокировку.

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
    
    
ответ дан kiri 19.01.2014 в 04:32
2

К сожалению, фьюзер не делает много для вас, когда вы работаете в разных непривилегированных контейнерах пространства имен, таких как lxc.

Кроме того, aptdcon не установлен по умолчанию (по крайней мере, 18.04) и фону вашей задачи в очереди, поэтому вы теряете сериализацию. Это не является непреодолимым, но это означает, что ваша автоматизация должна иметь некоторый способ избежать ошибок flock в apt при установке aptdcon, и вам нужно будет иметь какие-то циклы ожидания для всего, что вам нужно для сериализации после установки пакетов через aptdcon если для этого уже есть какой-то флаг.

Что делает стая. Это также должно работать над NFS и т. Д., Поскольку он использует блокировку файловой системы тем же способом, что и apt, только с параметром -w seconds он будет ждать вашей блокировки вместо того, чтобы бросать ошибку.

Итак, следуя модели обертки, добавьте это как apt-get в / usr / local / bin / и разделите.

Это также имеет преимущество ограничения IO, не допуская параллелизма на apt, чтобы вы могли позволить cron запускать обновления в полночь повсюду, не избивая диск.

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

Очень приятный и простой запрос функции для apt-get будет флагом -w, чтобы переключиться на блокировку / блокировку ожидания.

    
ответ дан Raymond Ferguson 07.09.2018 в 18:02
0

Однострочный на основе Ответ Оли :

while sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock >/dev/null 2>&1; do sleep 1; done
    
ответ дан Menasheh 27.02.2018 в 06:55