Mendeteksi sistem init menggunakan shell

90

Ini mungkin lebih berkaitan dengan mendeteksi sistem operasi, tetapi saya secara khusus membutuhkan sistem init yang saat ini digunakan pada sistem.

Fedora 15 dan Ubuntu sekarang menggunakan systemd, Ubuntu digunakan untuk menggunakan Pemula (standar lama hingga 15,04), sementara yang lain menggunakan variasi Sistem V.

Saya memiliki aplikasi yang saya tulis untuk menjadi daemon lintas-platform. Skrip init sedang dibuat secara dinamis berdasarkan parameter yang dapat diteruskan pada konfigurasi.

Yang ingin saya lakukan adalah hanya menghasilkan skrip untuk sistem init tertentu yang mereka gunakan. Dengan cara ini skrip instalasi dapat dijalankan secara wajar tanpa parameter sebagai root dan daemon dapat "dipasang" secara otomatis.

Inilah yang saya buat:

  • Cari systemd, pemula, dll di / bin
  • Bandingkan / proc / 1 / comm dengan systemd, pemula, dll
  • Tanyakan pada pengguna

Apa cara lintas / platform terbaik untuk melakukan ini?

Jenis yang terkait, Dapatkah saya bergantung pada bash untuk menjadi mayoritas * nix atau tergantung distribusi / OS?

Platform target:

  • OS Mac
  • Linux (semua distribusi)
  • BSD (semua versi)
  • Solaris, Minix, dan * nix lainnya
hajar
sumber
1
Hanya untuk menambahkan dua sen saya, bash tidak diinstal secara default di FreeBSD.
Chinmay Kanchi
@jameson, apakah Anda menemukan cara yang lebih langsung? Saya mencari hal yang sama tetapi jawaban di sini hanya arahan, bukan jawaban langsung. Secara khusus 1) lokasi skrip untuk mencari dan 2) mendeteksi sistem init yang berlaku, jika ada beberapa yang diinstal (bash dijawab secara langsung).
n611x007
3
@naxa - Jawaban singkat, tidak. Jawaban panjang, Anda bisa mendapatkan cukup jauh dengan ps -p 1 -o command(mencetak jalur ke arus init). Di Arch Linux dan Fedora (IIRC), itu adalah symlink ke systemdbiner (mungkin sama pada semua systemdsistem). Pada upstart, init --helpakan mencetak informasi penggunaan, dan pada kotak saya, upstartdisebutkan di mana dikatakan siapa yang harus diemail. Pada FreeBSD (sysV), ini akan mengembalikan kesalahan. Mungkin ada petunjuk serupa pada sistem lain, tetapi sejak mengajukan pertanyaan ini, saya telah memutuskan untuk hanya membuat mereka untuk semua platform dan membuat paket terpisah untuk masing-masing.
beatgammit
terima kasih banyak info! Melompat dari sana saya telah belajar yang sudo lsof -a -p 1 -d txtmungkin memberikan hasil yang lebih tepat. psdapat mencetak nama arbitrer, sedangkan dengan lsofAnda akan mendapatkan jalur yang dapat dieksekusi nyata. (Lihat pertanyaan saya unix.stackexchange.com/questions/102453/… )
n611x007
1
Tidak ada jawaban atau komentar dalam pertanyaan terkait yang terkait dengan bash. Solusi harus berlaku untuk kasus Anda juga.
Marco

Jawaban:

30

Untuk pertanyaan kedua, jawabannya adalah tidak dan Anda harus melihat Sumberdaya untuk pemrograman shell portabel .

Adapun bagian pertama - pertama-tama, Anda tentu harus berhati-hati. Saya akan mengatakan melakukan beberapa tes untuk memastikan - karena fakta bahwa seseorang memang memiliki systemd (misalnya) diinstal, tidak berarti itu benar-benar digunakan sebagai default init. Juga, melihat /proc/1/commdapat menyesatkan, karena beberapa instalasi dari berbagai program init dapat secara otomatis membuat /sbin/initsymlink hardlink atau bahkan versi berganti nama dari program utama mereka.

