如何可靠地获得操作系统的名称?


69

假设我已登录到远程系统,我如何知道它正在运行什么?在大多数现代Linux(Linuces?)上,您具有以下lsb_release命令:

$ lsb_release -ic    
Distributor ID: LinuxMint
Codename:       debian

据我所知,它给出的信息与相同/etc/lsb-release。如果该文件不存在怎么办?我似乎还记得该lsb_release命令是相对较新的,所以如果我必须获得旧系统的OS怎么办?

无论如何,lsb代表,Linux Standard Base所以我假设它不适用于非Linux Unices。据我所知,无法从中获取此信息,uname那么如何在不使用的系统上获取此信息lsb_release


1
unix.stackexchange.com/questions/6345/…适用于Linux。uname -s在Linux外部应该足够(可能需要BSD)。
马太福音

你检查了facter吗?facter operatingsystem应该可以在所有系统facter上正常工作。
约瑟夫

@JosephR。看起来不错,但默认情况下未安装。
terdon

1
facter将获取操作系统名称的代码粘贴到pastebin上。在这里找到它。它检查许多不同的文件以可靠地获取名称。
约瑟夫·R.

@JosephR。哇,有很多文件。如果有机会,我会把它移植到bash上,这应该足够便携。谢谢!
terdon

Answers:


72

lsb_release -a 可能是您找到此信息的最佳选择,并且能够以一致的方式做到这一点。

LSB的历史

lsb命令中的代表项目Linux Standards Base,该项目是Linux基金会赞助的伞形项目,旨在提供用于在各种Linux发行版上执行基本操作的通用方法。

该项目是自愿的,供应商可以作为用户参加该项目,也可以作为围绕不同模块的各种规范的促进者参与该项目,以帮助推动不同Linux发行版中的标准化。

宪章摘录

LSB工作组的核心目标是解决这两个问题。我们与主要的发行商协商后,发布了描述发行必须支持的最小API集的标准。我们还提供测试和工具,以衡量对标准的支持,并使应用程序开发人员可以针对通用集合。最后,通过我们的测试工作,我们试图防止分布之间不必要的差异。

与LSB相关的有用链接

批评

LSB存在许多问题,这些问题使Debian等发行版出现问题。RPM的强制使用为1。有关此问题的更多信息,请参见Wikipedia文章

Novell

如果您进行搜索,则可能会看到标题相当陈旧的页面:从Novell中检测底层Linux发行版。这是我见过的几个实际的列表之一,该列表显示了几个主要发行版以及如何检测所使用的基础发行版。

摘抄

Novell SUSE         /etc/SUSE-release
Red Hat             /etc/redhat-release, /etc/redhat_version
Fedora              /etc/fedora-release
Slackware           /etc/slackware-release, /etc/slackware-version
Debian              /etc/debian_release, /etc/debian_version,
Mandrake            /etc/mandrake-release
Yellow dog          /etc/yellowdog-release
Sun JDS             /etc/sun-release
Solaris/Sparc       /etc/release
Gentoo              /etc/gentoo-release
UnitedLinux         /etc/UnitedLinux-release
ubuntu              /etc/lsb-release

该页面还包含一个方便的脚本,该脚本尝试仅使用普通uname命令对上述内容进行整理,并提供上述文件之一。

注意:此列表已过时,但是您可以轻松地从列表中删除带有日期的发行版(例如Mandrake),并将其替换为替代版本。如果您尝试支持大量的Solaris和Linux变体,则这种类型的脚本可能是一种方法。

Linux黑手党

更多搜索将打开以下在Linuxmafia.com上维护的页面,标题为:/ etc / release相当于各式 Linux(和其他Unix)发行版的页面。这可能是迄今为止我所见过的最详尽的清单。您可以使用case / switch语句来整理此列表,并将其作为软件分发的一部分。

实际上,该页面底部有一个脚本可以完全做到这一点。因此,您可以简单地下载脚本并将其用作软件分发的第三方。

脚本

#!/bin/sh
# Detects which OS and if it is Linux then it will detect which Linux
# Distribution.

OS=`uname -s`
REV=`uname -r`
MACH=`uname -m`

GetVersionFromFile()
{
    VERSION=`cat $1 | tr "\n" ' ' | sed s/.*VERSION.*=\ // `
}

if [ "${OS}" = "SunOS" ] ; then
    OS=Solaris
    ARCH=`uname -p` 
    OSSTR="${OS} ${REV}(${ARCH} `uname -v`)"
elif [ "${OS}" = "AIX" ] ; then
    OSSTR="${OS} `oslevel` (`oslevel -r`)"
