apt-get 패키지가 설치되어 있는지 확인한 다음 Linux에 없으면 설치하십시오.


223

나는 우분투 시스템에서 일하고 있으며 현재 이것은 내가하고있는 일입니다.

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

이것이 대부분의 사람들이하는 일입니까? 아니면 더 우아한 해결책이 있습니까?


7
명령 이름이 항상 자신이 속한 패키지 이름을 반영하지는 않습니다. 더 큰 목표는 무엇입니까? 단순히 설치하려고 시도하지 마십시오. 이미 설치되어 있기 때문에 최악의 경우는 아닙니다.
viam0Zah

8
다행스럽게도 apt-get install은 idempotent이므로 설치하는 것이 안전하고 설치 여부에 대해 걱정하지 않아도됩니다.
David Baucum

@DavidBaucum의 의견은 가장 많은 표를 얻는 답변이어야합니다.
Nirmal

@Nirmal, 답변했습니다.
David Baucum

1
관련, 당신은 사용해야합니다 command -v <command>; 아닙니다 which <command>. 또한 Bash 스크립트에서 프로그램이 있는지 확인하십시오 .
jww

답변:


314

packagename설치 되었는지 확인하려면 다음을 입력하십시오.

dpkg -s <packagename>

당신은 또한 dpkg-query당신의 목적에 맞는 더 깔끔한 출력을 사용 하고 와일드 카드도 허용합니다.

dpkg-query -l <packagename>

패키지를 소유 한 패키지를 찾으려면 다음 command을 시도하십시오.

dpkg -S `which <command>`

자세한 내용 은 Linuxdpkg 치트 시트 에 패키지가 설치되어 있는지 확인 기사를 참조하십시오 .


31
사람이 프로그래밍 방식으로 이것을 원하지 않으면이 정보를 그대로 사용할 수 있습니다. 그러나 스크립팅을 위해 리턴 코드를 사용하거나 스크립팅을위한 출력 / 출력 부족만으로는 사용할 수 없습니다. 이 명령의 출력을 스캔하여이 질문에 대한 유용성을 제한해야합니다.
UpAndAdam

4
이상하게도 최근에 dpkg-query가 누락 된 패키지에서 1을 반환하는 데 사용되었음을 알았습니다. 이제 (Ubuntu 12.04)는 0을 반환하여 jenkins 빌드 노드 설정 스크립트에 모든 종류의 문제가 발생합니다! dpkg -s는 설치된 패키지에서 0을 반환하고 패키지가 설치되지 않은 경우 1을 반환합니다.
Therealstubot

17
이봐, OP는 if사용법을 물었다 . 또한 if사용법을 찾고 있습니다.
Tomáš Zato-복원 모니카

1
@Therealstubot : 또한 Ubuntu 12.04를 사용하고 dpkg -s있으며 누락 된 패키지에서 1을 반환하고 그렇지 않으면 0을 반환합니다. 이전 (또는 최신) 버전과 다른 점은 무엇입니까?
MestreLion

4
참고 : dpkg -s패키지가 설치되고 제거 된 경우 0을 반환합니다.이 경우 패키지는 Status: deinstall ok config-files유사하거나 "확인"이므로 안전한 테스트는 아닙니다. dpkg-query -l이 경우에도 유용한 결과를 반환하지 않는 것 같습니다.
예리한

86

좀 더 명확하게하기 위해 패키지를 확인하고 필요한 경우 설치하는 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

스크립트가 GUI 내에서 실행되는 경우 (예 : 노틸러스 스크립트) 'sudo'호출을 'gksudo'호출로 바꾸고 싶을 것입니다.


5
--force-yes나쁜 생각 인 것 같습니다. 맨 페이지에서 : "이 옵션은 잠재적으로 유해한 일을하고 있는지 묻지 않고 apt-get을 계속 발생시키는 위험한 옵션입니다. 매우 특별한 상황이 아닌 한 사용해서는 안됩니다. --force-yes를 사용하면 시스템이 잠재적으로 손상 될 수 있습니다 ! " 스크립트에서 사용하면 훨씬 더 나빠집니다.
활동 감소

68

이 one-liner는 'nano'패키지에 대해 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

4
이에 대한 나의 변화 :dpkg-query -W -f='${Status}' MYPACKAGE | grep -q -P '^install ok installed$'; echo $?
ThorSummoner

@ThorSummoner : 왜 더 나은지 설명해 주시겠습니까?
knocte

1
@knocte 객관적으로 나아질 것에 대한 논쟁이 확실하지 않습니다. 나는 말 그대로 게시물의 한 줄짜리가 결과 출력을 실행할 것이라고 확신하지만 대답에 매달려 싶지 않습니다. 내가 보여준 하나의 라이너는 종료 코드를 얻는 것 (인쇄)을 보여줍니다.
ThorSummoner