Mungkin hal yang paling berguna adalah melihat jenis skrip init - karena itulah yang sebenarnya akan Anda buat, apa pun yang menjalankannya.

Sebagai catatan tambahan, Anda mungkin juga melihat OpenRC yang bertujuan untuk menyediakan struktur skrip init yang kompatibel dengan sistem Linux dan BSD.

rozcietrzewiacz
sumber
2
Apa yang Anda maksud dengan "lihat tipe skrip init"? Seringkali sistem init yang berbeda menempatkan script mereka / file di suatu tempat selain /etc/init, seperti systemd menempatkan mereka dalam /etc/systemd. Jika saya ingin memiliki skrip grok ini, ini bisa memakan waktu cukup lama. Oh, dan terima kasih atas tautan BTW untuk pemrograman shell portabel.
beatgammit
1
Saya bermaksud mengatakan bahwa beberapa implementasi init dapat disesuaikan untuk menggunakan berbagai jenis dan lokasi skrip init (seperti /etc/rc.d/atau /etc/init.d/). Dan Anda harus menyesuaikan program Anda dengan benar pada waktu instalasi untuk memanfaatkan struktur yang digunakan pada sistem yang diberikan.
rozcietrzewiacz
2
Jadi, apakah Anda mengatakan bahwa tidak ada cara yang dapat diandalkan untuk mendeteksi sistem init secara terprogram? Memiliki parameter pass masuk pengguna tentu saja lebih aman, tetapi jika pengguna tidak menyampaikan apa pun, apa cara terbaik untuk menebak?
beatgammit
Saya tidak tahu apa yang akan menjadi cara terbaik untuk program Anda - semuanya tergantung pada sistem apa yang akan dijalankan oleh program. Saya belum menggunakan terlalu banyak distribusi, tetapi saya mencoba membagikan pengamatan saya untuk membantu Anda. Ini adalah skrip sulit yang akan Anda coba dan saya mencoba memberi Anda beberapa pandangan di lapangan - Anda harus sampai pada jawaban akhir sendiri atau menunggu lebih banyak petunjuk.
rozcietrzewiacz
Keren, terima kasih atas semua bantuan Anda. Anda pasti telah mengarahkan saya ke arah yang benar.
beatgammit
58

Saya sendiri sudah melangkah ke masalah ini dan memutuskan untuk melakukan beberapa tes. Saya sepenuhnya setuju dengan jawaban bahwa seseorang harus mengemas untuk setiap distro secara terpisah, tetapi kadang-kadang ada masalah praktis yang mencegahnya (tidak terkecuali tenaga kerja).

Jadi bagi mereka yang ingin "deteksi otomatis" inilah yang saya temukan di distro terbatas (lebih banyak di bawah):

  • Anda dapat mengetahui mulai dari:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
  • Anda dapat memberi tahu systemd dari:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
  • Anda dapat memberi tahu sys-v init dari:

    [[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]] && echo yes

Berikut ini eksperimen saya dengan baris perintah berikut:

if [[ `/sbin/init --version` =~ upstart ]]; then echo using upstart;
elif [[ `systemctl` =~ -\.mount ]]; then echo using systemd;
elif [[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]]; then echo using sysv-init;
else echo cannot tell; fi