elif [ "${OS}" = "Linux" ] ; then
    KERNEL=`uname -r`
    if [ -f /etc/redhat-release ] ; then
        DIST='RedHat'
        PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//`
        REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
    elif [ -f /etc/SuSE-release ] ; then
        DIST=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//`
        REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //`
    elif [ -f /etc/mandrake-release ] ; then
        DIST='Mandrake'
        PSUEDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//`
        REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//`
    elif [ -f /etc/debian_version ] ; then
        DIST="Debian `cat /etc/debian_version`"
        REV=""

    fi
    if [ -f /etc/UnitedLinux-release ] ; then
        DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]"
    fi

    OSSTR="${OS} ${DIST} ${REV}(${PSUEDONAME} ${KERNEL} ${MACH})"

fi

echo ${OSSTR}

注意:此脚本应该看起来很熟悉,它是Novell版本的最新版本!

腿部脚本

我见过的另一种方法是滚动自己的脚本,类似于上面的Novell方法,但改用LSB。标题为“确定Linux(或UNIX)发行版本名称的通用方法”的本文介绍了一种这样的方法。

# Determine OS platform
UNAME=$(uname | tr "[:upper:]" "[:lower:]")
# If Linux, try to determine specific distribution
if [ "$UNAME" == "linux" ]; then
    # If available, use LSB to identify distribution
    if [ -f /etc/lsb-release -o -d /etc/lsb-release.d ]; then
        export DISTRO=$(lsb_release -i | cut -d: -f2 | sed s/'^\t'//)
    # Otherwise, use release info file
    else
        export DISTRO=$(ls -d /etc/[A-Za-z]*[_-][rv]e[lr]* | grep -v "lsb" | cut -d'/' -f3 | cut -d'-' -f1 | cut -d'_' -f1)
    fi
fi
# For everything else (or if above failed), just use generic identifier
[ "$DISTRO" == "" ] && export DISTRO=$UNAME
unset UNAME

可以将这段代码包含在系统/etc/bashrc或某些此类文件中,然后再设置环境变量$DISTRO

海湾合作委员会

信不信由你。另一种方法是利用gcc。如果查询该命令,gcc --version您将获得gcc为其构建的发行版,该发行版始终与所运行的系统相同。

软呢帽14

$ gcc --version
gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4)
Copyright (C) 2010 Free Software Foundation, Inc.

CentOS 5.x

$ gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-54)
Copyright (C) 2006 Free Software Foundation, Inc.

CentOS 6.x版

$ gcc --version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)
Copyright (C) 2010 Free Software Foundation, Inc.

Ubuntu 12.04

$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.

TL; DR;

那么我应该使用哪一个呢?我倾向于使用lsb_release -a我经常使用的任何Linux发行版(RedHat,Debian,Ubuntu等)。对于您支持不提供的系统的情况lsb_release,与上面的脚本之一类似,我会在提供的软件分发中投入自己的力量。

更新#1:SuSE的后续行动

通过在下面的评论中与@Nils进行交谈,可以确定,无论出于何种原因,SLES11似乎都会默认取消安装LSB。这只是一个可选安装,对于提供此类关键功能的软件包而言似乎是相反的。

因此,我借此机会与OpenSuSE项目的某人联系,以了解其原因。

电子邮件摘录

Hi Rob,

I hope you don't mind me contacting you directly but I found your info here: 
https://en.opensuse.org/User:Rjschwei. I participate on one of the StackExchange 
sites, Unix & Linux and a question recently came up regarding the best option 
for determining the underlying OS.

http://unix.stackexchange.com/questions/92199/how-can-i-reliably-get-the-operating-systems-name/92218?noredirect=1#comment140840_92218

In my answer I suggested using lsb_release, but one of the other users mentioned 
that this command wasn't installed as part of SLES11 which kind of surprised me. 
Anyway we were looking for some way to confirm whether this was intentionally 
dropped from SLES or it was accidental.

Would you know how we could go about confirming this one way or another?

Thanks for reading this, appreciate any help and/or guidance on this.

-Sam Mingolelli
http://unix.stackexchange.com/users/7453/slm

这是罗伯的回应

Hi,

On 10/01/2013 09:31 AM, Sam Mingo wrote:
- show quoted text -

lsb_release was not dropped in SLES 11. SLES 11 is LSB certified. However, it 
is not installed by default, which is consistent with pretty much every other
distribution. The lsb_release command is part of the lsb-release package.

At present almost every distribution has an entry in /etc such as 
/etc/SuSE-release for SLES and openSUSE. Since this is difficult for ISVs and 
others there is a standardization effort going on driven by the convergence to 
systemd. The standard location for distribution information in the future will 
be /etc/os-release, although Ubuntu will probably do something different.

