首页 > 解决方案 > 如何在 perl 中列出内核的最高版本

问题描述

在许多 docker 容器中, le /boot 是空的。虽然,vmlinuz 在 /var/lib/modules/<kver>/vmlinuz 中可用

在 shell 中,我可以这样做:

for kver in $(ls /lib/modules|sort -Vr)
do
    test -f /lib/modules/$kver/vmlinuz && echo $kver && break
done

我怎样才能以可靠的方式做到这一点(我的意思是:使用 CentOS-6 到 CentOS-8 或任何其他 Linux 发行版中存在的模块。

我已经看到用于内核版本比较或版本排序的模块,但在 CentOS 的所有发行版中,从 6 到 8 都没有作为发行包可用(8 很重要,因为它是 RHEL-8 和 RHEL-8 的克隆非常重要剥离有关 perl 软件包的发行版)。

如果我有这 2 个版本: 4.18.0-144.el8.x86_64 4.18.0-80.7.1.el8_0.x86_64 我需要选择 -144 一个。

标签: perlsortingkernelversion

解决方案


最简单的方法是使用Sort::Versions模块(您需要从 CPAN 安装)。

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use Sort::Versions;
use File::Basename;

for (sort { versioncmp($b, $a) } glob '/lib/modules/*') {
  my $ver = basename $_;
  if (-e "/lib/modules/$ver/vmlinuz") {
    say $ver;
    last;
  }
}

更新:您的问题包括:

我已经看到用于内核版本比较或版本排序的模块,但在 CentOS 的所有版本(包括 6 到 8)中都没有作为发行包提供

当然,包不是安装 CPAN 模块的唯一方法。你总是可以使用cpanor cpanm。但是,如果您真的不想以这种方式安装模块,那么您也可以将versioncmp()子例程剪切并粘贴到您的代码中。它只有几十行代码。

sub versioncmp ($$) {
    my @A = ($_[0] =~ /([-.]|\d+|[^-.\d]+)/g);
    my @B = ($_[1] =~ /([-.]|\d+|[^-.\d]+)/g);

    my ($A, $B);
    while (@A and @B) {
        $A = shift @A;
        $B = shift @B;
        if ($A eq '-' and $B eq '-') {
            next;
        } elsif ( $A eq '-' ) {
            return -1;
        } elsif ( $B eq '-') {
            return 1;
        } elsif ($A eq '.' and $B eq '.') {
            next;
        } elsif ( $A eq '.' ) {
            return -1;
        } elsif ( $B eq '.' ) {
            return 1;
        } elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) {
            if ($A =~ /^0/ || $B =~ /^0/) {
                return $A cmp $B if $A cmp $B;
            } else {
                return $A <=> $B if $A <=> $B;
            }
        } else {
            $A = uc $A;
            $B = uc $B;
            return $A cmp $B if $A cmp $B;
        }       
    }
    @A <=> @B;
}

推荐阅读