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

Да, это называется Linelight.

Установите пакет sudo apt-get install xfce4-linelight-plugin

Затем добавьте апплет Linelight на панель

1
задан 21 April 2014 в 19:26

6 ответов

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

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

Создаю новый скрипт под названием apt-get (обертка для [ f5]) в каталоге /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 "$@"

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

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

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

38
ответ дан 25 May 2018 в 11:51
  • 1
    это действительно прямой удар по моему вопросу. благодаря :) – Ten-Coin 10 November 2013 в 22:32
  • 2
    Как ваш скрипт управляет сложными экземплярами apt-get? Например, до того, как он закончится, я запустил еще 5 apt-get? – Braiam 11 November 2013 в 07:14
  • 3
    @Braiam С уважением, я не знаю; Я не очень хороший тестер. Вы проверили это? Если возникают проблемы, сценарий можно улучшить, создав новую блокировку с меткой времени, когда начнется новый экземпляр скрипта (просто пример - есть и много других способов). – Radu Rădeanu 15 November 2013 в 03:03
  • 4
    Вау! красноречив. работает как шарм со всем, что я бросил на него до сих пор! Два больших пальца ... это должно быть просто частью пакета: D – Eric 4 July 2017 в 21:27
  • 5
    Отлично! У меня возникла проблема, когда я использую AWS cloudinit для установки пакетов на новый сервер, но Ubuntu делает некоторые вещи apt при загрузке, поэтому моя команда dpkg завершилась неудачно из-за блокировки dpkg db. Я поместил этот однострочный слой в свои userdata userdata: while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 1; done; dpkg -i package.deb, и он отлично работает. – Volodymyr Smotesko 19 July 2017 в 17:45

Помимо очевидного &&, вы можете искать 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 's safe-upgrade / full-upgrade. Им не нужны параметры. Есть несколько других операций, которые можно найти в руководстве. Но они наиболее часто используются пользователями, заинтересованными в aptd. Есть варианты, которые перекрываются с тем, что делают apt-key, apt-cache, dpkg.

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

20
ответ дан 25 May 2018 в 11:51
  • 1
    aptdcon --install /path/to/pgk.deb Работает как dpkg -i, хотя я не смог найти это явно упомянутое в руководстве. – whitehat101 17 March 2016 в 22:05
  • 2
    Могу ли я использовать это в сценарии после установки в пакете? – Nelson Teixeira 3 January 2017 в 21:22
  • 3
    @NelsonTeixeira, почему вы используете это в скрипте ppst-install? Если выполняется пост-установка, выполняется явно apt. – Braiam 3 January 2017 в 21:26
  • 4
    Я хочу, чтобы postinstall установил некоторые специальные пакеты, которые не находятся в репозитории. Это возможно ? Я бы включил их в пакет, а затем скрипт установил их после завершения установки. – Nelson Teixeira 3 January 2017 в 21:32
  • 5
    @NelsonTeixeira снова, зачем это нужно? Сценарии после установки выполняются только при установке пакета. Я предлагаю вам задать вопрос вместо и объяснить ваше дело более подробно. – Braiam 3 January 2017 в 21:56

Очень простой подход - это сценарий, который ждал, что блокировка не будет открыта. Назовем его 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 являются интерактивными («Вы уверены, что хотите удалить все эти пакеты ?!»), я не вижу в этом хорошего пути ...

14
ответ дан 25 May 2018 в 11:51
  • 1
    возможно, -y принять да для всех операций? – Braiam 9 November 2013 в 19:36
  • 2
    Спасибо. Я думаю, что могу использовать его лучше, если я использую псевдоним. – Ten-Coin 9 November 2013 в 20:29
  • 3
    Не уверен, что -y желательно. – Oli♦ 10 November 2013 в 01:02
  • 4
    Я не думаю, что вы хотите обернуть sudo fuser в [[ $(...) ]]. Он возвращает нулевой код выхода при обращении к файлу, чтобы этого было достаточно. – kiri 10 November 2013 в 15:15
  • 5
    Я нашел следующее решение более полным, поскольку при работе с apt-get задействовано несколько блокировок: while sudo fuser /var/lib/dpkg/lock /var/lib/apt/lists/lock /var/cache/apt/archives/lock >/dev/null 2>&1; do echo 'Waiting for release of dpkg/apt locks'; sleep 5; done; sudo apt-get -yy update – Manuel Kiessling 7 December 2017 в 17:57

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

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

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

#!/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 "$@"
    exit $?
fi

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

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

apt-wait && aptitude

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

Пример выполнения: во-первых, выполняется команда apt-get, например:
$ sudo apt-get remove some_package
Затем на другом терминале запускается другая команда:
$ sudo apt-get install some_other_package
дождитесь завершения первой команды, а затем выполните ее. Выход во время ожидания:
[/] Waiting for other package managers to finish...
      28223 : /usr/bin/apt-get remove some_package
3
ответ дан 25 May 2018 в 11:51

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

while sudo fuser /var/{lib/{dpkg,apt/lists},cache/apt/archives}/lock >/dev/null 2>&1; do sleep 1; done
0
ответ дан 25 May 2018 в 11:51

Другие вопросы по тегам:

Похожие вопросы: