apt-getパッケージがインストールされているかどうかを確認し、Linuxにない場合はインストールします


223

私は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

これはほとんどの人がすることですか?または、よりエレガントなソリューションはありますか?


7
コマンド名は、それらが属するパッケージ名を常に反映するわけではありません。あなたはより大きな目標は何ですか?既にインストールされているので、インストールしようとしないでください。最悪の場合はインストールしないでください。
viam0Zah 2009

8
幸い、apt-get installはべき等なので、実行するだけで安全で、インストールされているかどうかを心配する必要はありません。
David Baucum 2016年

@DavidBaucumのコメントは、最も多くの票を獲得する答えになるはずです。
通常の

@通常、答えが出ました。
David Baucum 16

1
関連して、あなたは使用する必要がありますcommand -v <command>。ないwhich <command>。「Bashスクリプトからプログラムが存在するかどうか確認する」も参照してください
2017年

回答:


314

packagenameがインストールされているかどうかを確認するには、次のように入力します。

dpkg -s <packagename>

またdpkg-query、目的に合わせて出力を整理し、ワイルドカードを使用することもできます。

dpkg-query -l <packagename>

を所有するパッケージを見つけるにはcommand、次のことを試してください。

dpkg -S `which <command>`

詳細については、「Linuxおよびdpkgチートシートにパッケージがインストールされているかどうかを確認する」の記事参照してください。


32
あなたが個人としてこれをプログラムで必要としない場合は、この情報をそのまま使用できます。ただし、ここでは、スクリプトのリターンコードや、スクリプトの出力/出力の欠如だけに依存することはできません。これらのコマンドの出力をスキャンする必要があるため、この質問に対するそれらの有用性は制限されます。
UpAndAdam 2013

4
奇妙なことに、私は最近、dpkg-queryが不足しているパッケージで1を返していましたが、現在(Ubuntu 12.04)が0を返し、jenkinsビルドノードセットアップスクリプトであらゆる種類の問題を引き起こしていることを発見しました。dpkg -sは、パッケージがインストールされている場合は0を返し、インストールされていないパッケージでは1を返します。
Therealstubot 2013

18
ねえ、OPはif使用法を尋ねました。if使い方も探しています。
トマーシュZato -復活モニカ

1
@Therealstubot:私もUbuntu 12.04を使用しておりdpkg -s、欠落しているパッケージでは1を返し、そうでなければ0を返します。以前の(または最近の)バージョンではどのように違いましたか?
MestreLion 2015

4
注: dpkg -sパッケージがインストールされてから削除された場合はゼロを返します-その場合、それは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内で実行される場合(例:Nautilusスクリプト)、「sudo」の呼び出しを「gksudo」の呼び出しに置き換えることをお勧めします。


5
--force-yes悪い考えのようです。manページから:「これは危険なオプションで、apt-getが有害な可能性のあることをしている場合はプロンプトを表示せずに続行します。非常に特殊な状況以外では使用しないでください。--force-yesを使用するとシステムが破壊される可能性があります!」スクリプトで使用すると、さらに悪化します。
活動の削減

68

このワンライナーは、「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 2016年

1
@knocte客観的に良くなることについての議論があるかどうかはわかりません。逐語的投稿の1行で結果の出力が実行されると確信していますが、結果をぶら下げたまま答えたくはありません。私が示す1つのライナーは、終了コードだけを取得(印刷)する例です。
ThorSummoner 2016年

1
@ThorSummoner grep -Pそのような単純な正規表現は必要ありません。
Tripleee 2016

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.

注意すべきことの1つは、実行しているということです。

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

次に:

  • 最初の2つのecho $?出力0、3つ目の出力のみ1

  • 最初の出力には以下dpkg -s certbotが含まれます。

    Status: deinstall ok installed

    2番目は言う:

    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パッケージ秒dpkgapt 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従来のDebianパッケージフロントエンド、dselect(1)と組み合わせて使用​​されます。dselect-upgradeは、dselect(1)によって利用可能なパッケージのStatusフィールドに加えられた変更に従い、その状態を実現するために必要なアクション(古いパッケージの削除や新しいパッケージのインストールなど)を実行します。

以下も参照してください。

Ubuntu 19.10でテスト済み。

Python aptパッケージ

と呼ばれるプリインストールされたPython 3パッケージがあります aptUbuntu 18.04には、Python aptインターフェースを公開するます。

パッケージがインストールされているかどうかをチェックし、インストールされていない場合にインストールするスクリプトは、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"終了コードに依存できません。たとえば、パッケージを「apt installed」し、次に「apt remove」して「dpkg -s packagename」を実行しようとすると、ステータスがわかります。アンインストールしてコード0を終了します(インストールされている場合と同様)。"dpkg -s"出力ブロを解析する必要があります。
Dmitry Shevkoplyas

