3

I want to script a test for a debian package being installed.

Searching using dpkg-query, will return an error if no packages match. But if I want to detect that specifically, and abort on any other errors (e.g. resource exhaustion), I don't know how to do that.

sourcejedi
  • 50,249

2 Answers2

2

dpkg-query is quite simple, you can quickly skim the manpage and find it has no option to implement this directly. So

dpkg-query -W -f '${Package} ${State}\n' | grep "^my-package .* installed"

The problem then reduces to catching error codes in a pipeline. Apparently strict error handling in Unix shell gets awkward. I was naively hoping for one-liners :).

set -e

function pkg_is_installed() {
  PKG="$1"
  LISTF=$(mktemp)
  dpkg-query -W -f '${Package} ${State}\n' >$LISTF
  grep "^${PKG} .* installed$" $LISTF >/dev/null   
  GREP_RC=$?
  rm $LISTF

  # for even moar strict error handling
  test $GREP_RC == 0 -o $GREP_RC == 1

  return $GREP_RC
}

I believe this will print any errors that occur to stderr, while avoiding printing a message when the only "error" is that dpkg hasn't (yet) seen the requested package.

sourcejedi
  • 50,249
2

dpkg-query does have an option to do this, and its exit codes support your use case:

-s, --status package-name...

Report status of specified package. This just displays the entry in the installed package status database. When multiple package-name are listed, the requested status entries are separated by an empty line, with the same order as specified on the argument list.

(note that it looks in the installed package status database, so it can't report on anything not installed — which is what you're after); and

EXIT STATUS

0: The requested query was successfully performed.

1: The requested query failed either fully or partially, due to no file or package being found (except for --control-path, --control-list and --control-show were such errors are fatal).

2: Fatal or unrecoverable error due to invalid command-line usage, or interactions with the system, such as accesses to the database, memory allocations, etc.

(The manpage included in Debian 8 doesn't mention this, but dpkg-query does behave like that even in Debian 8.)

So something like

#!/bin/sh

dpkg-query -s package > /dev/null 2>&1
case $? in
0)
    echo $1 is installed
    ;;
1)
    echo $1 is not installed
    ;;
2)
    echo An error occurred
    ;;
esac

(turned into a function) would fit the bill as I understand it.

Stephen Kitt
  • 434,908
  • Thanks! The manpage I looked at was on Debian Jessie. It does not document the value 2 in the section EXIT STATUS, only 0 and 1. – sourcejedi Nov 25 '16 at 11:06
  • Ah yes, I hadn't checked on Jessie — I just did, and the behaviour is as described above; the manpage is outdated. – Stephen Kitt Nov 25 '16 at 11:11