Bagaimana cara mengetahui versi Linux yang sedang berjalan?

29

Terkadang skrip Anda perlu berperilaku berbeda di Linux yang berbeda. Bagaimana saya bisa menentukan versi Linux yang menjalankan skrip?

jldugger
sumber
1
Menurut versi, maksud Anda versi kernel? Distribusi apa? Versi distro?
Chris Upchurch
2
Saya yakin jldugger ingin mengetahui keluarga distribusi mana yang dijalankan sistem. Tidak mungkin skrip akan terpengaruh oleh versi kernel kecuali tergantung pada beberapa / sys atau / proc - dan bahkan kemudian biasanya lebih mudah untuk mengasumsikan berdasarkan distribusi daripada pada kernel.
Mihai Limbăşan

Jawaban:

27

Jangan mencoba dan membuat asumsi berdasarkan distro tentang apa yang Anda bisa dan tidak bisa lakukan, karena itu ada kegilaan (lihat juga "Deteksi Agen Pengguna"). Alih-alih, deteksi apakah yang ingin Anda lakukan didukung, dan bagaimana hal itu dilakukan oleh perintah atau lokasi file apa pun yang ingin Anda gunakan.

Misalnya, jika Anda ingin menginstal paket, Anda dapat mendeteksi apakah Anda menggunakan sistem seperti Debian atau sistem seperti RedHat dengan memeriksa keberadaan dpkg atau rpm (periksa dpkg terlebih dahulu, karena mesin Debian dapat memiliki perintah rpm pada mereka ...). Buat keputusan tentang apa yang harus dilakukan berdasarkan itu, bukan hanya pada apakah itu sistem Debian atau RedHat. Dengan begitu Anda akan secara otomatis mendukung setiap distro turunan yang tidak Anda programkan secara eksplisit. Oh, dan jika paket Anda memerlukan dependensi tertentu, maka uji juga untuk itu dan beri tahu pengguna apa yang hilang.

Contoh lain adalah mengutak-atik antarmuka jaringan. Cari tahu apa yang harus dilakukan berdasarkan apakah ada file / etc / network / interfaces atau direktori / etc / sysconfig / network-scripts, dan lanjutkan dari sana.

Ya, ini lebih banyak pekerjaan, tetapi kecuali jika Anda ingin membuat kembali semua kesalahan yang telah dilakukan pengembang web selama dekade terakhir atau lebih, Anda akan melakukannya dengan cara yang cerdas sejak awal.

womble
sumber
1
(Memperluas jawaban ini) Deteksi fitur lebih disukai dalam beberapa situasi, tetapi pastikan Anda tidak pernah mencoba dan menebak distribusi dari fitur yang Anda deteksi! Jangan salah membaca jawaban dan mencari tahu apakah platform ini RedHat berdasarkan file apa yang ada di / etc. Jika Anda benar-benar membutuhkan nama distribusi, periksa lsb_release (atau / etc / redhat-release, dan seterusnya).
Nicholas Wilson
36

Tidak ada cara distribusi silang. Namun:

  • Redhat dan teman-teman: Uji untuk /etc/redhat-release, periksa konten
  • Debian: Tes untuk /etc/debian_version, periksa isinya
  • Mandriva dan teman-teman: Tes untuk /etc/version, periksa isinya
  • Slackware: Uji untuk /etc/slackware-version, periksa isinya

