Làm cách nào tôi có thể nhận được tên phân phối và số phiên bản trong tập lệnh shell đơn giản?


191

Tôi đang làm việc với một tập lệnh bash đơn giản có thể chạy trên các bản phân phối Ubuntu và CentOS (hỗ trợ cho Debian và Fedora / RHEL sẽ là một điểm cộng) và tôi cần biết tên và phiên bản phân phối mà tập lệnh đang chạy ( để kích hoạt các hành động cụ thể, ví dụ như việc tạo các kho lưu trữ). Cho đến nay những gì tôi có là đây:

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

Điều này dường như hoạt động, trở lại ubuntuhoặc centos(tôi chưa thử người khác) làm tên phát hành. Tuy nhiên, tôi có cảm giác rằng phải có một cách dễ dàng hơn, đáng tin cậy hơn để tìm ra điều này - điều đó có đúng không?

Nó không hoạt động cho RedHat. / etc / redhat-phát hành có chứa: Redhat Linux Entreprise phát hành 5.5

Vì vậy, phiên bản không phải là từ thứ ba, bạn nên sử dụng tốt hơn:

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"

Bạn có chắc chắn +-releaselàm việc? Thực tế, bạn đang tìm kiếm giả định nó sẽ /etc/lsb-releasenhư vậy, vì vậy có lẽ chỉ cần gọi nó như vậy.
Mikel

@Mikel: Tôi thay thế *với +để tránh Formating bình luận, nó phải là etc/*-release, có vẻ như để làm việc.
Alix Axel

8
Không bao giờ giới thiệu một lỗi cú pháp để có được định dạng đúng. Bên cạnh đó, định dạng chỉ sai trong phần xem trước, chế độ xem cuối cùng chọn cú pháp từ các thẻ.
Gilles

Tại sao không ai đề cập đến điều này uname -rv | grep -i "name_of_distro"và sử dụng mã thoát?
chạy trốn

Câu trả lời:


182

Để có được OSVER, tiêu chuẩn mới nhất dường như là /etc/os-release. Trước đó, đã có lsb_release/etc/lsb-release. Trước đó, bạn phải tìm các tệp khác nhau cho mỗi bản phân phối.

Đây là những gì tôi muốn đề xuất

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

Tôi nghĩ unameđể có ARCHđược vẫn là cách tốt nhất. Nhưng ví dụ bạn đưa ra rõ ràng chỉ xử lý các hệ thống Intel. Tôi sẽ gọi nó BITSnhư thế này:

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

Hoặc thay đổi ARCHthành phiên bản phổ biến hơn nhưng rõ ràng hơn: x86x64tương tự:

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

nhưng tất nhiên điều đó tùy thuộc vào bạn.


2
Tôi sẽ kiểm tra lsb_release và sử dụng nó nếu có, nhưng nó không có sẵn ở mọi nơi. Chẳng hạn, nó không có trong bản cài đặt mặc định của Fedora 14.
Steven D

Có thật không? Bạn đã thử đánh vần nó với -_? Có lẽ nó ở /lib/lsbhoặc nơi nào đó như thế. Không rpm -qa "lsb*"in gì?
Mikel

1
rpm -qa "lsb*không in gì cả. Theo yum provides */lsb_releasenó được chứa trong một gói gọi là redhat-lsb mà tôi đoán là không được cài đặt theo mặc định. Tuy nhiên, tôi không phải là chuyên gia Fedora, đây chỉ là kết quả từ một máy ảo Fedora ngẫu nhiên mà tôi có và có thể rất sai.
Steven D

3
Chỉ cần cài đặt Fedora 14 trong VM, và không có lsb-release, như bạn đã nói.
Mikel

5
Không sử dụng $OS, $VERSIONv.v. - theo quy ước, chúng tôi viết hoa các biến môi trường (PAGER, EDITOR, SHELL, ...) và các biến shell nội bộ (BASH_VERSION, RANDOM, ...). Tất cả các tên biến khác phải chứa ít nhất một chữ cái viết thường. Quy ước này tránh vô tình ghi đè các biến môi trường và nội bộ.
Chris Xuống

58

Tôi sẽ thực hiện bước này như một bước đầu tiên:

ls /etc/*release

Gentoo, RedHat, Arch & SuSE có một tệp gọi là eg /etc/gentoo-release. Có vẻ là phổ biến, kiểm tra trang web này về các tập tin phát hành .

Debian & Ubuntu cũng nên có /etc/lsb-releasethông tin phát hành và sẽ hiển thị với lệnh trước đó.

Một cách nhanh chóng khác là uname -rv. Nếu kernel được cài đặt là kernel distro stock, đôi khi bạn sẽ thường tìm thấy tên trong đó.


Trên Debian, đó là uname -a.
tshepang

2
không uname -rvchứa thông tin mặc dù? uname -asẽ in những thứ như loại bộ xử lý và tên máy chủ không liên quan ở đây. (Nhưng cả phiên bản kernel ( -r) và phiên bản ( -v) đều cần thiết, không phải tất cả các bản phân phối đều làm như vậy ở đó)
Mat

uname -r cho 2.6.32-5-686-bigmemuname -v cung cấp cho #1 SMP Tue Mar 8 22:14:55 UTC 2011Debian 6. uname -a OTOH cho Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux.
tshepang

phần thứ hai của uname -a-n, tức là nodename == hostname. Vì vậy, tôi muốn nói rằng unamesẽ không thú vị trên Debian. Nghĩ về nó, tôi cũng không chắc nó có ích cho RedHat hay không.
Mat

Ồ được thôi. Vì vậy, thật may mắn là tôi đã đặt tên máy chủ của mình làm mặc định debian.
tshepang

36

lsb_release -a. Hoạt động trên Debian và tôi đoán Ubuntu, nhưng tôi không chắc về phần còn lại. Thông thường nó nên tồn tại trong tất cả các bản phân phối GNU / Linux vì nó có liên quan đến LSB (Cơ sở tiêu chuẩn Linux).


3
Nó không được cài đặt theo mặc định trên Gentoo. Nó không phải mặc định trên Fedora vào một lúc nào đó (có lẽ là bây giờ)
Mat

2
Điều này hoạt động trên nền tảng Debian, Fedora 14 và OpenSUSE 11.3. Trên Debian và SUSE, gói chứa lsb_release là bản phát hành lsb, trên Fedora, nó là redhat-lsb. Nó đã được cài đặt trên Debian và SUSE, nhưng không phải trên Fedora. Tôi nghĩ rằng đây là câu trả lời tốt nhất cho đến nay. +1.
Faheem Mitha

3
lsb_release không phải là một phần của cài đặt tối thiểu CentOS 6.
một lập trình viên

1
lsb_release -a trả về "-bash: lsb_release: không tìm thấy lệnh" trên Raspberry với Raspbian ( dẫn xuất Debian 7.1).
Peter Mortensen

lsb_release -a hoạt động trên Red Hat Enterprise Linux Server phát hành 6.6 (Santiago)
jwilleke

21

Một lớp lót, dự phòng, một dòng đầu ra, không có lỗi.

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

Đẹp, cảm ơn bạn. Lưu ý rằng điều này vẫn không hoạt động trên Mac OS X, nhưng nó hoạt động tốt trên Ubuntu và CentOS (đây là ba ứng dụng tôi có).
tự đại diện

2
Xuất sắc! Tại sao một câu trả lời hấp dẫn như vậy không phải trên đầu trang?
Neo

13
python -c "import platform;print(platform.platform())"

hoặc chỉ

python -m platform

9
  1. lsb- * không được cài đặt / không tồn tại trên các hệ thống CentOS hoặc Debian cơ bản
  2. / Proc / * không tồn tại trên OSX

Lấy một mẹo từ các nhà phát triển javascript. Đừng kiểm tra phiên bản, hãy kiểm tra khả năng. Nó không đẹp, nhưng nó hoạt động. Mở rộng khi cần thiết.

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
Yum rất có thể là Red Hat, Khoa học Linux hoặc Fedora. Có một lệnh apt cho Fedora bắt chước Debian. Và như vậy. Chỉ cần siết chặt mọi thứ với yum là CentOS cung cấp cho bạn một loạt các hệ thống được hỗ trợ từ Red Hat 4 đến Fedora 18, đó là 8 năm lịch sử Linux ngay tại đó. Nếu bạn cần biết liệu <foo> có được hỗ trợ hay không, hãy kiểm tra cụ thể <foo> thay vì đoán dựa trên nhận dạng phân phối (không đáng tin cậy)! Chắc chắn, nó dẫn đến một cái gì đó bất thường của autotools, nhưng điều đó không thể giúp được (chỉ cảm ơn $ DEITY rằng các cuộc chiến Unix đã kết thúc).
vonbrand

@vonbrand thực sự, nó là như bạn nói. tôi không cố phân biệt các hương vị phụ. và thứ tự tôi đăng ký (hy vọng) sẽ loại bỏ hầu hết các tình huống khó khăn (RHEL với apt-get được cài đặt), mặc dù tôi đã không thực hiện nhiều nghiên cứu. nếu RHEL có thể cài đặt apt-get và người dùng Ubuntu có ... tốt, bạn sẽ không gặp may.
Orwellophile

6

Theo thứ tự thành công nhất, những điều sau đây:

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

bao gồm hầu hết các trường hợp (AFAIK): Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, * BSD và có lẽ những người khác.


cat /etc/*versionkhông hoạt động (không có tệp nào như vậy) trên CentOS (ít nhất là vào ngày 6.4)
om-nom-nom

Nếu bạn chạy lệnh trong vùng chứa, / Proc / phiên bản sẽ chứa phiên bản phân phối HOST chứ không phải phiên bản phân phối vùng chứa.
Dereckson

5

Đối với hầu hết các hệ điều hành Linux hiện đại, tệp /etc/os-releasethực sự đang trở thành tiêu chuẩn và được đưa vào hầu hết các hệ điều hành. Vì vậy, bên trong tập lệnh Bash của bạn, bạn chỉ có thể bao gồm tệp và bạn sẽ có quyền truy cập vào tất cả các biến được mô tả ở đây (ví dụ: NAME, VERSION, ...)

Vì vậy, tôi chỉ sử dụng điều này trong tập lệnh Bash của mình:

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

Nếu tệp /etc/debian_versiontồn tại, bản phân phối là Debian hoặc dẫn xuất Debian. Tập tin này có thể có một số phát hành; trên máy của tôi nó hiện tại 6.0.1. Nếu nó đang thử nghiệm hoặc không ổn định, nó có thể nói thử nghiệm / không ổn định, hoặc nó có thể có số lượng phát hành sắp tới. Ấn tượng của tôi là trên Ubuntu ít nhất, tệp này luôn kiểm tra / không ổn định và họ không đặt số phát hành trong đó, nhưng ai đó có thể sửa cho tôi nếu tôi sai.

Fedora (ít nhất là các bản phát hành gần đây), có một tệp tương tự, cụ thể là /etc/fedora-release.


Các phiên bản Debian mới hơn sử dụng / etc / os-release thay thế.
Dereckson

1
@Dereckson Tôi đã kiểm tra máy khò khè của tôi, và nó có cả /etc/debian_version/etc/os-release.
Faheem Mitha

Đã thử nghiệm trong một chroot Jessie được tạo bằng debootstrap. Nhưng thực sự, một máy cục bộ cũng thuộc Jessie, lần này đã cài đặt một cách thông thường hơn, chứa một /etc/debian_versiontệp. Vì vậy, cách chúng tôi chuẩn bị cài đặt Debian có thể ảnh hưởng đến các tệp phát hành có sẵn, điều đó thật thú vị.
Dereckson

Debian os-releasekhông bao gồm số phiên bản đầy đủ từ debian_version. Xem unix.stackexchange.com/questions/382531 .
JdeBP


1

2 cách từ nhiều người:

1) sử dụng

lsb_release -a

Tôi đã thử nghiệm nó trên CentOS 5.5 và Ubuntu 10.04

đầu ra cho CentOS là:

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

và đối với Ubuntu là:

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) nhập lệnh sau:

cat /etc/*-release

Tôi đã thử nghiệm nó trên CentOS 5.5 và Ubuntu 10.04 và nó hoạt động tốt.


lsb_release không có trong CentOS 6 (cài đặt tối thiểu fwiw)
một lập trình viên

lsb_release -a trả về "-bash: lsb_release: không tìm thấy lệnh" trên Raspberry với Raspbian ( dẫn xuất Debian 7.1).
Peter Mortensen

0

Kịch bản này hoạt động trên Debian, (có thể cần một số điều chỉnh trên 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

Đây là phiên bản chech_distro đơn giản của tôi. ^^;

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

Không có phiên bản, chỉ có dist:

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

Một câu trả lời từ một năm trước của Yahya Yahyaoui cũng nói điều tương tự. Cả hai câu trả lời trên thực tế đã được giải quyết vào năm 2011 trong các câu trả lời đã bị xóa. Những lý do mà họ sai vẫn áp dụng.
JdeBP

0

Điều này đã được thử nghiệm trên Ubuntu 14 và CentOS 7

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

@don_crissti Bạn sẽ làm thế nào?
BsdHelper

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

@cas Rất đẹp! Thêm nó vào hộp công cụ của tôi. Cảm ơn bạn đã chia sẻ.
BsdHelper

0

Tôi tìm thấy một kịch bản tốt từ đây , hoạt động cho hầu hết các bản linux phổ biến:

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

Có một viên ngọc ruby facter , cung cấp cho bạn một số sự thật về hệ điều hành os, nó phân tích các tệp phát hành HĐH, dữ liệu khác và in ra màn hình đầu cuối. Bạn có thể thử như sau, bắt đầu với cài đặt rubygems:

# apt-get install rubygems

Vui lòng sử dụng trường hợp trên đủ điều kiện cho hệ điều hành của bạn. Sau đó cài đặt đá quý chính nó.

# gem install facter

Sau đó sử dụng:

$ facter

LƯU Ý: Xem các nguồn đá quý facter để có thêm thông tin trong cài đặt.


0

Nếu ai đó cần bản phân phối là tốt:

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

Đầu ra:

It is: 18.04

Thay đổi thành: lsb_release -sc để nhận bản phân phối:

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

Đầu ra:

It is: bionic

-3

Lệnh này hoạt động cho các bản phân phối dựa trên Debian và Redhat: Sử dụng trbộ lọc, bạn chuyển đổi tài liệu sang định dạng một từ trên mỗi dòng và sau đó đếm dòng đầu tiên chứa tên phân phối.

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

Các ý kiến ​​về câu trả lời đã bị xóa từ năm 2011 cho biết điều tương tự, vẫn được áp dụng. Như câu trả lời sai, một lần nữa bây giờ đã bị xóa, điều đó nói rằng /etc/issuekhông có phiên bản hoặc tên trên zenwalk. Đây là một tệp có thể sửa đổi của quản trị viên có chứa một thông báo được trình bày cho con người không đảm bảo có chứa bất cứ thứ gì có thể được rút ra theo chương trình.
JdeBP
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.