pada contoh EC2 (saya termasuk id AMI us-east):

  • ArchLinux: using systemd (sejak 2012.10.06 )
  • CentOS6.4 ami-52009e3b: menggunakan pemula
  • CentOS7 ami-96a818fe: using systemd
  • Debian 6 ami-80e915e9: using sysv-init
  • Debian 7.5 ami-2c886c44: using sysv-init
  • Debian 7.6 GCE container-vm: using sysv-init
  • RHEL 6.5 ami-8d756fe4: menggunakan pemula
  • SLES 11 ami-e8084981: using sysv-init
  • Ubuntu 10,04 ami-6b350a02: menggunakan pemula
  • Ubuntu 12.04 ami-b08b6cd8: menggunakan pemula
  • Ubuntu 14.04 ami-a427efcc: using upstart
  • Ubuntu 14.10 dan lebih muda: using systemd
  • AWS linux 2014.3.2 ami-7c807d14: menggunakan pemula
  • Fedora 19 ami-f525389c: using systemd
  • Fedora 20 ami-21362b48: using systemd

Untuk lebih jelasnya: Saya tidak mengklaim bahwa ini sangat mudah! , hampir pasti tidak. Juga perhatikan bahwa untuk kenyamanan saya menggunakan pertandingan bash regexp, yang tidak tersedia di mana-mana. Di atas sudah cukup baik untuk saya sekarang. Namun, jika Anda menemukan distro yang gagal, beri tahu saya dan saya akan mencoba memperbaikinya jika ada AMI EC2 yang mereproduksi masalah ...