HTH,    
Robert

--  Robert Schweikert                           MAY THE SOURCE BE WITH YOU    
SUSE-IBM Software Integration Center                   LINUX    
Tech Lead    
Public Cloud Architect 

1
注意:只是对使用AIX和SunOS的机器进行了快速检查。他们似乎没有安装lsb_release(毕竟,这是Unix而不是Linux堆栈)。gcc的问题是某些ppl现在开始使用clang。另外,您永远无法确定要使用哪个gcc构建(在我使用的系统上,每个版本至少有几个版本)。因此,我的投票投给了Python解决方案,因为默认情况下它似乎已安装在任何地方。
Elmo 2013年

@elmo-是的LSB是Linux Standard Base,所以我不希望AIX或SunOS拥有它。我在SunOS方面的经验超过15年,并且与我合作的软件的大多数供应商通常会提供与上面引用的外壳脚本相似的外壳脚本。在Solaris 11之前,不能选择使用Python。这就是使它难以破解的原因。如果您提供需要在Solaris 9、10、11,AIX和几个Linux发行版(SUSE,Ubntu和RHEL)上运行的软件,该怎么办?Python不是一个选择,因此您只剩下一个手工编码的Shell脚本。
slm

@elmo-虽然gcc是一个选项,但对我来说似乎也不那么吸引人。似乎有太多问题,我只是作为一种选择而演示。
slm

@elmo-查看该函数背后的代码hg.python.org/cpython/file/2.7/Lib/platform.py#l259。令人惊讶的是它正在使用LSB!
slm

@slm:我可以使用SunOS 5.10(我认为在您的列表中为10-我不太熟悉Sun的版本号/约定)使用计算机,并且确实具有Python。我可以使用AIX 7访问机器,并且它确实具有Python。Linux机器显然也有。因此,Python仍然是大多数可移植的选择。至于Sun低于10,我不确定为什么不允许安装Python(诚然,目前缺少ncurses和ctypes安装,所以知道)。对于使用LSB的Python,如果它是默认方法,对于Linux来说一点也不奇怪。
Elmo 2013年

16

由于您可能无法facter在远程服务器上进行安装,因此可以模仿其查找操作系统名称的作用。operatingsystem事实的Ruby代码可在pastebin上找到。基本上,它会浏览不同的*-release文件和其他文件来确定操作系统名称。

它查看的一些文件:

/etc/debian_version
/etc/gentoo-release
/etc/fedora-release
/etc/mandriva-release
/etc/mandrake-release
/etc/meego-release
/etc/arch-release
/etc/oracle-release
/etc/enterprise-release
/etc/ovs-release
/etc/vmware-release
/etc/redhat-release
/etc/SuSE-release
/etc/bluewhite64-version
/etc/slamd64-version
/etc/slackware-version
/etc/alpine-release
/etc/system-release
/etc/centos-release

很抱歉,如果您在此列表中发现重复项,我会用快速生成grep。将其移植到POSIX shell脚本应该相当容易(尽管有点乏味)。


5
“很抱歉,如果您在此列表中发现重复项,我会使用grep快速生成。” ... | uniq
13年

@ new123456对。谢谢。这里的关键词是“迅速” :)
Joseph R.

很抱歉无法接受,但是@slm的答案太全面了,无法忽略:)。
terdon

3
/ etc / os-release呢?
Yauhen Yakimovich 2014年

1
@ new123456从技术上讲,应该是... | sort -uuniq仅找到相邻的唯一元素。
Parthian Shot

9

如果已python安装(无论是Python 3还是Python 2都无关紧要),则无需重新发明轮子就可以找到发行版名称:

python -c "import platform;print(platform.linux_distribution()[0])"

如果您想使用此选项,请确保支持您的操作系统:hg.python.org/cpython/file/2.7/Lib/platform.py#l259。如果不是,您可以在列表中添加更多内容:coderwall.com/p/cwrenq
slm

1
这不适用于古代Linux发行版。例如:SuSE 7.0具有Python 1.5.2,并且在2003年Python 2.3出现之前未添加平台模块;-)
pefu

6

/etc/issue应该包含发布信息。我相当确定我已经在Solaris系统上看到它。这是现代Debian系统中的文件:

$ cat /etc/issue
Debian GNU/Linux 7 \n \l

$ 

尽管/ etc / issue 是“可选的”,但在FHS中也提到了/ etc / issue (不仅限于Linux系统)。


