Как проверить, установлен ли пакет, и установить его, если нет?

Я работаю над системой Ubuntu, и в настоящее время я делаю следующее:

if ! which command > /dev/null; then
   echo -e "Command not found! Install? (y/n) \c"
   read
   if "$REPLY" = "y"; then
      sudo apt-get install command
   fi
fi

Это то, что сделало бы большинство людей? Или есть более элегантное решение?


person John Jiang    schedule 19.08.2009    source источник
comment
Имена команд не всегда отражают имя пакета, которому они принадлежат. Какова ваша большая цель? Почему бы вам просто не попробовать установить его, и в худшем случае он не будет, так как он уже установлен.   -  person viam0Zah    schedule 19.08.2009
comment
К счастью, apt-get install является идемпотентным, поэтому можно просто запустить его и не беспокоиться о том, установлен он или нет.   -  person David Baucum    schedule 31.03.2016
comment
Связано, вы должны использовать command -v <command>; не which <command>. Также см. раздел Проверить, существует ли программа из сценария Bash.   -  person jww    schedule 21.10.2017
comment
@DavidBaucum Не совсем; запуск установки для уже установленного пакета обновит его, если он устарел. Обычно желательно быть в курсе проблем безопасности, но может быть неожиданностью, если желательна стабильность.   -  person Izkata    schedule 23.01.2018


Ответы (25)


Чтобы проверить, был ли установлен packagename, введите:

dpkg -s <packagename>

Вы также можете использовать dpkg-query, который имеет более аккуратный вывод для ваших целей и также принимает подстановочные знаки.

dpkg-query -l <packagename>

Чтобы узнать, какому пакету принадлежит command, попробуйте:

dpkg -S `which <command>`

Дополнительные сведения см. в статье Найти out, если пакет установлен в Linux и шпаргалка dpkg.

person viam0Zah    schedule 19.08.2009
comment
Если вы, как человек, хотите этого НЕ программно, вы можете использовать эту информацию в ее нынешнем виде. Однако вы не можете просто полагаться здесь на коды возврата для сценариев или только на вывод/отсутствие вывода для сценариев. Вам придется сканировать вывод этих команд, ограничивая их полезность для этого вопроса. - person UpAndAdam; 30.04.2013
comment
Как ни странно, я недавно обнаружил, что dpkg-query раньше возвращал 1 для отсутствующего пакета, теперь (Ubuntu 12.04) возвращает 0, вызывая всевозможные проблемы в моем скрипте установки узла сборки jenkins! dpkg -s возвращает 0, если пакет установлен, и 1, если пакет не установлен. - person Therealstubot; 22.08.2013
comment
Эй, ОП запросил if использование. Я также ищу if использование. - person Tomáš Zato - Reinstate Monica; 12.10.2015
comment
@Therealstubot: я также использую Ubuntu 12.04, и dpkg -s возвращает 1 при отсутствующих пакетах и ​​0 в противном случае, как и должно быть. Чем отличались более ранние (или недавние) версии? - person MestreLion; 28.12.2015
comment
@UpAndAdam, можете ли вы объяснить, почему нельзя полагаться на коды возврата? Мне нужно использовать что-то подобное, и оно работает правильно (проверено на установленном и удаленном пакете в Ubuntu 16.04) при использовании в операторе if. Есть ли какой-то сценарий, в котором это ненадежно? - person JBentley; 28.07.2016
comment
@JBentley По крайней мере, в то время, когда я писал это и использовал его; код возврата не указывал, был ли установлен пакет или нет. Показательно было только то, что процесс dpkg не обнаружил ошибки. Это могло измениться, и я больше не использую систему, которая ежедневно использует dpkg, поэтому я не могу комментировать дальше. Но, учитывая, что 11 других человек, казалось, согласились со мной, я думаю, что что-то вроде непоследовательных или не показательных кодов возврата действительно было проблемой. - person UpAndAdam; 01.08.2016
comment
@JBentley Посмотрите на комментарий ThorSummoner и укажите немного ниже на другой ответ, который цитирует мой комментарий, в котором точно описан сценарий, с которым я столкнулся. - person UpAndAdam; 03.08.2016
comment
примечание: dpkg -s возвращает ноль, если пакет был установлен, а затем удален - в этом случае это Status: deinstall ok config-files или аналогичный, так что все в порядке - так что для меня это небезопасный тест. dpkg-query -l в этом случае тоже не дает полезного результата. - person keen; 23.09.2016
comment
dpkg -s <package> | grep Status Не самое красивое решение, но вы можете просто провести небольшой анализ строки возвращаемого значения для этой команды, если хотите получить более подробный ответ. - person 0xVox; 31.05.2018