TVE
sumber
5
Menurut dokumentasi systemd ( sd_booted (3) ), cara yang benar untuk memeriksa systemd adalah memeriksa apakah direktori tersebut /run/systemd/systemada.
Robie Basak
1
Saya akan menambahkan deteksi ini launchd, sistem init pada macOS: [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo nodiuji pada MacBookPro, macOS Sierra Versi 10.12
Tony
Saya juga akan menambahkan busybox:if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Astrinus
18

Menggunakan proses

Melihat output dari beberapa psperintah yang dapat mendeteksi berbagai versi systemd& upstart, yang dapat dibuat seperti:

pemula

$ ps -eaf|grep '[u]pstart'
root       492     1  0 Jan02 ?        00:00:00 upstart-udev-bridge --daemon
root      1027     1  0 Jan02 ?        00:00:00 upstart-socket-bridge --daemon

systemd

$ ps -eaf|grep '[s]ystemd'
root         1     0  0 07:27 ?        00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
root       343     1  0 07:28 ?        00:00:03 /usr/lib/systemd/systemd-journald
root       367     1  0 07:28 ?        00:00:00 /usr/lib/systemd/systemd-udevd
root       607     1  0 07:28 ?        00:00:00 /usr/lib/systemd/systemd-logind
dbus       615     1  0 07:28 ?        00:00:13 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation

Memperhatikan nama proses yang PID # 1 juga berpotensi menjelaskan sistem init yang sedang digunakan. Pada Fedora 19 (yang menggunakan systemd, misalnya:

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 07:27 ?        00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20

Perhatikan itu bukan init. Di Ubuntu dengan Upstart masih /sbin/init.

$ ps -efa|grep init
root         1     0  0 Jan02 ?        00:00:03 /sbin/init

CATATAN: Tetapi gunakan ini dengan sedikit hati-hati. Tidak ada sesuatu yang diatur dalam batu yang mengatakan sistem init khusus yang digunakan pada distro yang diberikan telah memiliki systemdsebagai PID # 1.

umum

$ (ps -eo "ppid,args" 2>/dev/null || echo "ps call error") \
    | awk 'NR==1 || $1==1' | less
 PPID   COMMAND
    1   /lib/systemd/systemd-journald
    1   /lib/systemd/systemd-udevd
    1   /lib/systemd/systemd-timesyncd

Lihatlah proses-proses dengan ppid 1 (anak-anak dari proses init). (Beberapa) nama proses anak mungkin menunjuk ke sistem init yang digunakan.

Sistem file

Jika Anda menginterogasi initexecutable, Anda bisa mendapatkan beberapa info darinya. Cukup parsing --versionoutput. Sebagai contoh:

pemula

$ sudo /sbin/init --version
init (upstart 1.5)
Copyright (C) 2012 Scott James Remnant, Canonical Ltd.

This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

systemd

$ type init
init is /usr/sbin/init

CATATAN: Fakta yang inittidak ada di lokasi standarnya adalah sedikit petunjuk. Itu selalu terletak di /sbin/initsistem sysvinit.

sysvinit

$ type init
init is /sbin/init

Ini juga:

$ sudo init --version
init: invalid option -- -
Usage: init 0123456SsQqAaBbCcUu

Kesimpulan

Jadi sepertinya tidak ada satu cara untuk melakukannya, tetapi Anda dapat merumuskan serangkaian cek yang akan menunjukkan sistem init mana yang Anda gunakan dengan tingkat kepercayaan yang cukup tinggi.

slm
sumber
Bagaimana dengan:pgrep systemd >/dev/null && echo init system: systemd
Marco
Terima kasih, inilah tepatnya yang saya cari: beberapa langkah yang harus diambil untuk mencoba menentukan sistem init.
user369450
1
PID # 1 tidak harus /usr/lib/systemd/systemdjika systemd digunakan, itu adalah asumsi yang salah. Di sistem saya, misalnya, PID # 1 adalah /sbin/init(saya menggunakan systemd). Itu tergantung distribusi.
Marco
Pada instalasi Kubuntu 15.04 saya, saya memiliki systemd dan sysvinit. Tidak tahu mengapa atau apa artinya itu, hanya mengatakan .. pgrep systemd >/dev/null && echo init system: systemd -> init system: systemddantype init -> init is /sbin/init
dotnetCarpenter
12

Tidak seefisien itu, tetapi saya sepertinya berhasil.

strings /sbin/init | grep -q "/lib/systemd" && echo SYSTEMD
strings /sbin/init | grep -q "sysvinit" && echo SYSVINIT
strings /sbin/init | grep -q "upstart" && echo UPSTART

Ini akan mencetak lebih banyak baris jika lebih dari satu string cocok, yang dapat diterjemahkan ke "Tidak bisa menebak". String yang digunakan dalam grep bisa sedikit dimodifikasi tetapi ketika diuji di os berikut saya selalu mendapat satu baris.

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (Pembaruan Nahant 7) [SYSVINIT]
  • Ubuntu 16.04.1 LTS [SYSTEMD]
  • Ubuntu 14.04.2 LTS [UPSTART]
  • Fedora merilis 23 (shell online) [SYSTEMD]
  • Debian GNU / Linux 7 (shell online) [SYSTEMD]

Pendekatan yang lebih sederhana dari solusi yang sama (tetapi berhenti pada pertandingan pertama)

strings /sbin/init |
  awk 'match($0, /(upstart|systemd|sysvinit)/) { print toupper(substr($0, RSTART, RLENGTH));exit; }'
Marinos An
sumber
jawaban pertama yang bagus. selamat datang di unix.se!
Olivier Dulac
Saya baru saja mencoba ini pada gambar docker default Gentoo dengan OpenRC terinstal, dan mengembalikan SYSVINIT. Menurut wiki.gentoo.org/wiki/Comparison_of_init_systems , default untuk Gentoo adalah OpenRC, tetapi tampaknya OpenRC menggunakan sysvinit. Ketika saya kemudian mencoba perintah OpenRC saya mendapatkan "Anda mencoba untuk menjalankan layanan OpenRC pada sistem yang tidak bisa boot openrc." Apakah ada cara untuk membedakan antara sysvinit yang tepat dan OpenRC menggunakan sysvinit?
tudor
9

Terkadang semudah menggunakan ls :

$ ls -l /sbin/init
lrwxrwxrwx 1 root root 20 juin  25 12:04 /sbin/init -> /lib/systemd/systemd

Saya kira jika /sbin/initbukan tautan simbolis, Anda harus memeriksa saran berikut lebih lanjut di jawaban lain.

Skippy le Grand Gourou
sumber
3
  1. Ini adalah paket khusus untuk distro. Ada jauh lebih banyak untuk menginstal perangkat lunak dengan benar daripada hanya mendeteksi sistem init. Banyak distro menggunakan SysVinit tetapi tidak semua dari mereka menulis skrip init mereka dengan cara yang sama. Cara yang tepat untuk menyelesaikan ini adalah dengan memasukkan semua varian yang berbeda dan kemudian menggabungkannya menggunakan file spesifikasi dengan nama dependensi distro-spesifik untuk distro rpm, file deb untuk sistem berbasis apt, dll. Hampir semua distro memiliki semacam spesifikasi paket yang Anda dapat menulis yang menyertakan dependensi, skrip, skrip init, dll. Jangan menciptakan kembali roda di sini.

  2. Tidak. Yang membawa kita kembali ke 1. Jika kamu butuh bash, itu harusnya ketergantungan. Anda dapat menentukan pemeriksaan ini sebagai bagian dari skrip konfigurasi Anda, tetapi harus juga dalam deskripsi paket.

Sunting: Gunakan bendera pada skrip konfigurasi Anda seperti --with upstartatau --without sysvinit. Pilih default waras, maka skrip yang mengemas perangkat lunak Anda untuk distro lain dapat memilih untuk menjalankan ini dengan opsi lain.

Caleb
sumber
Hmph, jadi sepertinya saya tidak bisa memiliki solusi 'satu skrip untuk mengatur semuanya'. Saya telah melihat banyak program yang menggunakan autoconf atau serupa untuk menangani hal-hal lintas platform, tetapi sepertinya itu bukan alat yang tepat untuk aplikasi saya. Apakah mempertahankan versi untuk setiap platform benar-benar satu-satunya solusi yang dapat diandalkan?
beatgammit
Satu skrip instalasi untuk mengatur semuanya adalah BadIdea. Akhirnya gagal lebih banyak tempat daripada yang bekerja. Autoconf bagus sejauh ini. Bekerja keras untuk menjaga agar ujung perangkat lunak Anda menjadi generik mungkin dan sertakan skrip init alternatif dalam paket Anda. Spesifikasi paket pengaturan untuk beberapa distro utama. Jika perangkat lunak Anda bagus, Anda bisa meminta orang lain membantu Anda mengemasnya untuk sistem lain.
Caleb
@jameson: Saya baru sadar saya lupa bagian yang paling penting. Hal semacam ini biasanya dilakukan dengan sakelar yang diteruskan ke skrip configure. Rutinitas build / paket masing-masing distro dapat memanggil switch yang berbeda, dan configure / make Anda hanya perlu tahu switch apa yang dilewati, tidak mendeteksi semua konfigurasi perangkat lunak yang mungkin.
Caleb
@ Caleb- Ya, saya sudah memiliki logika itu di sana, tetapi tangkapan yang bagus. Saya berharap cara untuk mengendus sistem init untuk menggunakan tebakan cerdas daripada standar waras.
beatgammit
2

Di Gentoo, lihat pid 1:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   4216   340 ?        Ss    2013   0:57 init [3]

Jika ya init, maka sistem init adalah OpenRC. Jika ya systemd, maka sistem init adalah systemd.

Anda dapat mendeteksi Gentoo dengan [ -f /etc/gentoo-release ].

Metode lain di Gentoo adalah menggunakan profile-config show, yang akan menunjukkan profil default apa yang digunakan. Semua profil kecuali dua yang berakhiran / systemd menggunakan init OpenRC. Perlu diingat, ini hanya mewakili standar dan ada kemungkinan bahwa pengguna telah mengambil langkah-langkah untuk mengesampingkan default itu dan mungkin bukan indikasi palungan init yang sebenarnya sedang digunakan.

casey
sumber
Pertanyaan bodoh, tapi bagaimana cara memeriksa pid 1?
Faheem Mitha
Gunakan popsi (identik dengan -pdan --pid) untuk memilih dengan PID. Cuplikan di atas sebenarnya adalah output untuk ps u --pid 1.
José M. Benítez
2

Pada debian / sbin / init adalah symlink ke init default Anda

ls -l /sbin/init

akan memberi Anda info yang Anda cari.

$ ls -l /sbin/init 
lrwxrwxrwx 1 root root 20 nov 18 13:15 /sbin/init -> /lib/systemd/systemd
rmorelli74
sumber
1
Tidak begitu. Di Ubuntu 14.04 dengan Upstart, ini bukan symlink.
muru
Instal sistem init lain dan periksa lagi.
rmorelli74
Dan yang lain yang initbisa saya instal di Ubuntu 14.04?
muru
... mengapa tidak sysv atau systemd?
rmorelli74
1
Saya tidak ingin downvote, saya hanya ingin Anda menentukan versi Debian mana yang berlaku. (Dan mungkin ulang kata "Berbasis Debian" menjadi "Debian" saja, sehingga menjadi benar.)
muru
2

Cukup dengan memasuki proses dengan PID 1 akan memberi tahu Anda:

strings /proc/1/exe |grep -q sysvinit
strings /proc/1/exe |grep -q systemd
Cyrille Pontvieux
sumber
Tidak semua OS yang disebutkan memiliki procsistem file ...
Toby Speight
2

Juga memeriksa deskriptor file dapat membantu. Dan itu dari benar-benar menjalankan init (Debian stretch saat ini memungkinkan untuk menginstal lebih banyak sistem init) :-)

