Bash 如何检查软件包是否已安装,如果未安装,如何安装?

Bash 如何检查软件包是否已安装,如果未安装,如何安装?,bash,apt-get,Bash,Apt Get,我正在Ubuntu系统上工作,目前我正在做: if ! which command > /dev/null; then echo -e "Command not found! Install? (y/n) \c" read if "$REPLY" = "y"; then sudo apt-get install command fi fi 这是大多数人会做的吗?或者有更优雅的解决方案吗?要检查是否安装了packagename,请键入: dpkg -s

我正在Ubuntu系统上工作,目前我正在做:

if ! which command > /dev/null; then
   echo -e "Command not found! Install? (y/n) \c"
   read
   if "$REPLY" = "y"; then
      sudo apt-get install command
   fi
fi

这是大多数人会做的吗?或者有更优雅的解决方案吗?

要检查是否安装了
packagename
,请键入:

dpkg -s <packagename>
要查找拥有
命令的包,请尝试:

dpkg -S `which <command>`
dpkg-S``

有关更多详细信息,请参阅文章和。

此功能已存在于Ubuntu和Debian中,位于未找到的
命令包中。

更明确一点,这里有一个bash脚本,用于检查包并在需要时安装。当然,您可以在发现包丢失时执行其他操作,例如仅带错误代码退出

REQUIRED_PKG="some-package"
PKG_OK=$(dpkg-query -W --showformat='${Status}\n' $REQUIRED_PKG|grep "install ok installed")
echo Checking for $REQUIRED_PKG: $PKG_OK
if [ "" = "$PKG_OK" ]; then
  echo "No $REQUIRED_PKG. Setting up $REQUIRED_PKG."
  sudo apt-get --yes install $REQUIRED_PKG 
fi

如果脚本在GUI中运行(例如,它是Nautilus脚本),您可能会想用“gksudo”调用替换“sudo”调用。

