6

I need to check if a specific package is installed on a machine from within a Bash script.

I found something like that but I don't know how use it correctly.

dpkg -l | grep "ansible" | awk '{print $2}'
if [$? -eq 0]; then
  echo OK
else
  echo FAIL
fi

I need check, if command dpkg -l | grep "ansible" | awk '{print $2}' return me word "Ansible" then echo OK, else echo FAIL.

@EDIT

I think better will be command

dpkg -l | grep "ansible" | awk '{print $2}'

so this command return me two words:

ansible
ansible_lint

How should I use this bash script? If I doing something like that:

ansible = $?
if [$? -eq 0]; then
  echo OK
else
  echo FAIL
fi

that's not work, but I'm sure I doing that wrong. How can I read result from dpkg -l | grep "ansible" | awk '{print $2}' command and if I get word "ansible" script will print OK, if not print FAIL.

Share

Improve this question

Follow

edited May 29 at 17:32

muru's user avatar

muru

209k5757 gold badges518518 silver badges792792 bronze badges

asked Apr 14, 2019 at 7:58

BElluu's user avatar

BElluu

20322 gold badges44 silver badges88 bronze badges

  • You have to insert blanks after '[' and before ']': if [ $? -eq 0 ] 

    – muclux

     CommentedApr 14, 2019 at 8:12
  • Even after your edit you are still missing those spaces aroung [ ]. 

    – muclux

     CommentedApr 14, 2019 at 8:50
  • What do you want to do by that code? Do you want to check if a package whose name contains 'ansible' is installed? All lines printed by dpkg -l do not indicate installed packages. There may be removed packages, too. Note also that dpkg -l list much more than just package names, so you have to be more careful, if you examine its output by grep

    – jarno

     CommentedApr 14, 2019 at 10:24

Add a comment

4 Answers

Sorted by:

                                              Highest score (default)                                                                   Date modified (newest first)                                                                   Date created (oldest first)                              

3

You can check if the software is installed on this way:

if [ "$(dpkg -l | awk '/ansible/ {print }'|wc -l)" -ge 1 ]; then
  echo OK
else
  echo FAIL
fi

You can't use exit code because it will be from awk and in this case always be 0

Share

Improve this answer

Follow

answered Apr 14, 2019 at 8:48

Romeo Ninov's user avatar

Romeo Ninov

70977 silver badges1414 bronze badges

  • Great! I have one more question. Can you tell me how should it look, if I need check software is installed in pip so command pip list. If I check dpkg -l for pip list I got that message in terminal DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning. 

    – BElluu

     CommentedApr 14, 2019 at 9:12
  • @BElluu, please use "Ask Question" button and create new question. But in general you can replace dpkg -l with pip list to use as source the list of packages, installed with pip 

    – Romeo Ninov

     CommentedApr 14, 2019 at 9:35
  • This is bad practice in several ways: there could be several packages whose name contain string "ansible", but it could be that none of them is named "ansible". The string could be something else in the output of dpkg -l than package name. Why use awk here, as the same could be done by grep 'ansible'  that may give non-zero exit code? wc -l is not needed in checking if a string is not null in Bash. So I wonder why this is accepted answer. I have given another answer. 

    – jarno

     CommentedApr 20, 2019 at 16:41

Add a comment

Report this ad

3

If you know the exact package name, you can just ask dpkg if it's installed with

dpkg -l packagename

For example:

$ dpkg -l pulsea
dpkg-query: no packages found matching pulsea

The exit code is also 1 (fail) if a package isn't installed, you can test for that (as seen later).

$ dpkg -l pulseaudio
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name               Version        Architecture   Description
+++-==================-==============-==============-=========================
ii  pulseaudio         10.0-1+deb9u1  i386           PulseAudio sound server

Here the exit code is 0 (success), so you can do this too

$ if dpkg -l pulseaudio; then echo yes;fi
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name               Version        Architecture   Description
+++-==================-==============-==============-=========================
ii  pulseaudio         10.0-1+deb9u1  i386           PulseAudio sound server
yes

Note the trailing "yes" above. But now since you can just use the exit code, you don't really care about dpkg's output, so ignore it with an if or an && (AND list):

$ if dpkg -l pulseaudio >/dev/null; then echo yes;fi
yes

$ dpkg -l pulseaudio >/dev/null && echo yes
yes

dpkg can also match partial names, using asterisks, like

$ dpkg -l "*pulse*"

About pipes and their exit status, if you want to see if a command somewhere in a pipeline has failed you'll have to do something like examining the ${PIPESTATUS[@]}:

$ false | true
$ echo ${PIPESTATUS[@]} 
1 0

And like $?${PIPESTATUS[@]} changes with every command, so if you want to examine them more than once you have to save them to another variable first. In your example

ansible = $?
if [$? -eq 0]; then

$? has already changed by the if test, and it's probably 0 since assigning a variable like that almost always succeeds.

Share

Improve this answer

Follow

edited Apr 14, 2019 at 9:58

answered Apr 14, 2019 at 9:51

Xen2050's user avatar

Xen2050

8,98344 gold badges3636 silver badges5454 bronze badges

  • When testing exit code of dpkg, you may want to redirect standard error to null as well like this >/dev/null 2>&1

    – jarno

     CommentedApr 14, 2019 at 10:34
  • 1

    Another way to use exit status with pipe is by using set -o pipefail. See help set for more information. 

    – jarno

     CommentedApr 14, 2019 at 10:39
  • @jarno True, that's a good tip for pipes if something in there fails. I'm pretty sure examining ${PIPESTATUS[@]} is the only way to figure out what part failed & succeeded though, if that even matters 

    – Xen2050

     CommentedApr 15, 2019 at 6:18

Add a comment

1

To check, if package named 'pkgname' is successfully installed, use

if dpkg-query -W -f'${db:Status-Abbrev}\n' pkgname 2>/dev/null \
 | grep -q '^.i $'; then
    echo 'Installed'
else
    echo 'Not installed'
fi

See man dpkg-query about usage of dpkg-query. With -q option grep does not output anything, but exits with code 0 if and only if there is a match.

Share

Improve this answer

Follow

answered Apr 15, 2019 at 5:12

jarno's user avatar

jarno

6,28366 gold badges6060 silver badges8484 bronze badges

  • FYI, dpkg -l / dpkg --list looks like it runs dpkg-query --list, and dpkg-query -W is "Just like the --list option this will list all packages matching the given pattern" but with a customizable format 

    – Xen2050

     CommentedApr 15, 2019 at 6:08 
  • @Xen2050 and it does not print the header lines. 

    – jarno

     CommentedApr 15, 2019 at 14:32

Add a comment

0

I think you're supposed to use dpkg -s (--status), not dpkg -l as suggested in Xen2050's answer.

if dpkg -s some-package; then
  # Package is installed.
  ...
fi

For most packages, -s and -l seems to make no difference. However, for example, in my Docker container, systemd is not installed, yet for some reason, dpkg -l systemd still lists it, just as "not installed", and returns exit code 0:

$ dpkg -l systemd; echo Exit code: $?
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
un  systemd        <none>       <none>       (no description available)
Exit code: 0

By contrast, dpkg -s returns 1 as expected:

$ dpkg -s systemd; echo Exit code: $?
dpkg-query: package 'systemd' is not installed and no information is available
Use dpkg --info (= dpkg-deb --info) to examine archive files.
Exit code: 1
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