Bash 如何检查软件包是否已安装,如果未安装,如何安装?
我正在Ubuntu系统上工作,目前我正在做: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
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
}