1
@ThorSummoner 그런 grep -P정규식이 필요하지 않습니다 .
tripleee

7
더 간단합니다 : if ! dpkg-query -W -f='${Status}' nano | grep "ok installed"; then apt install nano; fi– 사용할 필요가 없습니다 . – grep -c종료 상태를 사용하십시오grep
Stephen Ostermiller

17

dpkg -s 자동 설치를 통한 프로그래밍 방식 사용법

내가 좋아하는 dpkg -s그 상태로 종료로 1패키지 중 하나가 설치되어 있지 않은 경우 쉽게 자동화 할 수 그것을 만드는 :

pkgs='qemu-user pandoc'
if ! dpkg -s $pkgs >/dev/null 2>&1; then
  sudo apt-get install $pkgs
fi

man dpkg 불행히도 종료 상태를 문서화하지는 않지만 그것에 의존하는 것이 합리적으로 안전해야한다고 생각합니다.

-s, --status package-name...
    Report status of specified package.

주목해야 할 것은 실행 중입니다.

sudo apt remove <package-name>

일부 패키지에 대해 반드시 모든 파일을 즉시 제거 할 필요는 없지만 (다른 이유는 확실하지 않습니까?) 패키지를 제거 대상으로 표시합니다.

이 상태에서는 패키지를 계속 사용할 수 있으며 파일이 여전히 존재하지만 나중에 제거하도록 표시되어 있습니다.

예를 들어 다음을 실행하는 경우 :

pkg=certbot

sudo apt install -y "$pkg"
dpkg -s "$pkg"
echo $?

sudo apt remove -y "$pkg"
dpkg -s "$pkg"
echo $?
ls -l /usr/lib/python3/dist-packages/certbot/reporter.py

sudo apt remove --purge certbot
dpkg -s "$pkg"
echo $?
ls -l /usr/lib/python3/dist-packages/certbot/reporter.py

그때:

  • 처음 두 echo $?출력 0, 세 번째 출력 만1

  • 첫 번째 출력 dpkg -s certbot에는 다음이 포함됩니다.

    Status: deinstall ok installed

    두 번째는 말합니다 :

    Status: deinstall ok config-files

    퍼지 후에 만 ​​사라집니다.

    dpkg-query: package 'certbot' is not installed and no information is available
  • 파일 /etc/logrotate.d/certbot은 이후에도 시스템에 존재 apt remove하지만 이후 에는 존재하지 않습니다.--purge .

    그러나 파일 /usr/lib/python3/dist-packages/certbot/reporter.py은 이후에도 계속 존재 --purge합니다.

이유를 이해하지 못하지만 hello두 번째 패키지 dpkg이후에 apt remove패키지가 이미 제거되지 않은 것으로 나타났습니다 --purge.

dpkg-query: package 'hello' is not installed and no information is available

다음과 같은 문서도 매우 명확하지 않습니다.

sudo apt dselect-upgrade

제거하지 않은 certbot것처럼이 표시 될 때 deinstall, 비록 man apt-get나타 내기 위해 같다 :

dselect-upgrade전통적인 데비안 패키징 프론트 엔드, dselect (1)와 함께 사용됩니다. dselect-upgrade는 dselect (1)가 사용 가능한 패키지의 Status 필드로 변경 한 내용을 따르고 해당 상태를 실현하는 데 필요한 작업 (예 : 이전 패키지 제거 및 새 패키지 설치)을 수행합니다.

또한보십시오:

우분투에서 테스트 19.10.

파이썬 apt 패키지

사전 설치된 Python 3 패키지가 있습니다. aptPython apt 인터페이스를 제공하는 Ubuntu 18.04 있습니다!

패키지가 설치되어 있는지 확인하고 찾을 수없는 경우 설치하는 스크립트 : python-apt API를 사용하여 패키지를 설치하는 방법

다음은 참조 용 사본입니다.

#!/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 스크립트에서 프로그램이 있는지 어떻게 확인합니까?를 참조하십시오.


Ciro, ou는 "dpkg -s"종료 코드에 의존 할 수 없습니다. 예를 들어 패키지를 "설치 한"후 "제거"하고 "dpkg -s packagename"을 시도하면 설치 제거 및 종료 코드 0 (설치된 것처럼)이 표시됩니다. "dpkg -s"출력 bro를 구문 분석해야합니다.
Dmitry Shevkoplyas