Dll. Secara umum, periksa /etc/*-releasedan /etc/*-version.


Sunting: Menemukan skrip bash lama (1+ tahun) milik saya tergeletak di sekitar yang pasti telah saya kumpulkan selama bertahun-tahun (ini memiliki log CVS yang mengesankan selama 6 tahun.) Mungkin tidak berfungsi dengan baik lagi apa adanya dan saya bisa Jangan repot-repot menemukan distro yang terinstal untuk diuji, tetapi seharusnya memberi Anda titik awal yang baik. Ini berfungsi dengan baik pada CentOS, Fedora dan Gentoo. gyaresu mengujinya dengan sukses di Debian Lenny.

#!/bin/bash

get_distribution_type()
{
    local dtype
    # Assume unknown
    dtype="unknown"

    # First test against Fedora / RHEL / CentOS / generic Redhat derivative
    if [ -r /etc/rc.d/init.d/functions ]; then
        source /etc/rc.d/init.d/functions
        [ zz`type -t passed 2>/dev/null` == "zzfunction" ] && dtype="redhat"

    # Then test against SUSE (must be after Redhat,
    # I've seen rc.status on Ubuntu I think? TODO: Recheck that)
    elif [ -r /etc/rc.status ]; then
        source /etc/rc.status
        [ zz`type -t rc_reset 2>/dev/null` == "zzfunction" ] && dtype="suse"

    # Then test against Debian, Ubuntu and friends
    elif [ -r /lib/lsb/init-functions ]; then
        source /lib/lsb/init-functions
        [ zz`type -t log_begin_msg 2>/dev/null` == "zzfunction" ] && dtype="debian"

    # Then test against Gentoo
    elif [ -r /etc/init.d/functions.sh ]; then
        source /etc/init.d/functions.sh
        [ zz`type -t ebegin 2>/dev/null` == "zzfunction" ] && dtype="gentoo"

    # For Slackware we currently just test if /etc/slackware-version exists
    # and isn't empty (TODO: Find a better way :)
    elif [ -s /etc/slackware-version ]; then
        dtype="slackware"
    fi
    echo $dtype
}

Perhatikan bahwa ini mungkin hanya akan berfungsi dengan benar di Bash. Anda bisa menulis ulang untuk kerang lain.

Yang sedang berkata, Anda mungkin ingin menguji fitur, bukan untuk distribusi. Saya tidak menggunakan ini lagi hanya karena itu menjadi beban perawatan. Lebih mudah untuk mengandalkan alat dan solusi lintas distribusi.


Secara konseptual, apa yang dilakukannya adalah, dalam rangka:

  • Tarik jenis file yang dikenal, "fungsi skrip init umum". Itu adalah distribusi khusus. Jika tidak ada, lewati untuk memeriksa distribusi berikutnya.
  • Periksa keberadaan fungsi tertentu, yang diketahui ada, sering digunakan dan tidak mungkin diganti namanya dari skrip inti itu. Kami melakukannya menggunakan typeBash builtin. type -tkembali functionjika simbol itu adalah fungsi. Kami menambahkan zzke output dari type -t 2>/dev/nullkarena jika nama tidak didefinisikan string output akan kosong dan kami akan mendapatkan kesalahan sintaks tentang tangan kiri yang hilang ke ==operator. Jika nama yang baru saja kami periksa bukan fungsi, lewati ke pemeriksaan distribusi berikutnya, kalau tidak kami menemukan jenis distribusi.
  • Akhirnya, gema tipe distribusi sehingga output fungsi dapat dengan mudah digunakan dalam case .. esac block.

Edit jika Anda mencoba menjalankan ini sebagai skrip langsung: Skrip ini seharusnya bersumber atau disertakan dari skrip lain. Itu tidak menghasilkan apa-apa sendiri jika Anda menjalankan apa adanya. Untuk mengujinya, sumberilah dan aktifkan fungsinya, misalnya:

source /path/to/this/script.sh
get_distribution_type

di bash prompt.


Sunting: Harap dicatat bahwa skrip ini tidak memerlukan hak akses root. Saya mendorong Anda untuk tidak menjalankannya sebagai root. Seharusnya tidak membahayakan apa pun, tetapi tidak perlu.


Menemukan tautan ke pos milis yang relevan di log CVS. Harus berguna dalam membuka skrip skrip init.

Mihai Limbăşan
sumber
Saya belum melihat mengapa tetapi kembali ke prompt pada Debian Lenny (5.0).
Gareth
gyaresu, apakah Anda benar-benar memanggil fungsi get_distribution_type? Saya telah mengedit posting untuk memperjelas (lihat di bagian bawah.)
Mihai Limbăşan
@gyaresu: Jika hal di atas bukan masalah, bisakah Anda mencoba mengganti log_begin_msg di bagian Debian dengan log_warning_msg dan coba lagi? Mungkin salah nama fungsinya. Bagaimanapun, itu seharusnya telah mengembalikan "tidak dikenal" jika fungsi itu tidak menghalangi, tapi tetap saja.
Mihai Limbăşan
@Mihai Doh! Maaf. Tidak membaca skrip dengan benar. Sudah pagi, tidak ada kopi. Saya minta maaf gyaresu @ debian: ~ / bin $ source server_version.sh gyaresu @ debian: ~ / bin $ get_distribution_type debian
Gareth
@gyaresu: Terima kasih! Itu bagus, harus membantu jldugger untuk mengetahui bahwa itu berfungsi pada Debian juga :)
Mihai Limbăşan
17

Anda dapat menemukan versi kernel dengan menjalankan uname -a, menemukan versi distro tergantung pada distro.

Di Ubuntu dan beberapa OS lainnya, Anda dapat menjalankan lsb_release -aatau membaca / etc / lsb_release

Debian menyimpan versi di / etc / debian_version

Adam Gibbins
sumber
+1 untuk lsb_release (juga berfungsi pada turunan Red Hat jika paket yang tepat diinstal)
Josh Kelley
hanya untuk deskripsi 'lsb_release -ds'.
flickerfly
6

Kebanyakan distro memiliki metode unik untuk menentukan distribusi tertentu.

Sebagai contoh:

Redhat (And derivatives): /etc/redhat-release

SUSE: /etc/SUSE-release

Ada standar di luar sana yang dikenal sebagai Linux Standard Base atau LSB . Ini mendefinisikan bahwa harus ada file bernama / etc / lsb-release atau program yang disebut lsb_release yang akan mengulang kembali informasi tentang distro linux Anda.

lsb_release -a
Mark Turner
sumber
Dan tentu saja, lsb_releasetidak ada pada CentOS 6.
Justin
6
python -c 'import platform ; print platform.dist()[0]'

kode: http://hg.python.org/cpython/file/2.7/Lib/platform.py

jkeogh
sumber
Ide yang hebat. Saya akan menyarankan menggunakan python -c 'import platform; print(platform.dist()[0])', karena cara itu juga berfungsi jika python normal default ke python3.
heinrich5991
5

Selain jawaban lain: Jika Anda hanya ingin mem-parsing satu file, sebagian besar distro mempersonalisasi login tty melalui / etc / issue misalnya:

Selamat datang di SUSE Linux Enterprise Server 10 SP2 (i586) - Kernel \ r (\ l).

Dan ya saya tahu itu tidak optimal. :)

Node
sumber
Mungkin kurang optimal, tetapi berada di tempat yang sama.
Brad Gilbert
4

facter adalah alat yang berguna untuk penemuan semacam ini, meskipun mungkin menggunakan beberapa metode yang dijelaskan di atas, dan membutuhkan Ruby.

Cawflands
sumber
2

Yang perlu Anda lakukan adalah mengetikkan uname -ashell favorit Anda. Itu akan mencetak nama dan versi kernel.


sumber
2

Saya menemukan bahwa cat /etc/*release*hampir selalu berhasil.

ibuys
sumber
2

Saya setuju dengan Mark, Adam dan Mihai (tidak dapat memilih karena reputasi yang tidak memadai). Solusi berdasarkan LSB dan FHS relatifnya akan bekerja dengan sebagian besar distribusi dan kemungkinan akan terus bekerja di masa depan. LSB dan FHS adalah teman Anda.

David J. Liszewski
sumber
2

Anda juga bisa mendapatkan versi dengan

cat /proc/version

o / p:

Linux versi 2.6.17-13mdv ([email protected]) (versi gcc 4.1.2 20070302 (prerelease) (4.1.2-1mdv2007.1)) # 1 SMP Jum Mar 23 Maret 19:03:31 UTC 2007

prasanna
sumber
1

Versi linux adalah pertanyaan yang sulit. Jika kami melihatnya secara sempit, kami memiliki versi kernel yang dapat Anda dapatkan dengan " uname -r". Versi distribusi sebagian besar tidak sopan. Beberapa distribusi lebih baik (distribusi perusahaan seperti Redhat Enterprise Linux). Distribusi lain seperti Gentoo pada dasarnya adalah memindahkan target yang tidak memiliki versi yang masuk akal sama sekali. Jika Anda perlu melakukan hal-hal berdasarkan versi, lihat komponen utama yang relevan untuk Anda:

Component       Version command
glibc           /lib/libc.so.6
gcc             gcc --version
X               xdpyinfo
libX11          pkg-config --modversion x11
gtk+            pkg-config --modversion gtk+-2.0
qt-4            pkg-config --modversion QtCore

   etc...
Paul de Vrieze
sumber
1

Anda juga dapat memeriksa menu Grub, biasanya memberi Anda banyak info distro / versi :-)

Antoine Benkemoun
sumber
-1

FusionInventory adalah alat inventaris ringan lintas platform yang bisa mendapatkan informasi ini di banyak distro Linux, tetapi juga pada BSD, Windows, MacOS X, dan unit lainnya.

Jika tersedia, mereka menggunakan lsb_release(sebagaimana disebutkan beberapa kali di atas), tetapi jika tidak, mereka memiliki daftar file dan ekspresi reguler yang sangat berguna untuk memeriksa nama dan versi distro: https://github.com/fusinv/fusioninventory-agent/ gumpalan / 2.2.x / lib / FusionInventory / Agent / Task / Inventory / Input / Linux / Distro / NonLSB.pm # L16 .

Saya akan merekomendasikan menggunakan FusionInventory sendiri untuk mendapatkan informasi ini, daripada menerapkan kembali skrip Anda sendiri dengan logika ini, karena komunitas mereka akan menjaga fungsionalitas ini mutakhir. Anda bisa menggunakan agen itu sendiri (menghasilkan file XML / JSON yang mudah diurai) atau memasangkannya dengan solusi yang lebih luas untuk mengelola mesin di jaringan Anda seperti GLPI atau Rudder , tergantung pada kebutuhan Anda.

Jonathan Clarke
sumber
Ini akan menjadi solusi yang baik jika tidak memiliki dependensi eksternal dari modul Perl
Will Sheppard