Чтобы быть немного более явным, вот небольшой скрипт bash, который проверяет наличие пакета и устанавливает его, если это необходимо. Конечно, вы можете предпринять другие действия, обнаружив, что пакет отсутствует, например, просто выйти с кодом ошибки.

REQUIRED_PKG="some-package"
PKG_OK=$(dpkg-query -W --showformat='${Status}\n' $REQUIRED_PKG|grep "install ok installed")
echo Checking for $REQUIRED_PKG: $PKG_OK
if [ "" = "$PKG_OK" ]; then
  echo "No $REQUIRED_PKG. Setting up $REQUIRED_PKG."
  sudo apt-get --yes install $REQUIRED_PKG 
fi

Если скрипт работает в графическом интерфейсе (например, это скрипт Nautilus), вы, вероятно, захотите заменить вызов «sudo» вызовом «gksudo».

person Urhixidur    schedule 03.05.2012
comment
--force-yes кажется плохой идеей. Со страницы руководства: Это опасная опция, которая приведет к тому, что apt-get продолжит работу без запроса, если он делает что-то потенциально опасное. Его не следует использовать, за исключением очень особых ситуаций. Использование --force-yes потенциально может разрушить вашу систему! Использование его в сценарии делает его еще хуже. - person reducing activity; 28.01.2018
comment
Что означает ${Статус}? - person SaladHead; 26.02.2021
comment
@SaladHead См. man7.org/linux/man-pages/man1 /dpkg-query.1.html Информация о пакете может быть включена [в showformat] путем вставки переменных ссылок на поля пакета с использованием синтаксиса «${field[;width]}». Статус — одно из таких полей. - person Urhixidur; 30.06.2021

Этот однострочник возвращает 1 (установлено) или 0 (не установлено) для пакета «нано».

