10

My binary depends on these boost libraries and respective packages:

NAME                                  |          PACKAGE:
--------------------------------------+-----------------------------------
libboost_serialization.so.1.55.0      |  libboost-serialization1.55.0
libboost_thread.so.1.55.0             |  ibboost-thread1.55.0
libboost_date_time.so.1.55.0          |  libboost-date-time1.55.0
libboost_signals.so.1.55.0            |  libboost-signals1.55.0

So I'd like to define a list of packages:

boostlibnames="libboost-serialization1.55.0 libboost-thread1.55.0 libboost-date-time1.55.0 libboost-signals1.55.0"

And now I'd like to check if they are all installed and only then run actual apt-get install. I know apt will automatically check whether the packages are already installed, but I'd like to place in a prompt to the user whether he wants to install missing libraries before doing so.

So is there a nice way to check whether all listed libraries (in variable as above) are installed?

Tomáš Zato
  • 1,776
  • 1
    Create a proper Debian package and let apt handle the dependencies – ivanivan Apr 20 '18 at 22:11
  • @ivanivan It's an internal company application and of course not open-source. – Tomáš Zato Apr 21 '18 at 15:14
  • Doesn't mean that you have to distribute the deb file or anything else beyond your internal company ... just use the packaging systems dependency resolving. Heck, use the method on this q/a to create a fake package to get the deps installed - https://unix.stackexchange.com/questions/318117/create-a-deb-package-with-only-dependencies – ivanivan Apr 21 '18 at 15:42

5 Answers5

14

The dpkg -s command returns the status of installed packages. For example, on my system, if I run it for firefox which is installed and nedit which isn't, I get:

$ dpkg -s firefox
Package: firefox
Status: install ok installed
Priority: optional
Section: web
Installed-Size: 94341
Maintainer: Clement Lefebvre <root@linuxmint.com>
Architecture: amd64
Version: 41.0~linuxmint1+betsy
Replaces: firefox-l10n-af, firefox-l10n-ar, firefox-l10n-be, firefox-l10n-bg, firefox-l10n-bn-bd, firefox-l10n-ca, firefox-l10n-cs, firefox-l10n-da, firefox-l10n-de, firefox-l10n-el, firefox-l10n-en-gb, firefox-l10n-en-us, firefox-l10n-eo, firefox-l10n-es, firefox-l10n-et, firefox-l10n-eu, firefox-l10n-fa, firefox-l10n-fi, firefox-l10n-fr, firefox-l10n-fy, firefox-l10n-gl, firefox-l10n-gu, firefox-l10n-he, firefox-l10n-hi, firefox-l10n-hr, firefox-l10n-hu, firefox-l10n-id, firefox-l10n-is, firefox-l10n-it, firefox-l10n-ja, firefox-l10n-kn, firefox-l10n-ko, firefox-l10n-lt, firefox-l10n-lv, firefox-l10n-nb, firefox-l10n-nl, firefox-l10n-nn, firefox-l10n-pl, firefox-l10n-pt, firefox-l10n-pt-br, firefox-l10n-ro, firefox-l10n-ru, firefox-l10n-sk, firefox-l10n-sl, firefox-l10n-sq, firefox-l10n-sr, firefox-l10n-sv, firefox-l10n-th, firefox-l10n-tr, firefox-l10n-uk, firefox-l10n-zh
Provides: gnome-www-browser, www-browser
Breaks: firefox-l10n-en-us
Description: The Firefox web browser
 The Mozilla Firefox Web Browser.

$ dpkg -s nedit
dpkg-query: package 'nedit' is not installed and no information is available
Use dpkg --info (= dpkg-deb --info) to examine archive files,
and dpkg --contents (= dpkg-deb --contents) to list their contents.

So, you can use that command to check whether a package is installed:

#!/usr/bin/env bash

run_install()
{
    ## Prompt the user 
    read -p "Do you want to install missing libraries? [Y/n]: " answer
    ## Set the default value if no answer was given
    answer=${answer:Y}
    ## If the answer matches y or Y, install
    [[ $answer =~ [Yy] ]] && apt-get install ${boostlibnames[@]}
}

boostlibnames=("libboost-serialization1.55.0" "libboost-thread1.55.0"
                "libboost-date-time1.55.0" "libboost-signals1.55.0" "nedit")