$ ls -l /proc/1/fd |grep systemd
lrwx------ 1 root root 64 srp 14 13:56 25 -> /run/systemd/initctl/fifo
lr-x------ 1 root root 64 srp 14 13:56 6 -> /sys/fs/cgroup/systemd

$ ls -l /proc/1/fd |grep /run/initctl # sysvinit
lrwx------ 1 root root 64 srp 14 14:04 10 -> /run/initctl

$ ls -l /proc/1/fd |grep upstart
l-wx------ 1 root root 64 srp 13 16:09 13 -> /var/log/upstart/mysql.log.1 (delete
l-wx------ 1 root root 64 srp 13 16:09 9 -> /var/log/upstart/dbus.log.1 (deleted)

$ ls -l /proc/1/fd # busybox
total 0
lrwx------    1 root     root          64 Jan  1 00:00 0 -> /dev/console
lrwx------    1 root     root          64 Jan  1 00:00 1 -> /dev/console
lrwx------    1 root     root          64 Jan  1 00:00 2 -> /dev/console

Mungkin cara yang lebih aman untuk memeriksa busybox adalah dengan check /proc/1/exe, karena busybox biasanya menggunakan symlink:

$ ls -l /proc/1/exe 
lrwxrwxrwx    1 root     root          0 Jan  1 00:00 /proc/1/exe -> /bin/busybox

Jadi cek bisa:

{ ls -l /proc/1/fd |grep -q systemd && echo "init: systemd"; } || \
{ ls -l /proc/1/fd |grep -q /run/initctl && echo "init: sysvinit"; } || \
{ ls -l /proc/1/fd |grep -q upstart && echo "init: upstart"; } || \
{ ls -l /proc/1/exe |grep -q busybox && echo "init: busybox"; } || \
echo "unknown init"
pevik
sumber
Juga sistem dengan systemd biasanya memiliki direktori /run/systemd/system.
pevik
2

Tidak tahu tentang sistem lain maka Debian (wheezy) / atau Ubuntu (14.10.) Tapi saya menguji masalah tersebut dengan fileperintah lama biasa .

file /sbin/init

berikan ini:

/sbin/init: symbolic link to 'upstart'

Sistem Debian dengan systemd(misalnya sid) menunjukkan ini:

# file /sbin/init 
/sbin/init: symbolic link to /lib/systemd/systemd
zzeroo
sumber
Sistem apa yang Anda uji? Tidak ada yang namanya Debian / Ubuntu dan ini tidak berfungsi pada Debian. Apakah Anda mencobanya di Ubuntu?
terdon
Maaf atas kebingungan ini, maksud saya Debian (wheezy) / atau Ubuntu (14.10.). Output pada debian: file /sbin/init /sbin/init: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, BuildID[sha1]=0x8c68a736c6a4e6fadf22d5ac9debf11e79c6bdcd, stripped berarti kita menggunakan SYSV di sini. Output untuk ubuntu ditunjukkan dalam jawaban saya.
zzeroo
Tepat, jadi solusi Anda tampaknya hanya berfungsi jika ada yang menggunakan pemula dan Ubuntu.
terdon
@terdon: Pada sistem (RHEL, Fedora) yang menjalankan systemd, ia mengembalikan "tautan simbolik ke ... systemd"; pada sistem (Ubuntu) yang menjalankan pemula ini mengembalikan "tautan simbolik ke pemula"; pada sistem (RHEL, Ubuntu, Debian) yang menjalankan SysV init mengembalikan "executable". Walaupun itu bukan survei yang komprehensif, dan metode ini jelas bukan 100% sangat mudah, itu jelas jauh lebih dekat dengan "bekerja untuk setidaknya distro besar" daripada "hanya pemula dan Ubuntu"!
psmears
1
@psmears jika itu juga berfungsi untuk beberapa sistem systemd, itu memang lebih baik (tetapi tidak disebutkan dalam jawaban ini). Saya baru saja menguji pada Debian menjalankan sysvinit, dan tiga Ubuntus (10,04,12,04 dan 14,04, semuanya berjalan pemula) dan file /sbin/initkembali "dieksekusi" pada semua sistem. Ini juga mengembalikan yang sama pada CentOS 5.8, sebuah SLES 10, sebuah Ubuntu 8.04, pada dasarnya setiap sistem tunggal yang bisa saya dapatkan. Jadi, sejauh yang saya tahu itu tidak bekerja untuk pemula dan Ubuntu.
terdon
2

Saya juga memiliki masalah yang sama, dan melakukan banyak tes di beberapa mesin RedHat / CentOS / Debian / Ubuntu / Mint. Inilah yang akhirnya saya dapatkan, dengan hasil yang baik.

  1. Temukan nama yang dapat dieksekusi dengan PID 1:

    ps -p 1

    Jika itu systemd atau pemula, masalah terpecahkan. Jika "init", itu mungkin symlink atau sesuatu selain nama depan. Lanjutkan.

  2. Temukan jalur nyata untuk dieksekusi (hanya berfungsi sebagai root):

    ls -l `which init`

    Jika initsymlink ke Pemula atau systemd, masalah terpecahkan. Kalau tidak, hampir pasti Anda memiliki SysV init. Tapi itu bisa menjadi executable yang salah nama. Lanjutkan.

  3. Temukan paket yang menyediakan executable. Sayangnya, ini tergantung pada distro:

    dpkg-query -S (executable real path) # Debian  
    rpm -qf (executable real path) # RedHat  

Kemudian, jika Anda ingin membuat skrip itu (bagian paling lucu, IMHO), ini adalah one-liners saya (jalankan sebagai root):

ls -l $(which $(ps -p 1 o comm)) | awk '{ system("dpkg-query -S "$NF) }' # Debian  

ls -l $(which $(ps -p 1 o comm)) | awk '{ system("rpm -qf "$NF) }' # RedHat  
Emerson Prado
sumber
1
Tidak semua sistem operasi yang ditentukan memiliki dpkg atau rpm (masalah ini tidak khusus untuk jawaban Anda saja, BTW).
Toby Speight
@ toby-speight Ya, tentu. Catatan saya menyatakan demikian dalam jawaban saya, hanya untuk membuat batasannya jelas.
Emerson Prado
Sedangkan untuk langkah 3, Anda bisa berlari init --versionuntuk mendapatkan informasi.
jarno
1

Ini sangat mudah untuk beberapa sistem init. Untuk systemd:

test -d /run/systemd/system

untuk pemula:

initctl --version | grep -q upstart

untuk hal lain, Anda dapat mengasumsikan berdasarkan distro (launchd di OS X, sysvinit di Debian, OpenRC di Gentoo).

CameronNemo
sumber
"asumsikan berdasarkan distro" tidak berfungsi untuk Debian, di mana setidaknya tiga init yang berbeda didukung ...
Toby Speight
1

Berikut skrip bash untuk melakukan deteksi. Hanya memeriksa untuk pemula dan systemd saat ini, tetapi harus mudah diperluas. Saya telah mengambil ini dari kode yang saya berikan pada skrip pemasangan driver DisplayLink .

detect_distro()
{
  # init process is pid 1
  INIT=`ls -l /proc/1/exe`
  if [[ $INIT == *"upstart"* ]]; then
    SYSTEMINITDAEMON=upstart
  elif [[ $INIT == *"systemd"* ]]; then
    SYSTEMINITDAEMON=systemd
  elif [[ $INIT == *"/sbin/init"* ]]; then
    INIT=`/sbin/init --version`
    if [[ $INIT == *"upstart"* ]]; then
      SYSTEMINITDAEMON=upstart
    elif [[ $INIT == *"systemd"* ]]; then
      SYSTEMINITDAEMON=systemd
    fi
  fi

  if [ -z "$SYSTEMINITDAEMON" ]; then
    echo "WARNING: Unknown distribution, assuming defaults - this may fail." >&2
  else
    echo "Init system discovered: $SYSTEMINITDAEMON"
  fi
}
Ben McCann
sumber
1
Saya pikir penggunaan /procikatan ini ke Linux (jika dikonfigurasi dengan sesuai) dan satu atau dua lainnya - itu tentu jauh dari universal.
Toby Speight
1

Ada banyak jebakan kompatibilitas saat menguji systemd vs initd. Ini sebenarnya berfungsi pada OpenSuSE 42.1:ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'

David Lakatos
sumber
1

Untuk systemd:

if [[ `systemctl is-system-running` =~ running ]]; then echo using systemd; fi
guilhermebr
sumber
downvoting karena jawaban ini tidak memberikan informasi baru atau berbeda dibandingkan dengan banyak jawaban yang ada.
jayhendren
@ jayhendren Saya tidak melihat cuplikan ini di tempat lain. Itu tidak lengkap dengan sendirinya, dan mungkin akan lebih baik berdiri sebagai komentar terhadap jawaban unix.stackexchange.com/a/164092/100397 oleh TvE
roaima
Oh kamu benar @roaima. Itu tidak persis sama dengan yang lain. Saya mencari string yang tidak terlalu spesifik pada halaman itu :)
jayhendren
1
Sejauh ini sepertinya ini jawaban yang paling benar :)
Jack O'Connor
1

Solusi saya: periksa perintah yang berjalan sebagai proses dengan ID 1.

case `cat /proc/1/comm` in
    init)    echo Init ;;
    systemd) echo SystemD ;;
    # add here other patterns
    *)       echo "unknown: '`cat /proc/1/comm`'" ;;
esac

Saat ini saya hanya memiliki akses ke mesin Init dan SystemD, jadi saya tidak tahu bagaimana Upstart atau macOS (OS X) akan terdeteksi, tetapi saya akan terus mencari.

t0r0X
sumber
0
check(){
    if hash systemctl 2>/dev/null;
    then
        echo "there is systemd"
    fi

    if hash initctl 2>/dev/null;
    then
        echo "there is upStart"
    fi

    if [ -f "/etc/inittab"];
    then
        echo "there is systemV"
    fi
}
hxysayhi
sumber