@DmitryShevkoplyas 보고서에 감사드립니다. 나는 우분투 19.10에서 다음과 같이 재현 할 수 없었습니다 sudo apt install hello; dpkg -s hello; echo $?; sudo apt remove hello; dpkg -s hello; echo $?. 더 자세한 정보를 제공 할 수 있습니까?
Ciro Santilli

1
실제로 "hello"패키지 "dpkg -s"가있는 테스트 케이스의 경우 패키지가 설치되지 않은 것으로 올바르게 표시되고 예상 종료 코드 "1"이 표시됩니다. 그러나 "certbot"패키지와 동일한 설치 / 제거 검사를 시도하면 "aptbot certbot"후 종료 상태가 잘못 표시되면 "상태 : ok config-files 설치 제거"가 "dpkg -s"출력으로 표시됩니다. "0". 내 잘못된 가정은 다른 패키지의 경우에는 정확한 경우이지만 모든 것이 동일하지는 않은 것으로 보입니다. "dpkg -s"구문 분석 (c) Yoda :)
Dmitry Shevkoplyas

11

이 질문에 대한 답변과 마찬가지로 Ubuntu에서 "PPA (Personal Package Archive)"를 추가하고 PPA 패키지의 결과가 다르기 때문에이 업데이트를 제공합니다.

  1. 네이티브 데비안 저장소 패키지가 설치되지 않았습니다 :

    ~$ 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.

/superuser/427318/test-if-a-package-is-installed-in-apt/427898에 게시 됨


2
패키지를 설치하고 제거하면 다음으로 dpkg-query package를 사용합니다. 에코 $? 패키지가 설치되지 않은 경우에도 0이됩니다.
Pol Hallen

8

UpAndAdam은 다음과 같이 썼다.

그러나 단순히 스크립팅을 위해 리턴 코드에 의존 할 수는 없습니다.

에서 경험을 당신은 할 수 dkpg의 종료 코드에 의존하고 있습니다.

패키지가 설치되어 있으면 dpkg -s 의 반환 코드 는 0 이고 그렇지 않으면 1입니다 . 가장 간단한 해결책은 다음과 같습니다.

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

나를 위해 잘 작동합니다 ...


11
apt-get remove <package>, dpkg -s <package>여전히 패키지 임에도 불구하고, 0을 반환deinstalled
ThorSummoner

7

이것은 꽤 잘 작동하는 것 같습니다.

$ sudo dpkg-query -l | grep <some_package_name> | wc -l
  • 0설치되지 않은 경우 반환 되거나 설치된 경우 일부 숫자 를 반환 합니다 > 0.

8
grep | wc -l반 패턴입니다. 무언가 존재하는지 확인하려면 간단히 원합니다 grep -q. 발생을 실제로 세려면 (이 시나리오에서는 거의 유용하지 않음)를 사용하십시오 grep -c.
tripleee

@tripleee 그래서 dpkg -s zip | grep -c "Package: zip"? (zip을 샘플 패키지로 사용)
David Tabernero M.

@Davdriver 위의 내용과 정확히 일치하는 것은 아니지만 그렇습니다. 스크립트 grep -q 'Package: zip'에서 아무 것도 인쇄하지 않고 결과를 찾았는지 여부를 나타내는 종료 코드를 반환 하려고 합니다.
tripleee 2018 년

이것은 제거 된 패키지에서도 잘 작동하는 것 같습니다
mehmet

4

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"deinstall"과 같은 상태를 포함하지 않기 때문에 오류 메시지 는 다른 대부분의 것보다 구문 분석하기가 훨씬 쉽습니다. 또한 오류 코드만으로는 수행 할 수없는 여러 패키지를 동시에 확인할 수 있습니다.

설명 / 예 :

$ 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주석에서 언급했듯이 계획하지 않은 패키지를 예기치 않게 업그레이드 할 수 있기 때문에 맹목적으로 발행 하지 않습니다. 안정적 일 것으로 예상되는 자동화 된 프로세스에는 좋은 아이디어가 아닙니다.


나는이 해결책을 좋아한다. 여러 패키지를 한 번에 간결하고 테스트합니다. 또한 옵션 점검을 간단하게 만들 수 있습니다[[ ! -z $MISSING ]] && sudo apt-get install $MISSING
Shenk

3

패키지가 설치 된 다음 제거되었지만 설치 패키지가 시스템에 남아 있으면 위의 모든 솔루션이 오 탐지를 생성 할 수 있음을 발견했습니다.

복제하려면 : 패키지 설치 패키지 apt-get install curl
제거apt-get remove curl

이제 위의 답변을 테스트하십시오.

다음 명령은이 조건을 해결하는 것 같습니다.
dpkg-query -W -f='${Status}\n' curl | head -n1 | awk '{print $3;}' | grep -q '^installed$'

