测试是否在APT中安装了软件包


10

我想要一个外壳脚本方法来测试/报告是否安装了软件包。我不需要详细信息,只需布尔返回即可设置逻辑流程。我查看了“ 查找是否已安装软件包”,但是dpkg返回复杂的输出,并且其格式会根据软件包是在Debian存储库中还是在Ubuntu PPA中而变化。

我发现这apt-cache做得很好,并提出了以下方法:

is_installed=0
test_installed=( `apt-cache policy package-name | grep "Installed:" ` )
[ ! "${test_installed[1]}" == "(none)" ] && is_installed=1

有谁知道更简单或更直接的方法?

Answers:


12

dpkg-query 就像在您的链接文章中一样,似乎是最正确的工具,除了在这种脚本上下文中使用可用的Python库直接绑定到APT系统之外。

dpkg-query

dpkg-query -Wf'${db:Status-abbrev}' package-name 2>/dev/null | grep -q '^i'

0如果安装了软件包,将返回true(在shell脚本中为退出状态1),否则为false(退出状态)。

  • -W表示“显示”(dpkg-query必须执行请求的操作)。
  • -f 更改输出格式。
  • db:Status-abbrev 是包装状态的简称。
  • 2>/dev/null沉默dpkg-query,如果一个无效的包名给出。如何处理此问题可能视情况而定。
  • grep -q 如果存在匹配项,则返回true,否则返回false。

如果经常使用,可以将其设为简单的功能:

#!/bin/sh
debInst() {
    dpkg-query -Wf'${db:Status-abbrev}' "$1" 2>/dev/null | grep -q '^i'
}

if debInst "$1"; then
    printf 'Why yes, the package %s _is_ installed!\n' "$1"
else
    printf 'I regret to inform you that the package %s is not currently installed.\n' "$1"
fi

或者只是

#!/bin/sh
if dpkg-query -Wf'${db:Status-abbrev}' "$1" 2>/dev/null | grep -q '^i'; then
    printf 'Why yes, the package "%s" _is_ installed!\n' "$1"
else
    printf 'I regret to inform you that the package "%s" is not currently installed.\n' "$1"
fi

尽管这无疑是正确的,但我发现dpkg-query -l "$package" | grep -q ^.i通常就足够了(并且更容易记住)。
phogg 2012年

1
@phogg:是的,取决于它是否应该存在于脚本中。另外,由于dpkg-query -l输出只是用户演示模式,因此输出不是一成不变的,因此,如果演示更改,则此类脚本可能会中断。
丹尼尔·安德森

@丹尼尔 我喜欢返回码方法。请在代码中查看我的答案以及详细信息。
tahoar,2012年

在10.04上,格式选项db:Status-abbrev似乎不存在-我用过:dpkg-query -Wf'${Version}' ${pkg} 2>/dev/null | grep -q '^\d*'具有相同的效果。
scottynomad

1

我用以下结果在三个软件包上测试了Daniel的建议:

  1. 未安装本机Debian存储库软件包:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' apache-perl
    ~$ echo $?
    1
    
  2. 在主机上注册并安装的PPA软件包:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' libreoffice
    ~$ echo $?
    0
    
  3. 在主机上注册但未安装的PPA软件包:

    ~$ dpkg-query -Wf'${db:Status-abbrev}' 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.
    

尽管我喜欢这种方法,但似乎我不相信PPA软件包的返回码。缺少这些,我想我将坚持解析apt-cache policy命令的返回。


好吧,您的代码示例不是我所说的,但是我想您只是错过了grep粘贴的一部分。我无法真正重现您的问题,但这可能是因为代码示例当前不完整,所以请解决此问题。您运行Debian还是Ubuntu?
丹尼尔·安德森

我正在运行Ubuntu 10.04(PPA是否不受直接Debian支持?)。我的代码删除了您的grep,因为1)dkpg-query命令未向stdout写入任何内容,而grep始终抛出返回码。如果已安装,则dpkg-query的返回码为0。
tahoar 2012年

2
1.然后,不要将您的帖子标记为“ Debian”。2.我认为您不理解grep命令中扮演的角色,因此您删除了它,现在您说它不起作用?如果匹配,即安装程序或程序不可用,或者安装了程序,则grep -q给出返回码。我在帖子中解释了这一点。10
Daniel Andersson

1
#!/bin/bash

# Check for dependencies 
check_deps () {
DEPS=$(echo {dialog,sqlite3,openssh-client})
for i in $DEPS ; do
    dpkg-query -W -f='${Package}\n' | grep ^$i$ > /dev/null
    if [ $? != 0 ] ; then
        echo "Installing deps ..."
        aptitude install $i -y > /dev/null
    fi
done  
}

# execute the check_deps function
check_deps

-1,问题不在于依赖检查。另外,请解释命令的各个部分在做什么:否则其他人将看不到正在发生的事情。
丹尼尔·安德森

DEPS=$(echo {dialog,sqlite3,openssh-client})可以等价地写成DEPS="dialog sqlite3 openssh-client"
2013年

1

我喜欢丹尼尔·安德森(Daniel Andersson)的回答,但这对我没有用。我在Ubuntu 12.04上。

dpkg手册页中db:Status-abbrev仅适用于dpkg 1.16.2+:

          db:Status-Abbrev
                 It  contains the abbreviated package status, such as “ii”
                 (since dpkg 1.16.2).

我的解决方案是使用传统行为,仅使用Status格式化程序:

dpkg-query -Wf'${Status}' {my_pkg_name}

输出

install ok installed 

我猜想这是其他表示形式中“ ii”的灵感来源。

因此,为了完全改编Daniel Andersson的答案,使其可以在较旧版本的dpkg以及较旧的Ubuntu发行版上工作:

dpkg-query -Wf'${Status}' {your_pkg_name} 2>/dev/null | grep -q "install ok installed"

返回值:

  • 0-已安装软件包,或
  • 1-未安装软件包。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.