Bir apt-get paketinin kurulu olup olmadığını kontrol edin ve Linux'ta değilse yükleyin


223

Bir Ubuntu sistemi üzerinde çalışıyorum ve şu anda yaptığım şey bu:

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

Çoğu insanın yaptığı bu mu? Yoksa daha zarif bir çözüm var mı?


7
Komut adları her zaman ait oldukları paket adını yansıtmaz. Daha büyük hedefin nedir? Neden kurmaya çalışmıyorsunuz ve zaten yüklü olduğu için en kötü durumda olmayacak.
viam0Zah

8
Neyse ki, apt-get kurulumu idempotenttir, bu yüzden sadece çalıştırmak ve yüklü olup olmadığı konusunda endişelenmemek güvenlidir.
David Baucum

@ DavidBaucum'un yorumu en çok oyu alan bir cevap olmalıdır.
Nirmal

@Nirmal, cevap geldi.
David Baucum

1
İlgili, kullanmalısınız command -v <command>; değil which <command>. Ayrıca bkz. Bir programın Bash betiğinden olup olmadığını kontrol etme .
jww

Yanıtlar:


314

packagenameYüklü olup olmadığını kontrol etmek için şunu yazın:

dpkg -s <packagename>

Ayrıca kullanabilirsiniz dpkg-queryda vahşi kartları senin amaç için daha düzgün bir çıkışı vardır ve kabul eden.

dpkg-query -l <packagename>

Hangi paketin sahip olduğunu bulmak için şunu commanddeneyin:

dpkg -S `which <command>`

Daha fazla ayrıntı için Linux ve dpkg hile sayfasına paketin yüklü olup olmadığını öğrenme makalesine bakın .


32
Eğer bir kişi olarak bunu programsız bir şekilde istiyorsanız, bu bilgileri olduğu gibi kullanabilirsiniz. Bununla birlikte, komut dosyası oluşturma için buradaki dönüş kodlarına veya komut dosyası oluşturma için yalnızca çıktı / çıktı eksikliğine güvenemezsiniz. Bu komutların çıktılarını taramanız ve bu soru için yararlılıklarını sınırlamanız gerekir.
UpAndAdam

4
Garip bir şekilde, son zamanlarda dpkg-query'in eksik bir pakette 1 döndürdüğünü keşfettim, şimdi (Ubuntu 12.04) 0 döndürüyor, bu da jenkinlerim düğüm kurulum komut dosyamdaki her türlü soruna neden oluyor! dpkg -s kurulu pakette 0, kurulu değil 1 döndürür.
Therealstubot

18
Hey, OP ifkullanım istedi . Ayrıca ifkullanım arıyorum .
Tomáš Zato - Monica'yı

1
@Therealstubot: Ayrıca Ubuntu 12.04 kullanıyorum ve dpkg -seksik paketler üzerinde 1, aksi takdirde olması gerektiği gibi 0 döndürüyor . Önceki (veya son) sürümlerde ne fark vardı?
MestreLion

4
not: dpkg -sbir paket yüklendikten ve kaldırıldıktan sonra sıfır döndürür - bu durumda Status: deinstall ok config-filesya da benzer, bu yüzden "tamam" - bu yüzden bana göre, bu güvenli bir test değil. dpkg-query -lbu durumda da yararlı bir sonuç vermiyor gibi görünüyor.
hevesli

86

Biraz daha açık olmak gerekirse, bir paketi kontrol eden ve gerekirse yükleyen bir bash betiği. Tabii ki, paketin eksik olduğunu fark ettikten sonra, bir hata koduyla çıkmak gibi başka şeyler de yapabilirsiniz.

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

Komut dosyası bir GUI içinde çalışıyorsa (örneğin, bir Nautilus komut dosyasıysa), muhtemelen 'sudo' çağrısını 'gksudo' ile değiştirmek isteyeceksiniz.


5
--force-yeskötü bir fikir gibi görünüyor. Man sayfasından: "Bu, potansiyel olarak zararlı bir şey yapıp yapmadığını sormadan apt-get'in devam etmesine neden olacak tehlikeli bir seçenektir. Çok özel durumlar dışında kullanılmamalıdır. --Force-yes, sisteminizi potansiyel olarak yok edebilir !" Bir komut dosyasında kullanmak daha da kötü hale getirir.
etkinlik

68

Bu tek astar, 'nano' paketi için 1 (yüklü) veya 0 (yüklü değil) döndürür.

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

paket mevcut olmasa bile / mevcut değilse bile.

Aşağıdaki örnek, kurulu değilse 'nano' paketini yükler.