啊,这是个好建议,+ 1。尽管它可能并不总是有效,但这The file /etc/issue is a text file which contains a message or system identification to be printed before the login prompt.似乎取决于系统管理员写他/她想要的任何东西。
terdon

2
/etc/issue完全不可靠。(我见过XY版本的系统,上面贴着/etc/issue标语,说他们是由于补丁管理不当而成为YZ。它绝对可以包含任何内容。)
Mat

建议使用该文件。合法的内容,例如允许谁登录。
Nils 2013年

由安全准则和审核员推荐。在法律上曾经有一个案例,黑客在没有受到惩罚的情况下逃脱,因为/ etc / issue中有WELCOME
Nils 2013年

@drewbenn手册页说了我在第一条评论中所引用的内容,关于它是否需要包含系统信息并没有什么。它只是经常这样做。
terdon

6

您无法从所有发行版中的单个命令可靠地获得发行版名称。有些可通过/ etc / *-release获得,而另一些可通过'lsb-release'命令获得。


谢谢,但是对于Unix或任何其他非Linux * nix都没有帮助。
terdon

3

我使用此shell命令来获取一个指示Linux发行版的字符串:

for f in $(find /etc -type f -maxdepth 1 \( ! -wholename /etc/os-release ! -wholename /etc/lsb-release -wholename /etc/\*release -o -wholename /etc/\*version \) 2> /dev/null); do echo ${f:5:${#f}-13}; done;

该命令基于Joseph R.和slm的答案。

它仅查找/ etc / {osname} -release或/ etc / {osname} _version之类的文件并显示特定的os名称。

它在

  • CentOS(centos)
  • 红帽(redhat)
  • Debian(debian)
  • 拱(arch)
  • OpenSUSE(OpenSUSE)
  • 软呢帽(fedora)
  • Ubuntu(Debian)

不能for f in /etc/*{_version,...*-release}; do [ -f "$f" ] && echo ${f:5:${#f}-13} ; done对所有这些都同样有效吗?我不明白您为什么要首先将find所有文件放入/etc
terdon

感谢您的反馈,terdon,但您的命令至少在Cent OS和Fedora中给出了0行
scrutari 2014年


1

SNMP是一种无处不在的协议,因此可以在许多不同种类的GNU / Linux发行版和UNIX系统中找到。

SNMPv2-MIB中system.sysDescr.0对象可以帮助您找出要连接的操作系统,前提是目标系统中正在运行SNMP守护程序:

描述

实体的文字描述。该值应包括系统硬件类型,软件操作系统和网络软件的全名和版本标识。

状态:当前

访问:只读

手册snmpget(1)页通过示例说明了如何检索此值。


缺点是这是不会自动维护的静态字符串。
Nils 2013年

1

由于没有通用的方法,因此我们通过snmp exec-command定义了发布字符串。

该命令的任务是打印发行版和当前的主要/次要版本的操作系统。

在RH和克隆上,我们在SuSe SuSe-release上解析/ etc / redhat-release ...


谁是“我们”?那Unix呢?
terdon

@terdon,我们是我们的工作团队。在Unix上,如果将相应的扩展名编译为snmpd,则可以执行相同的操作。
Nils 2013年

啊,我以为你是某个标准组织的一部分:)
terdon

@terdon当您必须管理80台以上服务器时,便开始制定站点标准。我们开发了此方法,以便可以监视os是否已过时(EoL次要或什至是主要数量)
Nils 2013年

1

根据我设法从该线程中收集的信息,您应该能够使用以下命令从该死的任何系统附近获取信息:

if which lsb_release &>> /dev/null; then
    lsb_release -a
elif [ -r /etc/issue ]; then
    cat /etc/issue
else
    ls /etc/ | grep -e '[_-]release$' -e '[_-]version$' | xargs -I % -n 1 cat /etc/%
fi

2
不要解析ls的输出!
heinrich5991

@ heinrich5991为什么不呢?
Sammitch

从技术上讲,他不解析的输出ls。他正在对的输出进行词法ls。但是,是的。。。这是错误的,因为/etc/issue它完全不可靠。完全,完全,完全不可靠。同样,您认为没有人可以放置与“ os”无关的文件以“ release”或“ version”结尾的假设是不明智的。
Parthian Shot

@ParthianShot因此,如果没有更可靠的选项可用,主要是您想抱怨第二和第三级回退吗?
Sammitch '16

@Sammitch more reliable options好吧,一方面,只有一种选择。因此,即使假设我同意您的假设(它不是更可靠),我们也不要开始将事情多元化。其次,如果有人实际使用了您的解决方案,但该解决方案完全失败了一半,那么就不会因“ else if”失败而受挫。lsb默认情况下,我的系统均未安装。
Parthian Shot

1

如果情况需要,您可以使用snmpwalk [或SNMP协议]进行远程查找。下面是一个示例:

snmpwalk -Os -c <snmp community string> -v1 <hostname> sysDescr.0

输出:sysDescr.0 =字符串:Linux example.hostname.com 2.6.32-358.23.2.el6.x86_64#1 SMP Sat Sep 14 05:32:37 EDT 2013 x86_64

可靠性的关键是在您的环境中是否正确设置了SNMP,所有主机均使用正确的社区字符串设置运行了snmp。


什么snpwalk啊 在哪里可以找到它?另外,它仅显示“ Linux”,没有分发信息(这是我想要的,uname可以提供给我Linux)。它可以在非Linux操作系统上运行吗?在UNIX上说,还是BSD或OSX?
terdon

snmpwalk是Linux命令行实用程序。它不仅打印“ Linux”,还打印内核版本,这实际上是您唯一需要的东西。如果在其他主机上配置了SNMP,则无论它是UNIX,BSD,OSX,snmpwalk都可以按标准(v1 | v2c | v3)正常运行,甚至可以在Windows主机上正常运行。另请参见snmpget或snmpgetnext。
xpros

听起来不错,但请您编辑答案并解释我们在哪里可以找到它。例如,这不是Debian仓库的意思。另外,请解释一下它给出的内容,uname -a以及它如何告诉我该问题所针对的发行版的名称。无论如何,即使假设它可以返回此信息,并且由于它是非标准实用程序并且需要安装,我也不知道它在这里是否有用。这个想法是登录到远程系统并找出操作系统(如果是Linux,则包括发行版)。
terdon

it also prints the kernel version which is really the only thing you need但这就是这个问题的全部重点。如果这确实是您所需要的,则可以使用uname -a。内核是操作系统的重要组成部分,但不是整个操作系统。文件系统布局和用户态实用程序(例如,程序包管理器)很重要。
Parthian Shot

1

用途/etc/os-release

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.10 (Cosmic Cuttlefish)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.10"
VERSION_ID="18.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=cosmic
UBUNTU_CODENAME=cosmic

该问题在FAQ中通过@weberjn此注释中免费提供的链接http://0pointer.de/blog/projects/os-release.html进行了很好的解释。我在这里仅列出一个反对使用的论点,这是迄今为止2013年最受好评的答案。lsb_release

已经有了lsb_release工具,为什么不只使用它呢?嗯,这是一个非常奇怪的接口:您必须调用一个shell脚本(并因此从您的C代码异步生成),并且该脚本不是可扩展的。它是许多发行版中的可选软件包,没有任何我们愿意在早期启动时调用以显示欢迎消息的东西。(在用户空间启动时间不到一秒的时间内,我们真的不想为了显示琐碎的内容而调用巨大的shell脚本,例如显示欢迎消息)。我们发现的lsb_release工具似乎是对分发检查进行抽象的尝试,其中需要对分发检查进行标准化。这只是一个设计不良的界面。我们认为,它可以用作确定LSB版本本身的接口,但不能用于检查发行版本或版本。


谢谢,但是最后被引用的答案已经解决了这一点,这说明它将/etc/os-release变得更加标准。但是,该文件并不总是在所有系统上都存在,这就是为什么公认的答案提供了更多可移植的替代方案的原因。另外,我不知道为什么你提的C代码,这个问题是不是从C调用任何东西
terdon

@terdon我只是很好奇2018年哪些系统/etc/os-release不存在?我猜他们的用户群与lsb_release默认情况下未交付的系统相比是痛苦的。至少我无法在Fedora上使用您接受的答案。至于C注释,这不是我的,而是systemd我提供的0pointer.de链接的引号。
anatoly techtonik '18

是的,我知道这不是您的,我只是想知道为什么您觉得有关C代码的引用很重要。据我所知,os-release主要还是专门用于Linux。它似乎是由FreeDesktop.org 定义的,所以也许某些Unix风格也可以使用它,但是我怀疑您会在大多数系统,嵌入式系统或任何非GUI系统等中找到它。最后,不要忘记很多地方为了稳定起见,仍然使用非常旧的机器。
terdon

引号是关于lsb_release,您可以用Go替换C并获得相同的参数。lsb_release从安全性和性能角度来看,运行的开销要比仅解析静态文件高得多。我不相信提供稳定性的旧机器。Heartbleed和朋友应该早就把它们带走了,所以就使用吧/etc/os-release
anatoly techtonik 18-11-10
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.