이것은 최종 설치 또는 설치 되지 않은 결과를 초래합니다


슬프게도-이 경우 다른 가능한 결과는 아닙니다 .- 기능 종료 코드 상태를 얻으려면 실제로 config-files최종 결과 | grep -q "installed"가 필요 하다고 생각합니다 .
예리한

그 만들| grep -q '^installed$'
예리한

3

요즘 apt-get에는 --no-upgradeOP가 원하는 것을 수행 하는 옵션이있는 것 같습니다 .

--no-upgrade패키지를 업그레이드하지 마십시오. 설치와 함께 사용하면 업그레이드하지 않음으로 인해 나열된 패키지가 이미 설치된 경우 업그레이드되지 않습니다.

https://linux.die.net/man/8/apt-get 에서 맨 페이지

따라서 사용할 수 있습니다

apt-get install --no-upgrade package

package그렇지 않은 경우에만 설치됩니다.



2

그렇게 할 것입니다. apt-get installdem 등이다.

sudo apt-get install command

5
apt-get install명령 자체가 dem 등원이더라도 패키지가 이미 설치되어있는 경우에는 패키지에서 수행하는 것이 바람직하지 않은 시나리오가 있습니다 . 필자의 경우 Ansible의 원시 모듈이있는 원격 시스템에 패키지를 설치하고 있습니다.이 모듈은 apt-get install무차별 적으로 실행될 때마다 시스템이 변경된 것으로보고합니다 . 조건부로 해당 문제를 해결합니다.
JBentley

1
@JBentley 좋은 지적입니다. 종속성의 일부로 설치된 패키지는 수동으로 설치된 것으로 표시되며, apt-get install을 설치하면 종속성이 제거 될 때 제거되지 않습니다.
David Baucum

2

사용하다:

apt-cache policy <package_name>

설치되어 있지 않으면 다음과 같이 표시됩니다.

Installed: none

그렇지 않으면 다음과 같이 표시됩니다.

Installed: version

1

이 기능은 command-not-found패키지의 우분투와 데비안에 이미 존재 합니다.


15
matt @ matt-ubuntu : ~ $ 명령을 찾을 수 없음 명령을 찾을 수 없음 : command not found ... lol.
매트 플레처

1
command-not-found대화 형 도우미이며 원하는 종속성을 보장하는 도구가 아닙니다. 물론 의존성을 선언하는 올바른 방법은 소프트웨어를 데비안 패키지로 패키징하고 Depends:패키지 debian/control파일에 선언을 올바르게 채우는 것입니다.
tripleee

1
apt list [packagename]

dpkg 및 이전 apt- * 도구 외부에서 수행하는 가장 간단한 방법 인 것 같습니다.


수동 검사에는 좋지만 apt- * 도구와 달리 apt는 스크립팅 용이 아니라는 경고를 표시합니다.
Hontvári Levente


1

docker 대신 로컬에서 테스트를 실행할 때 비슷한 요구 사항이있었습니다. 기본적으로 나는 아직 설치되지 않은 .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 파일이 최신 버전이면 현재 설치된 패키지를 덮어 쓰지 않는다는 것입니다.


1

우분투의 경우 apt는이를 수행하는 상당히 괜찮은 방법을 제공합니다. 다음은 Google 크롬의 예입니다.

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

apt가 "불안정한 cli"를 사용하지 않도록 경고하기 때문에 오류 출력을 null로 리디렉션합니다. 나는 목록 패키지가 안정적이라고 생각 하므로이 경고를 버리는 것이 좋다고 생각합니다. -qq는 apt를 매우 조용하게 만듭니다.


1
무언가가 "업그레이드 가능"하면 제대로 작동하지 않습니다
Pawel Barcik

@PawelBarcik 좋은 지적. 그 상황을 처리하기 위해 답변을 업데이트했습니다.
carlin.scott

0

이 명령은 가장 기억에 남습니다.

dpkg --get-selections <package-name>

설치되어 있으면 다음과 같이 인쇄됩니다.

<패키지 이름> 설치

그렇지 않으면 인쇄

<package-name>과 (와) 일치하는 패키지가 없습니다.

이것은 Ubuntu 12.04.1 (Precise Pangolin)에서 테스트되었습니다.


4
dpkg --get-selections <package-name>패키지를 찾을 수 없을 때 종료 코드를 0이 아닌 값으로 설정하지 않습니다.
Lucas

0

많은 것들을 들었지만 가장 간단한 방법은 다음과 같습니다.

dpkg -l | grep packagename

0

배쉬에서 :

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

PKG에는 여러 패키지가 포함 된 문자열이있을 수 있습니다.


0

나는 다음과 같은 방법을 사용합니다 :

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.