$(dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed")

даже если пакет не существует/не доступен.

В приведенном ниже примере устанавливается пакет «nano», если он не установлен.

if [ $(dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed") -eq 0 ];
then
  apt-get install nano;
fi
person Seb    schedule 23.03.2014
comment
Моя вариация на эту тему: dpkg-query -W -f='${Status}' MYPACKAGE | grep -q -P '^install ok installed$'; echo $? - person ThorSummoner; 18.08.2015
comment
@ThorSummoner: не хочешь объяснить, почему твой лучше? - person knocte; 21.05.2016
comment
@knocte Я не уверен, что есть аргумент в пользу того, чтобы быть объективно лучше. Хотя я уверен, что однострочник дословного поста выполнит вывод результата, который я бы не хотел оставлять висящим в ответе. Один лайнер, который я показываю, иллюстрирует получение (печать) только кода выхода. - person ThorSummoner; 23.05.2016
comment
@ThorSummoner Вам не нужно grep -P для такого простого регулярного выражения. - person tripleee; 01.07.2016
comment
@knocte Все, что избегает grep -c, когда задача не состоит в том, чтобы фактически подсчитывать количество вхождений, объективно лучше. - person tripleee; 01.07.2016
comment
Проще: if ! dpkg-query -W -f='${Status}' nano | grep "ok installed"; then apt install nano; fi -- Не нужно использовать grep -c, просто используйте статус выхода grep - person Stephen Ostermiller; 05.10.2017
comment
@StephenOstermiller Если бы ваша версия была ответом, я бы проголосовал за нее. - person Wowfunhappy; 28.04.2018

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
comment
Чиро, ты не можешь полагаться на код выхода dpkg -s. Например, если вы apt установили пакет, затем apt удалили его и попытались выполнить команду dpkg -s packagename, то вы увидите статус: деинсталлировать и выйти с нулевым кодом (как если бы он был установлен). Вы должны разобрать вывод dpkg -s, братан. - person Dmitry Shevkoplyas; 28.01.2020
comment
@DmitryShevkoples спасибо за отчет. Я не мог воспроизвести на Ubuntu 19.10 с: sudo apt install hello; dpkg -s hello; echo $?; sudo apt remove hello; dpkg -s hello; echo $?. Можете ли вы предоставить более подробную информацию? - person Ciro Santilli 新疆再教育营六四事件ۍ 29.01.2020
comment
действительно - для вашего тестового примера с приветственным пакетом dpkg -s правильно показывает пакет как не установленный и дает ожидаемый код выхода 1. Но попробуйте ту же проверку установки / удаления с пакетом certbot, тогда вы увидите Статус: деинсталлировать ok config-files так как вывод dpkg -s после того, как ваш apt remove certbot и код выхода неправильно показывает нам 0. Мое неправильное предположение заключалось в том, что это точный случай для любого другого пакета, но, похоже, это не то же самое для всех, что еще хуже и меньше предсказуемый. Разобрать dpkg -s надо (с) Yoda :) - person Dmitry Shevkoplyas; 29.01.2020
comment
Информация о том, что dpkg remove package-name не приводит к тому, что dpkg -s package-name возвращает 0, отсутствует в большинстве ответов, что чуть не свело меня с ума. На самом деле это приводит к состоянию удалено, а не просто не установлено! Фух, Debian... своеобразен. - person TNT; 24.01.2021

Я предлагаю это обновление, поскольку Ubuntu добавила свой «Персональный архив пакетов» (PPA) сразу после того, как на этот вопрос был дан ответ, а пакеты PPA имеют другой результат.

  1. Пакет собственного репозитория Debian не установлен:

    ~$ dpkg-query -l apache-perl
    ~$ echo $?
    1
    
  2. Пакет PPA зарегистрирован на хосте и установлен:

    ~$ dpkg-query -l libreoffice
    ~$ echo $?
    0
    
  3. Пакет PPA зарегистрирован на хосте, но не установлен:

    ~$ dpkg-query -l domy-ce
    ~$ echo $?
    0
    ~$ sudo apt-get remove domy-ce
    [sudo] password for user: 
    Reading package lists... Done
    Building dependency tree       
    Reading state information... Done
    Package domy-ce is not installed, so not removed
    0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
    

Также размещено на: https://superuser.com/questions/427318/test-if-a-package-is-installed-in-apt/427898

person tahoar    schedule 23.05.2012
comment
Если вы устанавливаете и удаляете пакет, затем вы используете пакет dpkg-query; эхо $? также будет равно 0, если пакет не установлен. - person Pol Hallen; 23.09.2017

UpAndAdam написал:

Однако вы не можете просто полагаться на коды возврата здесь для сценариев

По моему опыту, вы можете полагаться на коды выхода dkpg.

Код возврата dpkg -s равен 0, если пакет установлен, и 1, если нет, поэтому самым простым решением, которое я нашел, было:

dpkg -s <pkg-name> 2>/dev/null >/dev/null || sudo apt-get -y install <pkg-name>

У меня работает нормально...

person rocka84    schedule 22.09.2014
comment
После apt-get remove <package> dpkg -s <package> по-прежнему возвращает 0, хотя пакет deinstalled - person ThorSummoner; 18.08.2015

Кажется, это работает очень хорошо.

$ sudo dpkg-query -l | grep <some_package_name> | wc -l
  • Он либо возвращает 0, если не установлен, либо некоторое число > 0, если установлен.
person sandman    schedule 20.08.2013
comment
grep | wc -l — это антипаттерн. Чтобы проверить, существует ли что-то, вам нужно просто grep -q. Для фактического подсчета вхождений (что редко бывает полезно в такого рода сценариях) используйте grep -c. - person tripleee; 01.07.2016
comment
@tripleee Итак, dpkg -s zip | grep -c "Package: zip"? (используя zip в качестве примера пакета) - person David Tabernero M.; 13.06.2018
comment
@Davdriver Это не совсем то, что написано выше, но да. В сценарии вы, вероятно, захотите, чтобы grep -q 'Package: zip' возвращал код выхода, указывающий, был ли найден результат без вывода чего-либо. - person tripleee; 14.06.2018
comment
это, кажется, отлично работает и для удаленных пакетов - person mehmet; 04.12.2018

Я остановился на одном, основываясь на ответе Nultyi:

MISSING=$(dpkg --get-selections $PACKAGES 2>&1 | grep -v 'install$' | awk '{ print $6 }')
# Optional check here to skip bothering with apt-get if $MISSING is empty
sudo apt-get install $MISSING

По сути, сообщение об ошибке от dpkg --get-selections гораздо легче разобрать, чем большинство других, потому что оно не включает такие статусы, как «удалить». Он также может проверять несколько пакетов одновременно, чего нельзя сделать только с кодами ошибок.

Объяснение/пример:

$ dpkg --get-selections  python3-venv python3-dev screen build-essential jq
dpkg: no packages found matching python3-venv
dpkg: no packages found matching python3-dev
screen                                          install
build-essential                                 install
dpkg: no packages found matching jq

Таким образом, grep удаляет установленные пакеты из списка, а awk извлекает имена пакетов из сообщения об ошибке, что приводит к MISSING='python3-venv python3-dev jq', который можно тривиально вставить в команду установки.

Я не выдаю apt-get install $PACKAGES вслепую, потому что, как упоминалось в комментариях, это может неожиданно обновить пакеты, которые вы не планировали; не очень хорошая идея для автоматизированных процессов, которые должны быть стабильными.

person Izkata    schedule 05.02.2018
comment
Мне нравится это решение. Краткость и тесты для нескольких пакетов одновременно. Кроме того, вы можете сделать необязательную проверку такой простой, как [[ ! -z $MISSING ]] && sudo apt-get install $MISSING - person Shenk; 20.01.2020

Я обнаружил, что все приведенные выше решения могут привести к ложному срабатыванию, если пакет установлен, а затем удален, но установочный пакет остается в системе.

Для репликации: установите пакет apt-get install curl
удалите пакет apt-get remove curl

Теперь проверьте приведенные выше ответы.

Следующая команда решает эту проблему:
dpkg-query -W -f='${Status}\n' curl | head -n1 | awk '{print $3;}' | grep -q '^installed$'

Это приведет к окончательному выводу установлено или не установлено.

person Mark    schedule 03.05.2016
comment
не совсем, к сожалению - другие возможные результаты в этом случае config-files - так что я думаю, что последний | grep -q "installed" действительно необходим, чтобы получить статус функционального кода выхода. - person keen; 23.09.2016
comment
сделай это | grep -q '^installed$' - person keen; 23.09.2016

Кажется, что в настоящее время у apt-get есть опция --no-upgrade, которая просто делает то, что хочет OP:

--no-upgrade Не обновляйте пакеты. При использовании в сочетании с установкой no-upgrade предотвратит обновление перечисленных пакетов, если они уже установлены.

Man-страница из https://linux.die.net/man/8/apt-get< /а>

Поэтому вы можете использовать

apt-get install --no-upgrade package

и package будет установлен, только если это не так.

person Giovanni Mascellani    schedule 06.05.2019

Это сделает это. apt-get install идемпотент.

sudo apt-get install --no-upgrade command
person David Baucum    schedule 05.04.2016
comment
Существуют сценарии, в которых выполнение apt-get install для пакета нежелательно, если пакет уже установлен, даже если сама команда является идемпотентной. В моем случае я устанавливаю пакет на удаленную систему с необработанным модулем Ansible, который будет сообщать о системе как об изменении каждый раз, если я запускаю apt-get install без разбора. Условие решает эту проблему. - person JBentley; 28.07.2016
comment
@JBentley Это хороший момент. Пакеты, установленные как часть зависимости, будут помечены как установленные вручную, а затем не будут удалены при удалении зависимости, если вы установите ее apt-get. - person David Baucum; 11.08.2016
comment
Я думаю, вам следует использовать apt-get install --no-upgrade package-name вместо этого, если вы хотите идемпотентное поведение, потому что простой install обновит пакет, если обновление доступно. - person Mikko Rantalainen; 17.07.2021
comment
Хороший звонок @MikkoRantalainen - person David Baucum; 18.07.2021

вдохновлено Крисом выше

#! /bin/bash

installed() {
    return $(dpkg-query -W -f '${Status}\n' "${1}" 2>&1|awk '/ok installed/{print 0;exit}{print 1}')
}

pkgs=(libgl1-mesa-dev xorg-dev vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools)
missing_pkgs=""

for pkg in ${pkgs[@]}; do
    if ! $(installed $pkg) ; then
        missing_pkgs+=" $pkg"
    fi
done

if [ ! -z "$missing_pkgs" ]; then
    cmd="sudo apt install -y $missing_pkgs"
    echo $cmd
fi
person FreeToGo    schedule 19.02.2021

Использовать:

apt-cache policy <package_name>

Если он не установлен, он покажет:

Installed: none

В противном случае он покажет:

Installed: version
person Mohammed Noureldin    schedule 14.07.2017

Эта функция уже существует в Ubuntu и Debian в пакете command-not-found.

person camh    schedule 19.08.2009
comment
matt@matt-ubuntu:~$ команда не найдена команда не найдена: команда не найдена ... лол. - person Matt Fletcher; 29.05.2013
comment
command-not-found — это интерактивный помощник, а не инструмент, гарантирующий, что у вас есть нужные зависимости. Конечно, правильный способ объявить зависимости — это упаковать ваше программное обеспечение в пакет Debian и правильно заполнить объявление Depends: в файле debian/control пакета. - person tripleee; 01.07.2016

apt list [packagename]

кажется, это самый простой способ сделать это вне dpkg и более старых инструментов apt-*

person Erich    schedule 17.07.2017
comment
Он удобен для ручной проверки, но выдает предупреждение о том, что apt не предназначен для сценариев — в отличие от инструментов apt-*. - person Hontvári Levente; 20.09.2017

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

# If there are .deb files in the folder, then install them
if [ `ls -1 *.deb 2> /dev/null | wc -l` -gt 0 ]; then
  for file in *.deb; do
    # Only install if not already installed (non-zero exit code)
    dpkg -I ${file} | grep Package: | sed -r 's/ Package:\s+(.*)/\1/g' | xargs dpkg -s
    if [ $? != 0 ]; then
        dpkg -i ${file}
    fi;
  done;
else
  err "No .deb files found in '$PWD'"
fi

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

person Craig    schedule 21.08.2018

Для Ubuntu apt предоставляет довольно приличный способ сделать это. Ниже приведен пример для Google Chrome:

apt -qq list google-chrome-stable 2>/dev/null | grep -qE "(installed|upgradeable)" || apt-get install google-chrome-stable

Я перенаправляю вывод ошибок на null, потому что apt предостерегает от использования своего «нестабильного кли». Я подозреваю, что пакет list стабилен, поэтому я думаю, что можно отбросить это предупреждение. -qq делает apt очень тихим.

person carlin.scott    schedule 06.12.2017
comment
это не будет работать должным образом, если что-то можно обновить - person Pawel Barcik; 28.11.2018
comment
@PawelBarcik хорошее замечание. Я обновил ответ, чтобы справиться с этой ситуацией. - person carlin.scott; 30.11.2018
comment
Вы можете использовать apt -qq list google-chrome-stable --installed таким образом, вы получите вывод только в том случае, если пакет установлен, и вам не нужно будет собирать вывод. - person Bartłomiej Uliasz; 12.08.2020

Эта команда самая запоминающаяся:

dpkg --get-selections <package-name>

Если он установлен, он печатает:

‹имя-пакета> установить

В противном случае он печатает

Пакеты, соответствующие ‹package-name>, не найдены.

Это было протестировано на Ubuntu 12.04.1 (Precise Pangolin).

person iNulty    schedule 25.09.2013
comment
dpkg --get-selections <package-name> не устанавливает ненулевой код выхода, если пакет не найден. - person Lucas; 05.03.2014

Многое было сказано, но для меня самый простой способ:

dpkg -l | grep packagename
person freedev    schedule 31.07.2018
comment
Ненадежный. Вместо этого передайте имя пакета в качестве аргумента. Например, dpkg -l packagename. Ваша версия будет возвращать строки, в которых имя пакета присутствует в описании или является частью имени другого пакета. Итак, для общего шаблона, где есть package и package-base, он вернет базовые пакеты, если вы проверите основные пакеты. - person Roger Dahl; 26.01.2021

В Баше:

PKG="emacs"
dpkg-query -l $PKG > /dev/null || sudo apt install $PKG

Обратите внимание, что у вас может быть строка с несколькими пакетами в PKG.

person daruma    schedule 07.11.2018

Я использую следующий способ:

which mySQL 2>&1|tee 1> /dev/null
  if [[ "$?" == 0 ]]; then
                echo -e "\e[42m MySQL already installed. Moving on...\e[0m"
        else
        sudo apt-get install -y mysql-server
                if [[ "$?" == 0 ]]; then
                        echo -e "\e[42mMy SQL installed\e[0m"
                else
                        echo -e "\e[42Installation failed\e[0m"
                fi
        fi
person Nitish Jadia    schedule 06.02.2019

Это явно печатает 0, если установлено, иначе 1, используя только awk:

dpkg-query -W -f '${Status}\n' 'PKG' 2>&1|awk '/ok installed/{print 0;exit}{print 1}'

или, если вы предпочитаете наоборот, где 1 означает установленный и 0 в противном случае:

dpkg-query -W -f '${Status}\n' 'PKG' 2>&1|awk '/ok installed/{print 1;exit}{print 0}'

** замените PKG на имя вашего пакета

Функция удобства:

installed() {
    return $(dpkg-query -W -f '${Status}\n' "${1}" 2>&1|awk '/ok installed/{print 0;exit}{print 1}')
}


# usage:
installed gcc && echo Yes || echo No

#or

if installed gcc; then
    echo yes
else
    echo no
fi
person Chris    schedule 02.12.2020
comment
потому что вы хотите добавить более одного пакета #! /bin/bash установлено() { return $(dpkg-query -W -f '${Статус}\n' ${1} 2›&1|awk '/ok установлено/{print 0;exit}{print 1} ') } pkgs=(xxx libgl1-mesa-dev yyy xorg-dev vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools)missing_pkgs= for pkg in ${упаковки[@]}; делать если! $(установлен $pkg) ; тогдаmissing_pkgs+= $pkg fi done echo $missing_pkgs if [ ! -z $missing_pkgs]; затем cmd=sudo apt install -y $missing_pkgs echo $cmd fi - person FreeToGo; 19.02.2021

Я использую это решение, так как считаю его наиболее простым.

function must_install(){ 
   return "$(apt -qq list $var --installed 2> /dev/null |wc -l)"
}

function install_if() { 
    unset install
    for var in "$@"
    do
        if $(must_install $var)
        then
            install+="${var} "
        fi
    done
    if [ -n "$install" ];
    then 
        sudo apt-get install -qy $install
    fi
}

Суть в том, что must_install возвращает 1 или 0, которые затем интерпретируются как истина или ложь из вызова if, поэтому нам не нужны никакие test с использованием [].

install_if принимает любое количество пакетов, разделенных пробелом.

Проблема в том, что apt не предназначен для использования в сценариях, поэтому он может перестать работать в любой момент. 8)

person JPT    schedule 12.03.2021

person    schedule
comment
Связано, вы должны использовать command -v <command>; не which <command>. Также см. раздел Проверить, существует ли программа из сценария Bash. - person jww; 21.10.2017

person    schedule
comment
Связано, вы должны использовать command -v <command>; не which <command>. Также см. раздел Проверить, существует ли программа из сценария Bash. - person jww; 21.10.2017