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

Ali*_*xel 231 linux shell-script distributions

我正在开发一个简单的 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
Run Code Online (Sandbox Code Playgroud)

似乎有效,返回ubuntucentos(我没有尝试过其他人)作为发布名称。但是,我有一种感觉,必须有一种更简单、更可靠的方法来解决这个问题——这是真的吗?

它不适用于 RedHat。/etc/redhat-release 包含:Redhat Linux 企业版 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"
Run Code Online (Sandbox Code Playgroud)

Mik*_*kel 233

要得到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
Run Code Online (Sandbox Code Playgroud)

我认为uname得到ARCH仍然是最好的方法。但是你给出的例子显然只处理英特尔系统。我要么这样称呼它BITS

case $(uname -m) in
x86_64)
    BITS=64
    ;;
i*86)
    BITS=32
    ;;
*)
    BITS=?
    ;;
esac
Run Code Online (Sandbox Code Playgroud)

或者更改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
Run Code Online (Sandbox Code Playgroud)

但当然这取决于你。

  • 不要使用`$OS`、`$VERSION` 等——按照惯例,我们将环境变量(PAGER、EDITOR、SHELL、...)和内部shell 变量(BASH_VERSION、RANDOM、...)大写。所有其他变量名称应至少包含一个小写字母。此约定可避免意外覆盖环境和内部变量。 (7认同)
  • 刚刚在虚拟机中安装了 Fedora 14,没有你所说的 `lsb-release`。 (3认同)
  • 我会检查 lsb_release 并在可用时使用它,但它并非随处可用。例如,它不在 Fedora 14 的默认安装中。 (2认同)

Mat*_*Mat 66

我会用这个作为第一步:

ls /etc/*release
Run Code Online (Sandbox Code Playgroud)

Gentoo、RedHat、Arch 和 SuSE 有一个名为例如/etc/gentoo-release. 似乎很流行,请查看有关release-files 的站点。

Debian 和 Ubuntu 也应该有一个/etc/lsb-release包含发布信息的,并且会显示上一个命令。

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

  • 难道`uname -rv` 不包含信息吗?`uname -a` 将打印在这里无关的处理器类型和主机名等内容。(但是内核版本(`-r`)和版本(`-v`)都是必需的,并非所有发行版都这样做) (3认同)

sak*_*isk 39

lsb_release -a. 适用于 Debian,我猜是 Ubuntu,但我不确定其余的。通常它应该存在于所有 GNU/Linux 发行版中,因为它与 LSB(Linux 标准基础)相关。

  • Gentoo 默认没有安装它。在某些时候,它在 Fedora 上也不是默认的(但现在可能是) (3认同)
  • lsb_release 不是 CentOS 6 最小安装的一部分。 (3认同)
  • 这适用于 Debian 挤压、Fedora 14 和 OpenSUSE 11.3。在 Debian 和 SUSE 上,包含 lsb_release 的包是 lsb-release,在 Fedora 上是 redhat-lsb。它已经安装在 Debian 和 SUSE 上,但没有安装在 Fedora 上。我认为这是迄今为止最好的答案。+1。 (2认同)
  • *lsb_release -a* 在 Raspberry 上使用 [Raspbian](http://en.wikipedia.org/wiki/Raspbian) 返回“-bash: lsb_release: 命令未找到” ([Debian](http://en.wikipedia. org/wiki/Debian)7.1 派生)。 (2认同)

小智 30

一行,回退,一行输出,没有错误。

( lsb_release -ds || cat /etc/*release || uname -om ) 2>/dev/null | head -n1
Run Code Online (Sandbox Code Playgroud)

  • 杰出的!为什么这么好的答案不在最上面? (2认同)

Ily*_*mov 16

python -m platform
Run Code Online (Sandbox Code Playgroud)

示例输出:

Ubuntu:

Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic
Run Code Online (Sandbox Code Playgroud)

Debian:

Linux-4.14.117-grsec-grsec+-x86_64-with-debian-buster-sid
Run Code Online (Sandbox Code Playgroud)

Centos:

Linux-3.10.0-957.1.3.el7.x86_64-x86_64-with-centos-7.6.1810-Core
Run Code Online (Sandbox Code Playgroud)

Mac OS X:

Darwin-17.7.0-x86_64-i386-64bit
Run Code Online (Sandbox Code Playgroud)

如果您需要该行中的特定值,请参阅平台模块文档。例如,如果您只需要 Linux 发行版名称,请使用

python -c "import platform;print(platform.linux_distribution()[0])"
Run Code Online (Sandbox Code Playgroud)


小智 7

  1. 在基本 CentOS 或 Debian 系统上未安装/不存在lsb-*
  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 AmigaOS, CPM, and modified cable modems.
     ;;
esac
}
Run Code Online (Sandbox Code Playgroud)

  • Yum 很可能是 Red Hat、Scientific Linux 或 Fedora。Fedora 有一个模仿 Debian 的 apt 命令。等等。只需用 yum 分类任何东西,因为 CentOS 为您提供了一系列受支持的系统,从 Red Hat 4 到 Fedora 18,这是 Linux 大约 8 年的历史。如果您需要知道是否支持 &lt;foo&gt;,请专门检查 &lt;foo&gt; 而不是基于(不可靠的)分布标识进行猜测!当然,它会导致类似 autotools 的东西,但这无济于事(感谢 $DEITY Unix 战争已经结束)。 (7认同)

Eel*_*vex 6

按照最有可能成功的顺序,这些:

cat /etc/*version
cat /proc/version #linprocfs/version for FreeBSD when "linux" enabled
cat /etc/*release
uname -rv
Run Code Online (Sandbox Code Playgroud)

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


Chr*_*aes 6

对于大多数现代 Linux 操作系统系统,该文件/etc/os-release确实正在成为标准,并已包含在大多数操作系统中。因此,在您的 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
Run Code Online (Sandbox Code Playgroud)