如何从 Bash 检查某个包是否已安装?

如何从 Bash 检查某个包是否已安装?

我需要通过 Bash 脚本检查机器上是否安装了特定的包。

我发现了类似的东西,但我不知道如何正确使用它。

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

我需要检查,如果命令dpkg -l | grep "ansible" | awk '{print $2}'返回单词“Ansible”则回显 OK,否则回显 FAIL。

@编辑

我认为更好的办法是命令

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

所以这个命令返回我两个词:

ansible
ansible_lint

我应该如何使用这个 bash 脚本?如果我做这样的事情:

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

那不行,但我确定我做错了。我如何读取 dpkg -l | grep "ansible" | awk '{print $2}' 命令的结果,如果我得到单词“ansible”,脚本将打印 OK,如果没有,则打印 FAIL。

答案1

您可以通过以下方式检查软件是否安装:

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

您不能使用退出代码,因为它将来自awk并且在这种情况下始终为 0

答案2

如果你知道确切的软件包名称,你可以直接询问dpkg它是否已安装

dpkg -l packagename

例如:

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

如果未安装包,退出代码也是 1(失败),您可以对此进行测试(稍后会看到)。

$ 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

这里的退出代码是 0(成功),所以你也可以这样做

$ 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

注意上面结尾的“yes”。但是现在,由于您可以直接使用退出代码,因此您实际上并不关心 dpkg 的输出,因此可以使用if&&(AND 列表)忽略它:

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

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

dpkg 还可以使用星号匹配部分名称,例如

$ dpkg -l "*pulse*"

关于管道及其退出状态,如果您想查看管道中某处的命令是否失败,您必须执行类似检查的操作${PIPESTATUS[@]}

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

并且像 一样$?${PIPESTATUS[@]}会随着每个命令而变化,因此如果您想要多次检查它们,则必须先将它们保存到另一个变量中。在您的示例中

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

$?已经通过 if 测试进行了更改,并且它可能是 0,因为分配这样的变量几乎总是会成功。

答案3

要检查名为“pkgname”的软件包是否已成功安装,请使用

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

请参阅man dpkg-query的用法dpkg-query。With-q选项grep不输出任何内容,但当且仅当匹配时才以代码 0 退出。

相关内容