我提供此更新,因为Ubuntu在回答此问题时添加了“个人软件包存档”(PPA),PPA软件包有不同的结果

  • 未安装本机Debian存储库包:

    ~$ dpkg-query -l apache-perl
    ~$ echo $?
    1
    
    ~$ dpkg-query -l libreoffice
    ~$ echo $?
    0
    
    ~$ dpkg-query -l 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包:

    ~$ dpkg-query -l apache-perl
    ~$ echo $?
    1
    
    ~$ dpkg-query -l libreoffice
    ~$ echo $?
    0
    
    ~$ dpkg-query -l 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包:

    ~$ dpkg-query -l apache-perl
    ~$ echo $?
    1
    
    ~$ dpkg-query -l libreoffice
    ~$ echo $?
    0
    
    ~$ dpkg-query -l 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.
    

  • 也发布在:

    这似乎很有效

    $ sudo dpkg-query -l | grep <some_package_name> | wc -l
    
    $sudo dpkg query-l | grep | wc-l
    
    • 如果未安装,则返回
      0
      ,如果安装,则返回某个数字
      >0

    此命令是最难忘的:

    dpkg --get-selections <package-name>
    
    dpkg——获取选择
    
    如果已安装,则打印:

    安装

    否则会打印出来

    没有找到匹配的包

    这是在Ubuntu 12.04.1(精确穿山甲)上测试的。

    对于“nano”软件包,这一行返回1(已安装)或0(未安装)

    $(dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed")
    
    即使包不存在/不可用

    下面的示例将安装“nano”软件包(如果未安装)

    if [ $(dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed") -eq 0 ];
    then
      apt-get install nano;
    fi
    
    乌潘达姆写道:

    但是,您不能简单地依赖这里的返回码来编写脚本

    在我的体验中,你可以依赖dkpg的退出代码

    如果安装了软件包,dpkg-s的返回代码为0,如果没有安装,返回代码为1,因此我找到的最简单的解决方案是:

    dpkg -s <pkg-name> 2>/dev/null >/dev/null || sudo apt-get -y install <pkg-name>
    
    dpkg-s2>/dev/null>/dev/null | | sudo apt get-y安装
    

    对我来说很好…

    这样就可以了<代码>apt get install
    是幂等的

    $name="rsync"
    
    [ `which $name` ] $$ echo "$name : installed" || sudo apt-get install -y $name
    
    sudo apt-get install command
    

    我发现,如果安装了软件包,然后又将其删除,但安装软件包仍保留在系统上,则上述所有解决方案都会产生误报

    复制: 安装包
    apt get Install curl

    删除包
    apt get Remove curl

    现在测试以上答案

    以下命令似乎可以解决此问题:
    dpkg query-W-f='${Status}\n'curl | head-n1 | awk'{print$3;}'| grep-q'^installed$'

    这将导致最终结果 已安装未安装

    哪个
    
    which <command>
    if [ $? == 1 ]; then
        <pkg-manager> -y install <command>
    fi
    
    如果[$?==1];然后 -y安装 fi
    使用:

    否则将显示:

    Installed: none
    
    Installed: version
    

    除了dpkg和旧的apt-*工具之外,apt似乎是最简单的方法。对于Ubuntu,apt提供了一种相当不错的方法。下面是google chrome的一个示例:

    apt-qq列表google chrome stable 2>/dev/null | grep-qE“(已安装|可升级)”| | apt获得安装google chrome stable


    我将错误输出重定向到null,因为apt警告不要使用其“不稳定cli”。我怀疑列表包是稳定的,所以我认为可以扔掉这个警告。-qq让apt变得超级安静。

    我选择了一个基于:

    基本上,来自
    dpkg--get selections
    的错误消息比其他大多数错误消息更容易解析,因为它不包括“deinstall”之类的状态。它还可以同时检查多个包,这是错误代码所不能做到的

    解释/示例:

    $ dpkg --get-selections  python3-venv python3-dev screen build-essential jq
    dpkg: no packages found matching python3-venv
    dpkg: no packages found matching python3-dev
    screen                                          install
    build-essential                                 install
    dpkg: no packages found matching jq
    
    因此,grep从列表中删除已安装的软件包,awk从错误消息中提取软件包名称,导致
    缺少
    ,这可以很容易地插入到install命令中


    我不是盲目地发布一个
    apt get install$PACKAGES
    ,因为正如评论中提到的,这可能会意外地升级您不打算升级的软件包;对于期望稳定的自动化流程来说,这并不是一个好主意。

    很多事情都告诉过我,但对我来说,最简单的方法是:

    dpkg -l | grep packagename
    

    在本地而不是在docker中运行测试时,我也有类似的要求。基本上,我只想安装任何未安装的.deb文件

    # If there are .deb files in the folder, then install them
    if [ `ls -1 *.deb 2> /dev/null | wc -l` -gt 0 ]; then
      for file in *.deb; do
        # Only install if not already installed (non-zero exit code)
        dpkg -I ${file} | grep Package: | sed -r 's/ Package:\s+(.*)/\1/g' | xargs dpkg -s
        if [ $? != 0 ]; then
            dpkg -i ${file}
        fi;
      done;
    else
      err "No .deb files found in '$PWD'"
    fi
    
    我想我能看到的唯一问题是它没有检查包的版本号,所以如果.deb文件是较新的版本,那么这不会覆盖当前安装的包。

    在Bash中:

    PKG="emacs"
    dpkg-query -l $PKG > /dev/null || sudo apt install $PKG
    
    请注意,在PKG中可以有一个包含多个包的字符串。

    dpkg查询--showformat='${db:Status Status}'

    这将生成一个小的输出字符串,该字符串不太可能更改,并且很容易在没有
    grep的情况下进行确定性比较:

    pkg=hello
    status="$(dpkg-query -W --showformat='${db:Status-Status}' "$pkg" 2>&1)"
    if [ ! $? = 0 ] || [ ! "$status" = installed ]; then
      sudo apt install $pkg
    fi
    
    $?=需要进行0
    检查,因为如果您以前从未安装过软件包,并且在删除某些软件包(如
    hello
    )后,
    dpkg query
    将以状态1退出并输出到stderr:

    dpkg-query: no packages found matching hello
    
    而不是输出未安装的
    2>&1
    在阻止该错误消息进入终端时也会捕获该错误消息

    对于多个包:

    pkgs='hello certbot'
    install=false
    for pkg in $pkgs; do
      status="$(dpkg-query -W --showformat='${db:Status-Status}' "$pkg" 2>&1)"
      if [ ! $? = 0 ] || [ ! "$status" = installed ]; then
        install=true
        break
      fi
    done
    if "$install"; then
      sudo apt install $pkgs
    fi
    
    可能的状态记录在man dpkg查询中,如下所示:

       n = Not-installed
       c = Config-files
       H = Half-installed
       U = Unpacked
       F = Half-configured
       W = Triggers-awaiting
       t = Triggers-pending
       i = Installed
    
    单字母版本可以通过
    db:Status Abbrev
    获得,但它们与操作和错误状态一起出现,因此您可以获得3个字符,并且需要
    sudo apt remove --purge certbot
    
    #!/usr/bin/env python
    # aptinstall.py
    
    import apt
    import sys
    
    pkg_name = "libjs-yui-doc"
    
    cache = apt.cache.Cache()
    cache.update()
    cache.open()
    
    pkg = cache[pkg_name]
    if pkg.is_installed:
        print "{pkg_name} already installed".format(pkg_name=pkg_name)
    else:
        pkg.mark_install()
    
        try:
            cache.commit()
        except Exception, arg:
            print >> sys.stderr, "Sorry, package installation failed [{err}]".format(err=str(arg))
    
    apt-get install --no-upgrade package
    
    dpkg-query -W -f '${Status}\n' 'PKG' 2>&1|awk '/ok installed/{print 0;exit}{print 1}'
    
    dpkg-query -W -f '${Status}\n' 'PKG' 2>&1|awk '/ok installed/{print 1;exit}{print 0}'
    
    installed() {
        return $(dpkg-query -W -f '${Status}\n' "${1}" 2>&1|awk '/ok installed/{print 0;exit}{print 1}')
    }
    
    
    # usage:
    installed gcc && echo Yes || echo No
    
    #or
    
    if installed gcc; then
        echo yes
    else
        echo no
    fi
    
    #! /bin/bash
    
    installed() {
        return $(dpkg-query -W -f '${Status}\n' "${1}" 2>&1|awk '/ok installed/{print 0;exit}{print 1}')
    }
    
    pkgs=(libgl1-mesa-dev xorg-dev vulkan-tools libvulkan-dev vulkan-validationlayers-dev spirv-tools)
    missing_pkgs=""
    
    for pkg in ${pkgs[@]}; do
        if ! $(installed $pkg) ; then
            missing_pkgs+=" $pkg"
        fi
    done
    
    if [ ! -z "$missing_pkgs" ]; then
        cmd="sudo apt install -y $missing_pkgs"
        echo $cmd
    fi
    
    function must_install(){ 
       return "$(apt -qq list $var --installed 2> /dev/null |wc -l)"
    }
    
    function install_if() { 
        unset install
        for var in "$@"
        do
            if $(must_install $var)
            then
                install+="${var} "
            fi
        done
        if [ -n "$install" ];
        then 
            sudo apt-get install -qy $install
        fi
    }