if [ $(dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed") -eq 0 ];
then
  apt-get install nano;
fi

4
Bu benim varyasyon:dpkg-query -W -f='${Status}' MYPACKAGE | grep -q -P '^install ok installed$'; echo $?
ThorSummoner

@ThorSummoner: sizinki neden daha iyi?
knocte

1
@knocte Objektif olarak daha iyi olma hakkında bir tartışma yapılacağından emin değilim. Verbatim gönderisinin bir astarının sonuç çıktısını yürüteceğinden emin olmama rağmen, bir cevapta sarkmak istemiyorum. Gösterdiğim bir astar, sadece çıkış kodunu almayı (yazdırmayı) örnekler.
ThorSummoner

1
@ThorSummoner Böyle grep -Pbasit bir normal ifadeye ihtiyacınız yok .
tripleee

7
Daha basit: if ! dpkg-query -W -f='${Status}' nano | grep "ok installed"; then apt install nano; fi- Kullanmanıza gerek yok grep -c, sadece çıkış durumunu kullanıngrep
Stephen Ostermiller

17

dpkg -s otomatik kurulum ile programlı kullanım

Paketlerin herhangi biri yüklü değilse dpkg -sdurumla çıkmayı seviyorum , bu 1da otomatikleştirmeyi kolaylaştırıyor:

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

man dpkg çıkış durumunu maalesef belgelemiyor, ancak bence buna güvenmek oldukça güvenli olmalı:

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

Unutulmaması gereken bir şey, koşmanın:

sudo apt remove <package-name>

bazı paketler için tüm dosyaları derhal kaldırmaz (ancak diğerleri için neden emin değilim?) ve yalnızca kaldırılmak üzere paketi işaretler.

Bu durumda, paket hala kullanılabilir gibi görünür ve dosyaları hala mevcut olduğundan, daha sonra kaldırılmak üzere işaretlenir.

Örneğin;

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

sonra:

  • ilk iki echo $?çıkış 0, sadece üçüncü çıkış1

  • ilk çıktı dpkg -s certbot:

    Status: deinstall ok installed

    ikincisi derken:

    Status: deinstall ok config-files

    ve sadece tasfiyeden sonra kaybolur:

    dpkg-query: package 'certbot' is not installed and no information is available
  • dosya /etc/logrotate.d/certbothala sistemde sonra var apt removeama sonra yok --purge.

    Ancak, dosya /usr/lib/python3/dist-packages/certbot/reporter.pydaha sonra bile kullanılabilir --purge.

Nedenini anlamıyorum, ama sonra hellopaketi ile o paket zaten kaldırılmış olduğunu gösterir :dpkgapt remove--purge

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

Belgeler de çok net değil, örneğin:

sudo apt dselect-upgrade

certbotolarak belirtilse de deinstall, olarak işaretlendiğinde kaldırılmadı man apt-get:

dselect-upgradegeleneksel Debian ambalaj ön ucu, dselect (1) ile birlikte kullanılır. dselect-upgrade, dselect (1) tarafından mevcut paketlerin Durum alanında yapılan değişiklikleri izler ve bu durumu gerçekleştirmek için gerekli eylemleri gerçekleştirir (örneğin, eski paketin kaldırılması ve yeni paketlerin yüklenmesi).

Ayrıca bakınız:

Ubuntu 19.10'da test edildi.

Python aptpaketi

aptUbuntu 18.04'te Python apt arabirimini ortaya çıkaran önceden yüklenmiş bir Python 3 paketi var !

Bir paketin kurulup kurulmadığını kontrol eden ve eğer kurulmuyorsa yükleyen bir komut dosyası şu adreste görülebilir: Python-apt API'sini kullanarak bir paket nasıl kurulur

İşte referans için bir kopyası:

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

PATHBunun yerine yürütülebilir dosyanın olup olmadığını kontrol edin

Bakınız: Bir programın Bash betiğinden olup olmadığını nasıl kontrol edebilirim?


1
Ciro, "dpkg -s" çıkış koduna güvenemezsin. Örneğin, bir paketi "apt kurduysanız", sonra "apt remove" ve "dpkg -s packagegename" komutunu denediyseniz, durumun farkına varacaksınız: deinstall ve sıfır kodu (kurulu gibi). "Dpkg -s" çıktı kardeşini ayrıştırmak zorundasın.
Dmitry Shevkoplyas

@DmitryShevkoplyas rapor için teşekkürler. Birlikte Ubuntu 19.10 üzerinde yeniden edemedi: sudo apt install hello; dpkg -s hello; echo $?; sudo apt remove hello; dpkg -s hello; echo $?. Daha ayrıntılı bilgi verebilir misiniz?
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

1
gerçekten - "merhaba" paket "dpkg -s" ile test durumda paketi doğru olarak yüklü değil gösterir ve beklenen çıkış kodu "1" verir. Ancak "certbot" paketiyle aynı yükleme / kaldırma denetimini deneyin, ardından "apt certbot'u kaldır" ve çıkış kodu yanlış bir şekilde gösterildikten sonra "Durum: ok config-files" i "dpkg -s" çıktısı olarak görürsünüz. "0". Yanlış varsayım, diğer herhangi bir paket için kesin bir durum olduğu, ancak herkes için aynı olmadığı, daha kötü ve daha az öngörülebilir olduğu anlaşıldı. Ayrıştırmak "dpkg -s" gerekir (c) Yoda :)
Dmitry Shevkoplyas

11

Ubuntu, "Kişisel Paket Arşivi" ni (PPA) bu soruya yanıt olarak eklediğinden ve PPA paketlerinin farklı bir sonucu olduğu için bu güncellemeyi öneriyorum.

  1. Yerel Debian depo paketi kurulu değil:

    ~$ dpkg-query -l apache-perl
    ~$ echo $?
    1
  2. Ana bilgisayara kayıtlı ve yüklü PPA paketi:

    ~$ dpkg-query -l libreoffice
    ~$ echo $?
    0
  3. Ana bilgisayara kayıtlı ancak yüklü olmayan PPA paketi:

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

Ayrıca yayınlandığı tarih: /superuser/427318/test-if-a-package-is-installed-in-apt/427898


2
Bir paket yükleyip kaldırırsanız, daha sonra dpkg-query paketini kullanırsınız; echo $? paket kurulu değilse de 0 olur.
Pol Hallen

8

UpAndAdam şunu yazdı:

Ancak, komut dosyası oluşturmak için burada dönüş kodlarına güvenemezsiniz

In my deneyim sen yapabilirsiniz dpkg en çıkış kodları güvenir.

Dönüş kodu dpkg -s olduğu 0 paketinin kurulması ve eğer 1 eğer o değil ben buldum basit çözüm oldu:

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

Benim için iyi çalışıyor ...


11
Sonra apt-get remove <package>, dpkg -s <package>paket yine de 0 döndürürdeinstalled
ThorSummoner

7

Bu gayet iyi çalışıyor gibi görünüyor.

$ sudo dpkg-query -l | grep <some_package_name> | wc -l
  • 0Yüklü değilse döndürür veya yüklüyse bir numara döndürür > 0.

8
grep | wc -lbir antipatterndir. Bir şeyin olup olmadığını kontrol etmek için basitçe istersiniz grep -q. (Bu tür bir senaryoda nadiren yararlı olan) gerçekleri saymak için kullanın grep -c.
tripleee

@tripleee Yani dpkg -s zip | grep -c "Package: zip"? (
zip'i

@Davdriver Yukarıdakilerin yaptığı tam olarak bu değil, evet. Bir komut dosyasında, muhtemelen grep -q 'Package: zip'hiçbir şey yazdırmadan sonucun bulunup bulunmadığını gösteren bir çıkış kodu döndürmek istersiniz .
tripleee

Bu da kaldırılan paketler için iyi çalışıyor gibi görünüyor
mehmet

4

Nultyi'nin cevabına dayanarak bir anlaşmaya vardım :

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

Temel olarak, gelen hata mesajı dpkg --get-selections "deinstall" gibi durumlar içermediğinden ayrıştırılması diğerlerinin çoğundan çok daha kolaydır. Aynı zamanda birden fazla paketi aynı anda kontrol edebilir, sadece hata kodlarıyla yapamayacağınız bir şey.

Açıklama / Örnek:

$ 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

Böylece grep, kurulu paketleri listeden kaldırır ve awk, paket adlarını hata mesajından çıkarır ve sonuçta MISSING='python3-venv python3-dev jq'bir install komutuna önemsiz bir şekilde eklenebilir.

apt-get install $PACKAGESYorumlarda belirtildiği gibi, körü körüne yayınlamıyorum , bu beklenmedik bir şekilde planlanmadığınız paketleri yükseltebilir; kararlı olması beklenen otomatik süreçler için iyi bir fikir değildir.


Bu çözümü seviyorum. Aynı anda birden fazla paket için özlü ve testler yapın. Ayrıca, isteğe bağlı kontrolü basit bir şey yapabilirsiniz[[ ! -z $MISSING ]] && sudo apt-get install $MISSING
Shenk

3

Yukarıdaki tüm çözümlerin bir paket yüklendikten ve kaldırıldıktan sonra yanlış bir pozitif üretebileceğini ancak kurulum paketinin sistemde kaldığını gördüm.

Çoğaltmak için: Paketi yükle Paketi apt-get install curl
kaldırapt-get remove curl

Şimdi yukarıdaki cevapları test edin.

Aşağıdaki komut bu durumu çözüyor gibi görünüyor:
dpkg-query -W -f='${Status}\n' curl | head -n1 | awk '{print $3;}' | grep -q '^installed$'

Bu, kesin bir kurulu veya kurulmamış


tamamen, ne yazık ki - bu durumda diğer olası sonuçlar vardır config-files- bu yüzden | grep -q "installed"gerçekten bir fonksiyonel çıkış kodu durumu almak için bir final gerekli olduğunu düşünüyorum .
düşkün

Bunu yapmak| grep -q '^installed$'
istekli

3

Bugünlerde OP'nin istediklerini yapan apt-getbir seçenek --no-upgradevar gibi görünüyor :

--no-upgradePaketleri yükseltmeyin. Yükleme ile birlikte kullanıldığında, yükseltme yapılmazsa, listelenen paketlerin zaten yüklenmişse yükseltilmeleri engellenir.

Https://linux.die.net/man/8/apt-get adresinden manpage

Bu nedenle kullanabilirsiniz

apt-get install --no-upgrade package

ve packageyalnızca yüklenmemişse yüklenecektir.



2

Bunu yapacak. apt-get installidempotenttir.

sudo apt-get install command

5
apt-get installKomutun kendisi idempotent olsa bile, bir paket üzerinde bir paket oluşturmanın istenmeyen bir durum olduğu senaryolar vardır . Benim durumumda, Ansible'ın ham modülüne sahip uzak bir sisteme bir paket kuruyorum, bu da her seferinde apt-get installrastgele çalışırsam sistemi değiştirmiş olarak rapor edecek . Koşullu bu sorunu çözer.
JBentley

1
@JBentley Bu iyi bir nokta. Bir bağımlılığın parçası olarak yüklenen paketler manuel olarak yüklendi olarak işaretlenir ve sonra apt-get kurulumunu yaparsanız bağımlılığı kaldırıldığında kaldırılmaz.
David Baucum

2

kullanın:

apt-cache policy <package_name>

Yüklü değilse şunları gösterecektir:

Installed: none

Aksi takdirde şunu gösterir:

Installed: version

1

Bu özellik command-not-foundpakette Ubuntu ve Debian'da zaten var .


15
matt @ matt-ubuntu: ~ $ komut bulunamadı bulunamadı komut bulunamadı: komut bulunamadı ... lol.
Matt Fletcher

1
command-not-foundetkileşimli bir yardımcıdır, istediğiniz bağımlılıklara sahip olmanızı sağlayacak bir araç değildir. Tabii ki, bağımlılıkları bildirmenin uygun yolu, yazılımınızı bir Debian paketinde paketlemek ve Depends:paketin debian/controldosyasındaki bildirimi düzgün bir şekilde doldurmaktır .
tripleee

1
apt list [packagename]

dpkg ve daha eski apt- * araçları dışında yapmanın en basit yolu gibi görünüyor


Manuel kontrol için güzel, ancak apt- * araçlarının aksine apt'in komut dosyası oluşturma için tasarlanmadığını bildiren bir uyarı verir.
Hontvári Levente


1

Docker yerine yerel olarak test çalıştırırken benzer bir gereksinimim vardı. Temel olarak, yalnızca önceden yüklenmemişlerse bulunan herhangi bir .deb dosyasını yüklemek istedim.

# 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

Sanırım görebildiğim tek sorun, paketin sürüm numarasını kontrol etmemesi .deb dosyası daha yeni bir sürümse, bu şu anda yüklü paketin üzerine yazmaz.


1

Ubuntu için, apt bunu yapmak için oldukça iyi bir yol sağlar. Aşağıda google chrome için bir örnek verilmiştir:

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

Hata çıktısını null'a yönlendiriyorum çünkü apt "kararsız cli" sini kullanmaya karşı uyarıyor. Liste paketinin kararlı olduğundan şüpheleniyorum, bu yüzden bu uyarıyı atmanın iyi olduğunu düşünüyorum. -Qq apt süper sessiz yapar.


1
bir şey "yükseltilebilir" ise bu düzgün çalışmaz
Pawel Barcik

@PawelBarcik iyi bir nokta. Bu durumu ele almak için cevabı güncelledim.
carlin.scott

0

Bu komut en unutulmazı:

dpkg --get-selections <package-name>

Yüklü ise yazdırır:

<paket-adı> install

Aksi takdirde yazdırır

<package-name> ile eşleşen paket bulunamadı.

Bu, Ubuntu 12.04.1 (Hassas Pangolin) üzerinde test edildi.


4
dpkg --get-selections <package-name>paket bulunmadığında çıkış kodunu sıfırdan farklı olarak ayarlamaz.
Lucas

0

Birçok şey söylendi ama benim için en basit yol:

dpkg -l | grep packagename

0

Bash'ta:

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

PKG'de birkaç paket içeren bir dizeye sahip olabileceğinizi unutmayın.


0

Ben şu yolu kullanıyorum:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.