Linux-如何比较已安装的软件包版本通过shell脚本新安装

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

我正在尝试编写一个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-402.x86_64

  • 检查版本后,我需要将其与正在安装的版本进行比较。例如,如果我要添加的pkg(最新版本/ava/repo)是avamaclient-6.1.200-102.x86_64,我需要对照avamaclient-6.1.100-402.x86_6进行检查,并确定哪一个更新或是否相同
  • 如果我尝试安装的pkg是相同的,则输出到已安装pkg的日志文件并结束

    如果我尝试安装的pkg较旧,则已安装pkg的日志文件的输出较新且结束

    如果我尝试安装的pkg较新,请卸载旧的pkg,然后安装新的pkg,并输出到升级包的日志文件,然后结束

    我只有基本的外壳技能,所以这个任务对我来说很难!任何帮助都将不胜感激。
    谢谢

    您必须从安装的软件包中获取主版本号、次版本号和内部版本号。 同样地,您需要从尝试安装的软件包中了解主版本号、次版本号和内部版本号。 首先比较主要编号,然后比较次要编号,然后比较内部编号

    我已经写了我解释过的逻辑

    #!/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