dpkg-query --showformat='${db:Status-Status}'
Это создает небольшую выходную строку, которая вряд ли изменится, и ее легко детерминировано сравнивать без grep
:
pkg=hello
status="$(dpkg-query -W --showformat='${db:Status-Status}' "$pkg" 2>&1)"
if [ ! $? = 0 ] || [ ! "$status" = installed ]; then
sudo apt install $pkg
fi
Проверка $? = 0
необходима, потому что, если вы никогда не устанавливали пакет раньше, и после удаления определенных пакетов, таких как hello
, dpkg-query
завершает работу со статусом 1 и выводит в stderr:
dpkg-query: no packages found matching hello
вместо вывода not-installed
. 2>&1
также фиксирует это сообщение об ошибке, когда оно появляется, препятствуя его переходу к терминалу.
Для нескольких пакетов:
pkgs='hello certbot'
install=false
for pkg in $pkgs; do
status="$(dpkg-query -W --showformat='${db:Status-Status}' "$pkg" 2>&1)"
if [ ! $? = 0 ] || [ ! "$status" = installed ]; then
install=true
break
fi
done
if "$install"; then
sudo apt install $pkgs
fi
Возможные статусы описаны в man dpkg-query
как:
n = Not-installed
c = Config-files
H = Half-installed
U = Unpacked
F = Half-configured
W = Triggers-awaiting
t = Triggers-pending
i = Installed
Версии с одной буквой можно получить с помощью db:Status-Abbrev
, но они идут вместе с действием и статусом ошибки, поэтому вы получаете 3 символа и должны их сократить.
Поэтому я думаю, что достаточно надежно полагаться на то, что статусы без заглавных букв (Config-files
против config-files
) не меняются.
dpkg -s
статус выхода
К сожалению, это не делает то, что хочет большинство пользователей:
pkgs='qemu-user pandoc'
if ! dpkg -s $pkgs >/dev/null 2>&1; then
sudo apt-get install $pkgs
fi
потому что для некоторых пакетов, например. certbot
, делаю:
sudo apt install certbot
sudo apt remove certbot
оставляет certbot
в состоянии config-files
, что означает, что файлы конфигурации остались в машине. И в этом состоянии dpkg -s
по-прежнему возвращает 0
, потому что метаданные пакета по-прежнему сохраняются, чтобы эти файлы конфигурации можно было обрабатывать более аккуратно.
Чтобы на самом деле заставить dpkg -s
вернуть 1, как хотелось бы, потребуется --purge
:
sudo apt remove --purge certbot
что фактически перемещает его в not-installed
/dpkg-query: no packages found matching
.
Обратите внимание, что только некоторые пакеты оставляют после себя файлы конфигурации. Более простой пакет, такой как hello
, переходит напрямую из installed
в not-installed
без --purge
.
Проверено на Ubuntu 20.10.
Пакет Python apt
В Ubuntu 18.04 есть предустановленный пакет Python 3 под названием apt
, который предоставляет интерфейс Python apt!
Сценарий, который проверяет, установлен ли пакет, и устанавливает его, если нет, можно увидеть по адресу: Как установить пакет с помощью API python-apt
Вот копия для справки:
#!/usr/bin/env python
# aptinstall.py
import apt
import sys
pkg_name = "libjs-yui-doc"
cache = apt.cache.Cache()
cache.update()
cache.open()
pkg = cache[pkg_name]
if pkg.is_installed:
print "{pkg_name} already installed".format(pkg_name=pkg_name)
else:
pkg.mark_install()
try:
cache.commit()
except Exception, arg:
print >> sys.stderr, "Sorry, package installation failed [{err}]".format(err=str(arg))
Проверить, находится ли исполняемый файл в PATH
См.: Как можно Я проверяю, существует ли программа из сценария Bash?
См. также
person
Ciro Santilli 新疆再教育营六四事件ۍ
schedule
17.01.2019
command -v <command>
; неwhich <command>
. Также см. раздел Проверить, существует ли программа из сценария Bash. - person jww   schedule 21.10.2017