如何在简单的Shell脚本中获取发行名称和版本号?


191

我正在研究一个简单的bash脚本,该脚本应该能够在Ubuntu和CentOS发行版上运行(对Debian和Fedora / RHEL的支持将是一个加号),我需要知道脚本正在运行的发行版的名称和版本(以触​​发特定操作,例如创建存储库)。到目前为止,我所得到的是:

OS=$(awk '/DISTRIB_ID=/' /etc/*-release | sed 's/DISTRIB_ID=//' | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')
VERSION=$(awk '/DISTRIB_RELEASE=/' /etc/*-release | sed 's/DISTRIB_RELEASE=//' | sed 's/[.]0/./')

if [ -z "$OS" ]; then
    OS=$(awk '{print $1}' /etc/*-release | tr '[:upper:]' '[:lower:]')
fi

if [ -z "$VERSION" ]; then
    VERSION=$(awk '{print $3}' /etc/*-release)
fi

echo $OS
echo $ARCH
echo $VERSION

似乎有效,返回ubuntucentos(我没有尝试过其他版本)作为发行名称。但是,我感觉必须找到一种更简单,更可靠的方法来找到答案-是这样吗?

它不适用于RedHat。/ etc / redhat-release包含:Redhat Linux Entreprise 5.5版

因此,版本不是第三个字,您最好使用:

OS_MAJOR_VERSION=`sed -rn 's/.*([0-9])\.[0-9].*/\1/p' /etc/redhat-release`
OS_MINOR_VERSION=`sed -rn 's/.*[0-9].([0-9]).*/\1/p' /etc/redhat-release`
echo "RedHat/CentOS $OS_MAJOR_VERSION.$OS_MINOR_VERSION"

您确定+-release可行吗?实际上,您正在假设它会是/etc/lsb-release,所以也许就这样称呼它。
Mikel

@Mikel:我换成*+避免评论格式化,它应该是etc/*-release,它似乎工作。
Alix Axel

8
切勿引入语法错误来正确设置格式。此外,格式化仅在预览中是错误的,最终视图从标记中提取语法。
Gilles

为什么没人提到此功能uname -rv | grep -i "name_of_distro"并使用退出代码?
逃亡者

Answers:


182

为了得到OSVER,最新的标准似乎是/etc/os-release。在此之前,还有lsb_release/etc/lsb-release。在此之前,您必须为每个发行版寻找不同的文件。

这是我的建议

if [ -f /etc/os-release ]; then
    # freedesktop.org and systemd
    . /etc/os-release
    OS=$NAME
    VER=$VERSION_ID
elif type lsb_release >/dev/null 2>&1; then
    # linuxbase.org
    OS=$(lsb_release -si)
    VER=$(lsb_release -sr)
elif [ -f /etc/lsb-release ]; then
    # For some versions of Debian/Ubuntu without lsb_release command
    . /etc/lsb-release
    OS=$DISTRIB_ID
    VER=$DISTRIB_RELEASE
elif [ -f /etc/debian_version ]; then
    # Older Debian/Ubuntu/etc.
    OS=Debian
    VER=$(cat /etc/debian_version)
elif [ -f /etc/SuSe-release ]; then
    # Older SuSE/etc.
    ...
elif [ -f /etc/redhat-release ]; then
    # Older Red Hat, CentOS, etc.
    ...
else
    # Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
    OS=$(uname -s)
    VER=$(uname -r)
fi

我认为uname得到ARCH仍然是最好的方法。但是您给出的示例显然仅适用于Intel系统。我可以这样称呼它BITS

case $(uname -m) in
x86_64)
    BITS=64
    ;;
i*86)
    BITS=32
    ;;
*)
    BITS=?
    ;;
esac

或改变ARCH是比较常见的,但明确的版本:x86x64或类似:

case $(uname -m) in
x86_64)
    ARCH=x64  # or AMD64 or Intel64 or whatever
    ;;
i*86)
    ARCH=x86  # or IA32 or Intel32 or whatever
    ;;
*)
    # leave ARCH as-is
    ;;
esac

但是,这完全取决于您。


2
我将检查lsb_release并使用它(如果可用),但它并非在所有地方都可用。例如,它是不是在默认的Fedora 14的安装
史蒂芬d

真?您是否尝试使用-和拼写_?也许是在这样的/lib/lsb地方。什么rpm -qa "lsb*"打印?
Mikel,

1
rpm -qa "lsb*什么都不打印。据称,yum provides */lsb_release它包含在名为redhat-lsb的软件包中,我估计默认情况下未安装该软件包。但是,我不是Fedora专家,这些只是我拥有的随机Fedora VM的结果,可能是非常错误的。
史蒂文D

3
正如lsb-release您所说,仅将Fedora 14安装在VM中,但没有。
Mikel

5
不要使用$OS$VERSION等等-按照惯例,我们将环境变量(PAGER,EDITOR,SHELL等)和内部外壳变量(BASH_VERSION,RANDOM等)大写。所有其他变量名称应至少包含一个小写字母。该约定避免了意外覆盖环境和内部变量。
克里斯·唐纳

58

我将以此作为第一步:

ls /etc/*release

Gentoo,RedHat,Arch和SuSE有一个名为eg的文件/etc/gentoo-release。似乎很流行,请在此站点上查看release-files

Debian和Ubuntu应该也有一个/etc/lsb-release包含发行信息的,并且将与前面的命令一起显示。

另一个快速的是uname -rv。如果安装的内核是股票发行版内核,通常您有时会在其中找到名称。


在Debian上,那就是uname -a
tshepang 2011年

2
虽然不uname -rv包含信息?uname -a将打印与此处无关的内容,例如处理器类型和主机名。(但两者的内核版本(-r)和版本(-v)是必要的,不是所有的发行版做有相同)

使用uname -r给人2.6.32-5-686-bigmemUNAME -v给出了#1 SMP Tue Mar 8 22:14:55 UTC 2011Debian的6 UNAME -a OTOH给出Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux
tshepang 2011年

的第二部分uname -a-n,即nodename == hostname。所以我想uname在Debian上不会很有趣。想一想,我不确定它在RedHat上是否有用。

哦好的。幸运的是,我将主机名设置为默认值debian
tshepang 2011年

36

lsb_release -a。可以在Debian上运行,我想是Ubuntu,但是我不确定其余的事情。通常它应该存在于所有GNU / Linux发行版中,因为它与LSB(Linux标准库)相关。


3
Gentoo默认未安装它。在某些时候,Fedora上也没有默认设置(可能现在是)
Mat Mat

2
这适用于Debian压缩,Fedora 14和OpenSUSE 11.3。在Debian和SUSE上,包含lsb_release的软件包是lsb-release,在Fedora上是redhat-lsb。它已经安装在Debian和SUSE上,但未安装在Fedora上。我认为这是迄今为止最好的答案。+1。
Faheem Mitha

3
lsb_release不是CentOS 6最小安装的一部分。
2013年

1
lsb_release -a在具有Raspbian(源自Debian 7.1)的Raspberry上返回“ -bash:lsb_release:未找到命令” 。
Peter Mortensen 2014年

lsb_release -a适用于Red Hat Enterprise Linux Server 6.6版(圣地亚哥)
jwilleke,2015年

21

一线,后备,一行输出,没有错误。

lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om

美丽,谢谢。请注意,这在Mac OS X上仍然不起作用,但在Ubuntu和CentOS(我方便使用的三个)上也可以正常工作。
2015年

2
辉煌!为什么没有这样一个令人满意的答案呢?


9
  1. lsb- * 未安装/不存在基本CentOS或Debian系统上
  2. / proc / * 在OSX上不存在

从javascript开发人员那里获取提示。不要测试版本,请测试功能。它不漂亮,但是可以用。根据需要展开。

function os_type
{
case `uname` in
  Linux )
     LINUX=1
     which yum && { echo centos; return; }
     which zypper && { echo opensuse; return; }
     which apt-get && { echo debian; return; }
     ;;
  Darwin )
     DARWIN=1
     ;;
  * )
     # Handle AmgiaOS, CPM, and modified cable modems here.
     ;;
esac
}  

6
百胜很可能是Red Hat,Scientific Linux或Fedora。对于Fedora模仿Debian的命令有一个适当的命令。等等。只需用yum修饰任何东西,CentOS就会为您提供从Red Hat 4到Fedora 18的一系列受支持的系统,这就是大约8年的Linux历史。如果您需要知道是否支持<foo>,请专门检查<foo>而不是根据(不可靠的)分发标识进行猜测!当然,这会导致大量的自动工具,但这无济于事(只不过感谢$ DEITY Unix之战已经结束)。
vonbrand

正如您所说的,@ vonbrand确实如此。我不会尝试区分不同口味。尽管我并没有做很多研究,但我签入的顺序(希望能)消除了大多数棘手的情况(安装了apt-get的RHEL)。如果RHEL可以安装apt-get,而Ubuntu用户则非常好...那么,您真是运气不佳。
Orwellophile

6

为了获得最大可能的成功,这些措施包括:

cat /etc/*version
cat /proc/version #linprocfs/version for FreeBSD when "linux" enabled
cat /etc/*release
uname -rv

涵盖大多数情况(AFAIK):Debian,Ubuntu,Slackware,Suse,Redhat,Gentoo,* BSD以及其他。


cat /etc/*version在CentOS(至少在6.4上)上不起作用(没有这样的文件)
om-nom-nom

如果在容器中运行该命令,则/ proc / version将包含HOST发行版本,而不是容器发行版本。
Dereckson

5

对于大多数现代Linux OS系统,该文件/etc/os-release实际上已成为标准文件,并且已包含在大多数OS中。因此,在您的Bash脚本中,您只需包含文件,就可以访问此处描述的所有变量(例如:NAME,VERSION等)

所以我只是在我的Bash脚本中使用它:

if [ -f /etc/os-release ]
then
        . /etc/os-release
else
        echo "ERROR: I need the file /etc/os-release to determine what my distribution is..."
        # If you want, you can include older or distribution specific files here...
        exit
fi

3

如果文件/etc/debian_version存在,则发行版为Debian或Debian衍生产品。该文件可能具有发行号;在我的机器上,当前6.0.1。如果正在测试或不稳定,则可能表示正在测试/不稳定,或者可能包含即将发布的版本号。我的印象是,至少在Ubuntu上,此文件始终处于测试/不稳定状态,并且他们没有在其中输入发行号,但是如果我错了,可以有人纠正我。

Fedora(至少是最新版本)具有类似的文件,即/etc/fedora-release


较新的Debian版本使用/ etc / os-release。
Dereckson

1
@Dereckson我检查了我的喘息机,它同时具有/etc/debian_version/etc/os-release
Faheem Mitha

在用debootstrap创建的Jessie chroot中进行了测试。但是确实,同样位于杰西(Jessie)下的本地计算机,这次以一种更常规的方式安装,包含一个/etc/debian_version文件。因此,我们准备Debian安装的方式可能会影响可用的发行文件,这很有趣。
Dereckson

Debian os-release不包含的完整版本号debian_version。参见unix.stackexchange.com/questions/382531
JdeBP '17


1

两种方式:

1)使用

lsb_release -a

我在CentOS 5.5和Ubuntu 10.04上进行了测试

CentOS的输出是:

LSB Version:    :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch 
Distributor ID: CentOS
Description:    CentOS release 5.5 (Final)
Release:        5.5
Codename:       Final

对于Ubuntu,是:

LSB Version:    :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch
Distributor ID: CentOS
Description:    CentOS release 5.5 (Final)
Release:        5.5
Codename:       Final

2)输入以下命令:

cat /etc/*-release

我在CentOS 5.5和Ubuntu 10.04上对其进行了测试,并且工作正常。


lsb_release不在CentOS 6中(最小安装速度)
编码器

lsb_release -a在具有Raspbian(源自Debian 7.1)的Raspberry上返回“ -bash:lsb_release:未找到命令” 。
Peter Mortensen 2014年

0

该脚本适用于Debian,(可能需要在Ubuntu上进行一些调整)

#!/usr/bin/env bash

echo "Finding Debian/ Ubuntu Codename..."

CODENAME=`cat /etc/*-release | grep "VERSION="`
CODENAME=${CODENAME##*\(}
CODENAME=${CODENAME%%\)*}

echo "$CODENAME"
# => saucy, precise, lucid, wheezy, squeeze

0

这是我简单的chech_distro版本。^^;

#!/usr/bin/env bash
check_distro2(){
    if [[ -e /etc/redhat-release ]]
    then
      DISTRO=$(cat /etc/redhat-release)
    elif [[ -e /usr/bin/lsb_release ]]
    then
      DISTRO=$(lsb_release -d | awk -F ':' '{print $2}')
    elif [[ -e /etc/issue ]]
    then
      DISTRO=$(cat /etc/issue)
    else
      DISTRO=$(cat /proc/version)
    fi
    }

    check_distro2
    echo $DISTRO

0

没有版本,只有dist:

cat /etc/issue | head -n +1 | awk '{print $1}'

Yahya Yahyaoui一年前的回答也是如此。实际上,这两个答案都在2011年被解决,此后已被删除。他们错误的原因仍然适用。
JdeBP '17

0

这已在Ubuntu 14和CentOS 7上进行了测试

cat /etc/os-release | grep "PRETTY_NAME" | sed 's/PRETTY_NAME=//g' | sed 's/["]//g' | awk '{print $1}'

@don_crissti你会怎么做?
BsdHelper

sed -n -e '/PRETTY_NAME/ s/^.*=\|"\| .*//gp' /etc/os-release
cas

@cas非常好!将其添加到我的工具箱中。感谢你的分享。
BsdHelper

0

从这里找到了一个适用于大多数常见Linux发行版的好的脚本:

#! /bin/bash
# return an awkable string consisting of
#    unix OS type, or
#    Linux dist, or
#    a long guess (based on /proc), or
#    no clue

giveUp () {
   echo "Unknown"
   exit 0
}

# keep this easily awkable, prepending an initial clue
versionGuess () {
   if [ -e /proc/version ]; then
      echo -n "Unsure "
      cat /proc/version
      exit 0
   fi
   return 1
}

# if we have ignition, print and exit
gotDist () {
   [ -n "$1" ] && echo "$1" && exit 0
}

# we are only interested in a single word "dist" here
# various malformations can occur; admin will have to code appropately based on output
linuxRelease () {
   if [ -r /etc/lsb-release ]; then
      dist=$(grep 'DISTRIB_ID' /etc/lsb-release | sed 's/DISTRIB_ID=//' | head -1)
      gotDist "$dist"
   fi

   dist=$(find /etc/ -maxdepth 1 -name '*release' 2> /dev/null | sed 's/\/etc\///' | sed 's/-release//' | head -1)
   gotDist "$dist"

   dist=$(find /etc/ -maxdepth 1 -name '*version' 2> /dev/null | sed 's/\/etc\///' | sed 's/-version//' | head -1)
   gotDist "$dist"

   return 1
}

# start with uname and branch the decision from there
dist=$(uname -s 2> /dev/null)
if [ "$dist" = "Linux" ]; then
   linuxRelease
   versionGuess
   giveUp
elif [ -n "$dist" ]; then
   echo "$dist"
   exit 0
else
   versionGuess
   giveUp
fi

# we shouldn't get here
giveUp
# done


0

有一个facter红宝石的宝石,它为您提供有关操作系统OS的一些事实,分析了OS版本文件,其它数据,并打印到终端屏幕。您可以尝试如下,从rubygems安装开始:

# apt-get install rubygems

请使用适合您的操作系统的上述情况。然后安装gem本身。

# gem install facter

然后使用:

$ facter

注意:请参阅事实gem资源以获取更多安装信息。


0

如果有人也需要发行版:

#!/usr/bin/env bash

LINUX_VERSION_NAME=`lsb_release -sr`


# Distribution specific installation
if [[ ${LINUX_VERSION_NAME} == "18.04" ]]
then
    echo "It is: ${LINUX_VERSION_NAME}"

else
    echo "It is not ${LINUX_VERSION_NAME}"
fi

输出:

It is: 18.04

更改为:lsb_release -sc以获取发行版:

LINUX_VERSION_NAME=`lsb_release -sc`


# Distribution specific installation
if [[ ${LINUX_VERSION_NAME} == "bionic" ]]
then
    echo "It is: ${LINUX_VERSION_NAME}"

else
    echo "It is not ${LINUX_VERSION_NAME}"
fi

输出:

It is: bionic

-3

此命令适用于基于Debian和基于Redhat的发行版:使用tr过滤器,将文档转换为每行一个单词的格式,然后计算包含发行版名称的第一行。

tr -s ' \011' '\012' < /etc/issue | head -n 1

关于2011年已删除答案的评论也是如此。放错了位置的答案也是如此,现在又删除了,它说/etc/issue在zenwalk上不包含版本或名称。这是一个管理员可修改的文件,其中包含呈现给人类的消息,不能保证包含任何可以以编程方式提取的消息。
JdeBP '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.