@DmitryShevkoplyasレポートをありがとう。Ubuntu 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」パッケージで同じインストール/削除チェックを実行すると、「apt remove certbot」の後に「dpkg -s」出力として「Status:deinstall ok config-files」が表示され、終了コードが間違って表示されます「0」。私の間違った仮定は、それが他のパッケージの正確なケースであるということでしたが、それはすべてに同じではないようです。「dpkg -s」を解析する必要があります(c)ヨーダ:)
Dmitry Shevkoplyas

11

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


2
パッケージをインストールして削除する場合は、次にdpkg-query packageを使用します。エコー$?パッケージがインストールされていない場合も0になります。
Pol Hallen 2017

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 '18

7

これはかなりうまくいくようです。

$ sudo dpkg-query -l | grep <some_package_name> | wc -l
  • 0インストールされていない場合は戻るか、インストールされている場合はいくつかの数値が返さ> 0れます。

8
grep | wc -lアンチパターンです。何かが存在するかどうかを確認するには、単純に必要ですgrep -q。オカレンスを実際にカウントするには(この種のシナリオではめったに役立ちません)、を使用しますgrep -c
Tripleee 2016

@tripleeeそれで、dpkg -s zip | grep -c "Package: zip"?(サンプルパッケージとしてzipを使用)
David Tabernero M.

@Davdriver上記のことは正確ではありませんが、そうです。スクリプトでは、おそらくgrep -q 'Package: zip'何も出力せずに結果が見つかったかどうかを示す終了コードを返します。
tripleee

これはアンインストールされたパッケージでもうまく機能しているようです
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は、「削除」などのステータスが含まれていないため、他のほとんどのも解析がはるかに簡単です。複数のパッケージを同時にチェックすることもできますが、これはエラーコードだけでは実行できません。

説明/例:

$ 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-upgrade、OPが望むことだけを行うオプションがあるようです:

--no-upgradeパッケージをアップグレードしないでください。インストールと組み合わせて使用​​した場合、no-upgradeは、リストされているパッケージがすでにインストールされている場合、それらがアップグレードされないようにします。

https://linux.die.net/man/8/apt-getのマンページ

したがって、使用できます

apt-get install --no-upgrade package

そしてpackage、それはない場合にのみインストールされます。



2

これでできます。apt-get installべき等です。

sudo apt-get install command

5
apt-get installコマンド自体がべき等であっても、パッケージがすでにインストールされている場所でパッケージに対してを実行することが望ましくないシナリオがあります。私の場合、Ansibleのrawモジュールを使用してリモートシステムにパッケージをインストールしていますapt-get install。無差別に実行すると、毎回システムが変更されたと報告されます。条件付きはその問題を解決します。
JBentley

1
@JBentleyそれは良い点です。依存関係の一部としてインストールされたパッケージは、手動でインストールされたものとしてマークされ、依存関係が削除されてもapt-get installで削除されません。
David Baucum

2

使用する:

apt-cache policy <package_name>

インストールされていない場合は、次のように表示されます。

Installed: none

それ以外の場合は表示されます:

Installed: version

1

この機能はUbuntuとDebianのcommand-not-foundパッケージにすでに存在します。


15
matt @ matt-ubuntu:〜$ command-not-found command-not-found:command not found ... lol。
マットフレッチャー2013年

1
command-not-foundインタラクティブなヘルパーであり、必要な依存関係を確保するためのツールではありません。もちろん、依存関係を宣言する適切な方法は、ソフトウェアをDebianパッケージにパッケージ化Depends:し、パッケージのdebian/controlファイルに宣言を適切に入力することです。
Tripleee 2016

1
apt list [packagename]

dpkgや古いapt- *ツールの外でそれを行う最も簡単な方法のようです


手動でのチェックには適していますが、apt- *ツールとは異なり、aptはスクリプト用ではないことを警告します。
Hontváriレベンテ


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

Ubuntuの場合、aptはこれを行うためのかなり適切な方法を提供します。以下は、Google Chromeの例です。

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 2018年

@PawelBarcik良い点。私はその状況に対処するために答えを更新しました。
carlin.scott

0

このコマンドは最も記憶に残るものです。

dpkg --get-selections <package-name>

インストールされている場合は、次のように出力されます。

<パッケージ名>インストール

それ以外の場合は印刷されます

<package-name>に一致するパッケージは見つかりませんでした。

これはUbuntu 12.04.1(Precise Pangolin)でテストされました。


4
dpkg --get-selections <package-name>パッケージが見つからない場合、終了コードをゼロ以外に設定しません。
ルーカス

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.