Linux-如何比较已安装的软件包版本通过shell脚本新安装
我正在尝试编写一个shell脚本,可以将Avamar客户端安装到Redhat或Centos机箱上。我将要安装的pkg放入repo dir/ava/repo中 脚本需要执行以下操作:Linux-如何比较已安装的软件包版本通过shell脚本新安装,linux,shell,centos,redhat,rpm,Linux,Shell,Centos,Redhat,Rpm,我正在尝试编写一个shell脚本,可以将Avamar客户端安装到Redhat或Centos机箱上。我将要安装的pkg放入repo dir/ava/repo中 脚本需要执行以下操作: 检查/ava/repo中的最新包装。在本例中,最新版本为AvamaClient-linux-sles11-x86_64-6.1.100-802.rpm(已编辑) 检查服务器上以前安装的Avamar客户端。我可以和你核对 rpm-qa | grep AvamarClient AvamaClient-6.1.100-40
谢谢您必须从安装的软件包中获取主版本号、次版本号和内部版本号。 同样地,您需要从尝试安装的软件包中了解主版本号、次版本号和内部版本号。 首先比较主要编号,然后比较次要编号,然后比较内部编号 我已经写了我解释过的逻辑
#!/bin/bash
INSTALLED_VERSION="AvamarClient-6.1.100-402.x86_64"
CURRENT_VERSION="AvamarClient-6.1.90-102.x86_64"
#get the Major numbe,Minor number and build number from the Installed version string
INST_MAJOR=`echo $INSTALLED_VERSION | cut -d'-' -f2 | cut -d'.' -f1`
INST_MINOR=`echo $INSTALLED_VERSION | cut -d'-' -f2 | cut -d'.' -f2`
INST_BUILD=`echo $INSTALLED_VERSION | cut -d'-' -f2 | cut -d'.' -f3`
echo "INST_MAJOR=$INST_MAJOR,INST_MINOR=$INST_MINOR,INST_BUILD=$INST_BUILD"
#get the Major numbe,Minor number and build number from the Current version string
CUR_MAJOR=`echo $CURRENT_VERSION | cut -d'-' -f2 | cut -d'.' -f1`
CUR_MINOR=`echo $CURRENT_VERSION | cut -d'-' -f2 | cut -d'.' -f2`
CUR_BUILD=`echo $CURRENT_VERSION | cut -d'-' -f2 | cut -d'.' -f3`
echo "CUR_MAJOR=$CUR_MAJOR,CUR_MINOR=$CUR_MINOR,CUR_BUILD=$CUR_BUILD"
if [ $CUR_MAJOR -gt $INST_MAJOR ]
then
echo "Starting with Installation..."
elif [ $CUR_MAJOR -eq $INST_MAJOR ]
then
if [ $CUR_MINOR -gt $INST_MINOR ]
then
echo "Starting with Installation..."
elif [ $CUR_MINOR -eq $INST_MINOR ]
then
if [ $CUR_BUILD -gt $INST_BUILD ]
then
echo "Starting with Installation..."
elif [ $CUR_BUILD -eq $INST_BUILD ]
then
echo "Package already installed..."
else
echo "You are trying to install older package...Exiting"
fi
else
echo "You are trying to install older package...Exiting"
fi
else
echo "You are trying to install older package...Exiting"
fi
这将非常详细地向您展示如何进行文本提取和操作。我们将基本上从/ava/repo中的候选文件中提取版本,并将其转换为一个数字,可使用以下公式进行比较:
AVAMAR_INSTALLED_MAGIC=$((1000000 * $AVAMAR_INSTALLED_VER_MAJ + 10000 * $AVAMAR_INSTALLED_VER_MIN + $AVAMAR_INSTALLED_VER_REL))
我们将使用此数字形式首先计算出/ava/repo中的最新版本,然后将其与我们安装的版本进行比较,看看是否要替换它
现在我们开始:
这很复杂
首先,整件事:
AVAMAR_CANDIDATE=$(ls -1 /ava/repo/AvamarClient* | \
sed -e 's/.*/&:&/' \
-e 's/-[0-9]*-x86_64//1' \
-e 's/AvamarClient-//' \
-e 's/\./:/1' -e 's/\./:/1' | \
awk -F: '{ print 1000000 * $1 + 10000 * $2 + $3 " " $4 }' | \
sort -n | tail -n1 )
让我们看看发生了什么。我们假设回购协议中有一份以上的候选人副本
我们列出/ava/repo
中的所有文件,并将其传输到sed+awk脚本,该脚本计算出它们的版本号并对它们进行排序,以便最后一个是最新的
让我们看看每个部分
塞德
步骤1:
-e 's/.*/&:&/'
创建名称的两个副本,以:
分隔。(我们将使用第2步和第3步分割第一个版本,并将其减少到版本号。保留第二个完整版本,以便稍后使用rpm命令)
步骤2:
-e 's/-[0-9]*-x86_64[^:]*//1'
从文件名的第一个副本中删除单词-NNN-x86_64.rpm
,准确地说,删除前面插入的:
之前的尾随位(但不是冒号)
步骤3:
-e 's/AvamarClient-//'
从文件名的第一个副本中删除单词avamaclient-
步骤4:
-e 's/\./:/1' -e 's/\./:/1'
将仅提取的版本号中的
转换为:
例如:
ls -1 /ava/repo/AvamarClient-6.4.200-400-x86_64.rpm | sed -e 's/.*/&:&/' -e 's/-[0-9]*-x86_64[^:]*//1' -e 's/AvamarClient-//' -e 's/\./:/1' -e 's/\./:/1'
将输出:
6:4:200:AvamarClient-6.4.200-400-x86_64.rpm
6040200 AvamarClient-6.4.200-400-x86_64
AWK
现在,为了将提取的版本转换成神奇的东西,我们通过awk:where-F:
将上面的字符串拆分为:作为分隔符。所以$1=MAJ,$2=MIN,$3=REL,$4=Filename;例如,上面的值为$1=6$2 = 4; $3 = 200; $4=AvamaClient-6.4.200-400-x86_64.rpm
因此,我们应用我们的魔术公式,用awk打印文件名:
'{ print 1000000 * $1 + 10000 * $2 + $3 " " $4 }'
因此,对于上面的示例,它将输出:
6:4:200:AvamarClient-6.4.200-400-x86_64.rpm
6040200 AvamarClient-6.4.200-400-x86_64
瞧,我们有一个神奇的可比数字
排序和尾部
由于我们的回购协议中可能有多个文件,以上将是它们的列表,因为我们有神奇的数字,我们可以使用它来获得最新的一个。使用sort-n
进行排序,并使用tail-n1
获取最后一个(排序是升序)
因此,现在在AVAMAR_候选者中,我们将使用6040200 AvamaClient-6.4.200-400-x86_64
让我们让生活变得更轻松,并将其分为两个变量:
AVAMAR_CANDIDATE_FILE=$(echo $AVAMAR_CANDIDATE | cut -f2 -d' ')
AVAMAR_CANDIDATE_MAGIC=$(echo $AVAMAR_CANDIDATE | cut -f1 -d' ')
让我们对已安装的版本执行相同的操作:
AVAMAR_INSTALLED=$(rpm -qa | grep AvamarClient)
AVAMAR_INSTALLED_MAGIC=$(echo $AVAMAR_INSTALLED | \
sed -e 's/^AvamarClient-//' \
-e 's/-[0-9].*x86_64$//' \
-e 's/\./:/g' | \
awk -F: '{ print 1000000 * $1 + 10000 * $2 + $3 }' )
现在,您只需比较两个幻数的值:
if [ $AVAMAR_INSTALLED_MAGIC -lt $AVAMAR_CANDIDATE_MAGIC ] ; then
rpm -ivU /ava/repo/$AVAMAR_CANDIDATE_FILE
fi
我希望这能让您学习shell脚本,因为它是一个功能强大得惊人的工具。@LtWorf:首先,如果您有疑问,rpm版本控制可能不够聪明,无法确定是否应该更换它。另外,这个特殊的解决方案实际上是使用字符串比较,因此您的注释是不正确的。字符串比较不能像上面所示那样用于实际进行版本比较,因此上面的解决方案在6.4.200和8.0.300这样的示例中会失败,因为
elif
的逻辑失败。那么,在解决方案上是-1,在注释上是-1,为什么rpm不能解决这个问题呢?在debian dpkg上可以,所以我认为rpm应该类似。dpkg——比较版本1.2-3 gt 1.1-4