bash 检查是否安装了 apt-get 软件包,如果它不在 Linux 上,则安装它

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1298066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:25:18  来源:igfitidea点击:

Check if an apt-get package is installed and then install it if it's not on Linux

bashshellapt-get

提问by John Jiang

I'm working on a Ubuntu system and currently this is what I'm doing:

我正在 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

Is this what most people would do? Or is there a more elegant solution?

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

回答by viam0Zah

To check if packagenamewas installed, type:

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

dpkg -s <packagename>

You can also use dpkg-querythat has a neater output for your purpose, and accepts wild cards, too.

您也可以使用dpkg-query它来为您的目的提供更整洁的输出,并且也接受通配符。

dpkg-query -l <packagename>

To find what package owns the command, try:

要查找拥有 的包command,请尝试:

dpkg -S `which <command>`

For further details, see article Find out if package is installed in Linuxand dpkg cheat sheet.

有关更多详细信息,请参阅文章找出 Linux 中是否安装了软件包dpkg 备忘单

回答by Urhixidur

To be a little more explicit, here's a bit of bash script that checks for a package and installs it if required. Of course, you can do other things upon finding that the package is missing, such as simply exiting with an error code.

更明确地说,这里有一些 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

If the script runs within a GUI (e.g. it is a Nautilus script), you'll probably want to replace the 'sudo' invocation with a 'gksudo' one.

如果脚本在 GUI 中运行(例如,它是一个 Nautilus 脚本),您可能希望将 'sudo' 调用替换为一个 'gksudo' 调用。

回答by Seb

This one-liner returns 1 (installed) or 0 (not installed) for the 'nano' package..

对于“纳米”包,此单行返回 1(已安装)或 0(未安装)。

$(dpkg-query -W -f='${Status}' nano 2>/dev/null | grep -c "ok installed")

even if the package does not exist / is not available.

即使包不存在/不可用。

The example below installs the 'nano' package if it is not installed..

如果未安装,下面的示例将安装“nano”包。

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

回答by tahoar

I offer this update since Ubuntu added its "Personal Package Archive" (PPA) just as this question was answered, and PPA packages have a different result.

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

  1. Native Debian repository package not installed:

    ~$ dpkg-query -l apache-perl
    ~$ echo $?
    1
    
  2. PPA package registered on host and installed:

    ~$ dpkg-query -l libreoffice
    ~$ echo $?
    0
    
  3. PPA package registered on host but not installed:

    ~$ 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.
    
  1. 未安装本机 Debian 存储库包:

    ~$ dpkg-query -l apache-perl
    ~$ echo $?
    1
    
  2. 在主机上注册并安装的 PPA 包:

    ~$ dpkg-query -l libreoffice
    ~$ echo $?
    0
    
  3. 在主机上注册但未安装的 PPA 包:

    ~$ 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.
    

Also posted on: https://superuser.com/questions/427318/test-if-a-package-is-installed-in-apt/427898

还发布在:https: //superuser.com/questions/427318/test-if-a-package-is-installed-in-apt/427898

回答by rocka84

UpAndAdam wrote:

UpAndAdam 写道:

However you can't simply rely on return codes here for scripting

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

In myexperience you canrely on dkpg's exit codes.

根据我的经验,您可以依赖 dkpg 的退出代码。

The return code of dpkg -sis 0if the package is installed and 1if it's not, so the simplest solution I found was:

如果安装了包,dpkg -s的返回码为0,否则为1,所以我找到的最简单的解决方案是:

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

Works fine for me...

对我来说很好用...

回答by sandman

This seems to work pretty well.

这似乎工作得很好。

$ sudo dpkg-query -l | grep <some_package_name> | wc -l
  • It either returns 0if not installed or some number > 0if installed.
  • 0如果未安装,则返回,如果已安装,则返回某个数字> 0

回答by Izkata

I've settled on one based on Nultyi's answer:

我已经根据Nultyi 的回答确定了一个:

MISSING=$(dpkg --get-selections $PACKAGES 2>&1 | grep -v 'install$' | awk '{ print  }')
# Optional check here to skip bothering with apt-get if $MISSING is empty
sudo apt-get install $MISSING

Basically, the error message from dpkg --get-selectionsis far easier to parse than most of the others, because it doesn't include statuses like "deinstall". It also can check multiple packages simultaneously, something you can't do with just error codes.

基本上,错误消息dpkg --get-selections比大多数其他错误消息更容易解析,因为它不包括“卸载”等状态。它还可以同时检查多个包,这是仅凭错误代码无法做到的。

Explanation/example:

说明/示例:

$ 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

So grep removes installed packages from the list, and awk pulls the package names out from the error message, resulting in MISSING='python3-venv python3-dev jq', which can be trivially inserted into an install command.

因此,grep 从列表中删除已安装的包,而 awk 从错误消息中提取包名称,从而生成MISSING='python3-venv python3-dev jq',可以轻松地将其插入到安装命令中。

I'm not blindly issuing an apt-get install $PACKAGESbecause as mentioned in the comments, this can unexpectedly upgrade packages you weren't planning on; not really a good idea for automated processes that are expected to be stable.

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

回答by Mark

I've found all solutions above can produce a false positive if a package is installed and then removed yet the installation package remains on the system.

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

To replicate: Install package apt-get install curl
Remove package apt-get remove curl

复制: 安装包apt-get install curl
删除包apt-get remove curl

Now test above answers.

现在测试上面的答案。

The following command seems to solve this condition:
dpkg-query -W -f='${Status}\n' curl | head -n1 | awk '{print $3;}' | grep -q '^installed$'

以下命令似乎解决了这种情况:
dpkg-query -W -f='${Status}\n' curl | head -n1 | awk '{print $3;}' | grep -q '^installed$'

This will result in a definitive installedor not-installed

这将导致最终 安装或未安装

回答by Giovanni Mascellani

It seems that nowadays apt-gethas an option --no-upgradethat just does what the OP wants:

现在似乎apt-get有一个选项--no-upgrade可以满足 OP 的要求:

--no-upgradeDo not upgrade packages. When used in conjunction with install, no-upgrade will prevent packages listed from being upgraded if they are already installed.

--no-upgrade不要升级软件包。当与 install 结合使用时,no-upgrade 将阻止已安装的软件包被升级。

Manpage from https://linux.die.net/man/8/apt-get

来自https://linux.die.net/man/8/apt-get 的手册

Therefore you can use

因此你可以使用

apt-get install --no-upgrade package

and packagewill be installed only if it's not.

并且package只有在没有时才会安装。

回答by Mohammed Noureldin

Use:

用:

apt-cache policy <package_name>

If it is not installed, it will show:

如果没有安装,会显示:

Installed: none

Otherwise it will show:

否则会显示:

Installed: version