How to check linux packages

How can I check if a package is installed and install it if not?

Command names does not always reflect the package name they are belong to. What is you’re larger goal? Why don’t you simply try to install it, and worst case it won’t, since it’s already installed.

Fortunately, apt-get install is idempotent, so it is safe to just run it and not worry about if it is installed or not.

@DavidBaucum Not quite; running install on an already-installed package will upgrade it if it’s out of date. Usually desirable to keep up-to-date for security issues, but could be surprising if stability is desired.

@DavidBaucum: manually apt install ing an already installed package will also mark it as manually installed, a very undesired side-effect if that package was previously set as automatically installed.

29 Answers 29

To check if packagename was installed, type:

You can also use dpkg-query that has a neater output for your purpose, and accepts wild cards, too.

To find what package owns the command , try:

If you as a person want this NON-programmatically you can use this information as it stands. However you can’t simply rely on return codes here for scripting or the output/lack of output alone for scripting. You would have to scan the output of these commands, limiting their usefulness for this question.

Oddly enough, I’ve recently discovered that dpkg-query used to return 1 on a missing package, now ( Ubuntu 12.04 ) returns 0, causing all sorts of trouble on my jenkins build node setup script! dpkg -s returns 0 on package installed, and 1 on package not installed.

@Therealstubot : I’m also using Ubuntu 12.04 and dpkg -s does return 1 on missing packages and 0 otherwise, as it should. How was different on earlier (or recent) versions?

a note: dpkg -s returns zero if a package was installed and then removed — in that case it’s Status: deinstall ok config-files or similar, so it’s «ok» — so to me, this is not a safe test. dpkg-query -l doesnt seem to return a useful result in this case either.

To be a little more explicit, here’s a bit of Bash script that checks for a package and installs it if required. Of course, you can do other things upon finding that the package is missing, such as simply exiting with an error code.