## Run the run_install function if sany of the libraries are missing
dpkg -s "${boostlibnames[@]}" >/dev/null 2>&1 || run_install
terdon
  • 242,166
  • Is there some short way to save results? Eg. in C/C++ I'd do installed = installed || isInstalled(libArray[i]). So similarly, I'd like to put false in a variable if one or more were not installed. I think I can do this with if, but that's a lot of code for nothing. – Tomáš Zato Oct 12 '15 at 15:05
  • @TomášZato yes, but you'll have to be more specific. Do you want to save the list of missing libraries? Is just one enough? Personally, I would just check whether all are installed and if at least one isn't, run apt-get install on all of them. Any that are installed will simply be ignored. Let me know what you want and I'll edit this. Basically, you'll need to change the || echo ... to || installed=1 or something. – terdon Oct 12 '15 at 15:21
  • I wanted to do exactly what you do, it's wasted effort to save list of missing libraries. Just check'em all, and if any is missing, prompt user for apt-get. I already got your code working with ugly if statement, but variable would be preffered. I plan on wraping it into a function. – Tomáš Zato Oct 12 '15 at 15:23
  • @TomášZato OK, have a look at the updated answer. I simplified it a bit since dpkg -s can check for multiple packages at once. – terdon Oct 12 '15 at 15:33
3

I use the following code in my work called the Easy Bash, which helps install the most popular packages quicky on Ubuntu servers. This code will check the listed packages installed or not.

#!/usr/bin/env bash

packages=("curl" "gnupg2" "ca-certificates" "lsb-release")

for pkg in ${packages[@]}; do

    is_pkg_installed=$(dpkg-query -W --showformat='${Status}\n' ${pkg} | grep "install ok installed")

    if [ "${is_pkg_installed}" == "install ok installed" ]; then
        echo ${pkg} is installed.
    fi
done

Result:

enter image description here

Terry Lin
  • 131
1

The following will give you a list of all relevant packages which aren't installed:

dpkg -l $boostlibnames 2>&1 | awk '{if (/^D|^\||^\+/) {next} else if(/^dpkg-query:/) { print $6} else if(!/^[hi]i/) {print $2}}' 

This skips dpkg -l's header lines, and then prints out lines where dpkg-query complains about a an unknown package, AND lines not beginning with hi or ii (Hold Inst or Install Inst).

Usually, I'd do something like awk 'NR<=5 {next} ; ...' or sed -e '1,5d' to get rid of dpkg -l's header lines but in this case we're redirecting stderr to stdout in order to catch complaints by dpkg-query as well as dpkg -l's output, so we can't simply delete the first 5 lines.

This will show packages either never installed, removed, purged, or where the install has failed / partially-completed due to error.

cas
  • 78,579
1

I did this function for a CentOS system today.

#!/bin/bash

# List of the packages that should be present
list=("vim-enhanced" "nano" "expect" "dialog" "epel-release" "yum-utils" "bind-utils")

# Check for the existence of the packages in the system and print to file.txt the packages to be installed
check_list=$(rpm -q "${list[@]}" | grep -e "not installed" | awk 'BEGIN { FS = " " } ; { print $2}' > list.txt)

# Check if the list.txt is empty
grep -q '[^[:space:]]' < list.txt
EMPTY_FILE=$?
# If list.txt is empty there's nothing to do
if [[ $EMPTY_FILE -eq 1 ]]; then

echo "Nothing to do"

else

# If list.txt is not empty it installs the packages in list.txt

for PACKAGES in `cat /your/path/list.txt`; do

  yum install -y $PACKAGES

done

fi

Well, i slightly modified the function. Faster and it does not need a loop anymore.

#!/bin/bash


list=("vim-enhanced" "nano" "expect" "dialog" "epel-release" "yum-utils" "bind-utils")
check_list=$(rpm -q "${list[@]}" | grep -e "not installed" | awk 'BEGIN { FS = " " } ; { printf $2" "}' > /your/path/to/list.txt)
install=$(cat /your/path/to/list.txt)

grep -q '[^[:space:]]' < /your/path/to/list.txt

EMPTY_FILE=$?

if [[ $EMPTY_FILE -eq 1 ]]; then

echo "Nothing to do"

else

yum install -y $install

fi

The Debian/Ubuntu counterpart:

apt -qq YOUR_LIST_GOES_HERE | grep -v "installed" | awk -F/ '{print $1}' > /your/path/to/list.txt
packages=$(cat /your/path/to/list.txt)
grep -q '[^[:space:]]' < /your/path/to/list.txt
EMPTY_FILE=$?
if [[ $EMPTY_FILE -eq 1 ]]; then
echo "Nothing to do"
else
apt-get  install -y $packages
fi
-1
#to check package is installed or not without distribution dependency
#!/bin/bash
read -p "Package Name: " pkg
which $pkg > /dev/null 2>&1
if [ $? == 0 ]
then
echo "$pkg is already installed. "
else
read -p "$pkg is not installed. Answer yes/no if want installation_ " request
if  [ $request == "yes" ]
then
yum install $pkg
fi
fi
linux.cnf
  • 129