REQUIRED_PKG="some-package" PKG_OK=$(dpkg-query -W --showformat='$\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 

If the script runs within a GUI (e.g., it is a Nautilus script), you’ll probably want to replace the ‘sudo’ invocation with a ‘gksudo’ one.

—force-yes seems a poor idea. From man page: «This is a dangerous option that will cause apt-get to continue without prompting if it is doing something potentially harmful. It should not be used except in very special situations. Using —force-yes can potentially destroy your system!» Using it in a script makes it even worse.

Читайте также:  Linux mkdir if exist

@SaladHead See man7.org/linux/man-pages/man1/dpkg-query.1.html «Package information can be included [in showformat] by inserting variable references to package fields using the syntax “$”.» Status is one of those fields.

In your answer, perhaps explain how and why it works. E.g., what is the intent of -W —showformat=’$ ? What does the variable «Status» contain? Or is it literal? Why is it dpkg-query when some other answers use dpkg ? Etc. (But without «Edit:», «Update:», or similar — the answer should appear as if it was written today.)

This one-liner returns 1 (installed) or 0 (not installed) for the ‘nano’ package.

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

even if the package does not exist or is not available.

The example below installs the ‘nano’ package if it is not installed.

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

@knocte I’m not sure there is an argument to be made about being objectively better. Though I’m confident the verbatim post’s one-liner will execute the result output, which I wouldn’t want to leave dangling in an answer. The one liner I show exemplifies getting (printing) just the exit code.

Simpler: if ! dpkg-query -W -f=’$‘ nano | grep «ok installed»; then apt install nano; fi — No need to use grep -c , just use the exit status of grep

dpkg-query —showformat=’$’

This produces a small output string which is unlikely to change and is easy to compare deterministically without grep :

pkg=hello status="$(dpkg-query -W --showformat='$' "$pkg" 2>&1)" if [ ! $? = 0 ] || [ ! "$status" = installed ]; then sudo apt install $pkg fi 

The $? = 0 check is needed because if you’ve never installed a package before, and after you remove certain packages such as hello , dpkg-query exits with status 1 and outputs to stderr:

dpkg-query: no packages found matching hello 

instead of outputting not-installed . The 2>&1 captures that error message too when it comes preventing it from going to the terminal.

pkgs='hello certbot' install=false for pkg in $pkgs; do status="$(dpkg-query -W --showformat='$' "$pkg" 2>&1)" if [ ! $? = 0 ] || [ ! "$status" = installed ]; then install=true break fi done if "$install"; then sudo apt install $pkgs fi 

The possible statuses are documented in man dpkg-query as:

 n = Not-installed c = Config-files H = Half-installed U = Unpacked F = Half-configured W = Triggers-awaiting t = Triggers-pending i = Installed 

The single letter versions are obtainable with db:Status-Abbrev , but they come together with the action and error status, so you get 3 characters and would need to cut it.

Читайте также:  Установка asterisk astra linux

So I think it is reliable enough to rely on the uncapitalized statuses ( Config-files vs config-files ) not changing instead.

dpkg -s exit status

This unfortunately doesn’t do what most users want:

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

because for some packages, e.g. certbot , doing:

sudo apt install certbot sudo apt remove certbot 

leaves certbot in state config-files , which means that config files were left in the machine. And in that state, dpkg -s still returns 0 , because the package metadata is still kept around so that those config files can be handled more nicely.

To actually make dpkg -s return 1 as desired, —purge would be needed:

sudo apt remove --purge certbot 

which actually moves it into not-installed / dpkg-query: no packages found matching .

Note that only certain packages leave config files behind. A simpler package like hello goes directly from installed to not-installed without —purge .

Python apt package

There is a pre-installed Python 3 package called apt in Ubuntu 18.04 which exposes an Python apt interface!

A script that checks if a package is installed and installs it if not can be seen at: How to install a package using the python-apt API

Here is a copy for reference:

#!/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 " already installed".format(pkg_name=pkg_name) else: pkg.mark_install() try: cache.commit() except Exception, arg: print >> sys.stderr, "Sorry, package installation failed []".format(err=str(arg)) 

Check if an executable is in PATH instead

Ciro, ou can’t rely on «dpkg -s» exit code. For example if you «apt installed» a package, then «apt remove» it and tried to «dpkg -s packagename» then you’ll notice status: deinstall and exit code zero (as if installed). You have to parse the «dpkg -s» output bro.

@DmitryShevkoplyas thanks for the report. I could not reproduce on Ubuntu 19.10 with: sudo apt install hello; dpkg -s hello; echo $?; sudo apt remove hello; dpkg -s hello; echo $? . Can you provide further details?

indeed — for your test case with «hello» package «dpkg -s» correctly shows the package as not installed and gives expected exit code «1». But try the same instal/remove check with package «certbot», then you’ll see «Status: deinstall ok config-files» as the «dpkg -s» output after your «apt remove certbot» and exit code is incorrectly shows us «0». My wrong assumption was that it is exact case for any other package, but it seems it is not the same for all, which even worse and less predictable. Parse «dpkg -s» you must (c) Yoda 🙂

The information that dpkg remove package-name does not result in dpkg -s package-name returning 0 is missing in most answers which almost drove me crazy. It actually results in state deinstalled instead of just not installed! Puhh, Debian is . peculiar.

Читайте также:  Установить домашнюю директорию linux

Ubuntu added its «Personal Package Archive» (PPA), and PPA packages have a different result.

    A native Debian repository package is not installed:

~$ dpkg-query -l apache-perl ~$ echo $? 1 
~$ dpkg-query -l libreoffice ~$ echo $? 0 
~$ 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. 

If you install and remove a package, next you use dpkg-query package ; echo $? will be 0 also if the package is not installed.

However you can’t simply rely on return codes here for scripting

In my experience you can rely on dkpg’s exit codes.

The return code of dpkg -s is 0 if the package is installed and 1 if it’s not, so the simplest solution I found was:

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

After apt-get remove , dpkg -s still returns 0, even though the package is deinstalled

Really short and to the point. Plus good explanation. Thanks rocka84 @ThorSummoner can you clarify your point?

@KasirBarati that, the return code isn’t consistent for uninstalled and deinstalled packages- in both cases the software is missing, but in half the cases the return code indicates the software is missing. i think? its been a while since I’ve looked at this

I’ve settled on one based on Nultyi’s answer:

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 

Basically, the error message from dpkg —get-selections is far easier to parse than most of the others, because it doesn’t include statuses like «deinstall». It also can check multiple packages simultaneously, something you can’t do with just error codes.

$ 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 

So grep removes installed packages from the list, and awk pulls the package names out from the error message, resulting in MISSING=’python3-venv python3-dev jq’ , which can be trivially inserted into an install command.

I’m not blindly issuing an apt-get install $PACKAGES , because as mentioned in the comments, this can unexpectedly upgrade packages you weren’t planning on; not really a good idea for automated processes that are expected to be stable.

Источник

Оцените статью
Adblock
detector