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
sumber
ps -p 1 -o command
(mencetak jalur ke arusinit
). Di Arch Linux dan Fedora (IIRC), itu adalah symlink kesystemd
biner (mungkin sama pada semuasystemd
sistem). Padaupstart
,init --help
akan mencetak informasi penggunaan, dan pada kotak saya,upstart
disebutkan 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.sudo lsof -a -p 1 -d txt
mungkin memberikan hasil yang lebih tepat.ps
dapat mencetak nama arbitrer, sedangkan denganlsof
Anda akan mendapatkan jalur yang dapat dieksekusi nyata. (Lihat pertanyaan saya unix.stackexchange.com/questions/102453/… )Jawaban:
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/comm
dapat menyesatkan, karena beberapa instalasi dari berbagai program init dapat secara otomatis membuat/sbin/init
symlink 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.
sumber
/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./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.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:
Anda dapat memberi tahu systemd dari:
Anda dapat memberi tahu sys-v init dari:
Berikut ini eksperimen saya dengan baris perintah berikut:
pada contoh EC2 (saya termasuk id AMI us-east):
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 ...
sumber
/run/systemd/system
ada.launchd
, sistem init pada macOS:[[ $(ps 1) =~ 'launchd' ]] && echo yes || echo no
diuji pada MacBookPro, macOS Sierra Versi 10.12if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Menggunakan proses
Melihat output dari beberapa
ps
perintah yang dapat mendeteksi berbagai versisystemd
&upstart
, yang dapat dibuat seperti:pemula
systemd
Memperhatikan nama proses yang PID # 1 juga berpotensi menjelaskan sistem init yang sedang digunakan. Pada Fedora 19 (yang menggunakan
systemd
, misalnya:Perhatikan itu bukan
init
. Di Ubuntu dengan Upstart masih/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
systemd
sebagai PID # 1.umum
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
init
executable, Anda bisa mendapatkan beberapa info darinya. Cukup parsing--version
output. Sebagai contoh:pemula
systemd
CATATAN: Fakta yang
init
tidak ada di lokasi standarnya adalah sedikit petunjuk. Itu selalu terletak di/sbin/init
sistem sysvinit.sysvinit
Ini juga:
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.
sumber
pgrep systemd >/dev/null && echo init system: systemd
/usr/lib/systemd/systemd
jika systemd digunakan, itu adalah asumsi yang salah. Di sistem saya, misalnya, PID # 1 adalah/sbin/init
(saya menggunakan systemd). Itu tergantung distribusi.pgrep systemd >/dev/null && echo init system: systemd -> init system: systemd
dantype init -> init is /sbin/init
Tidak seefisien itu, tetapi saya sepertinya berhasil.
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.
Pendekatan yang lebih sederhana dari solusi yang sama (tetapi berhenti pada pertandingan pertama)
sumber
Terkadang semudah menggunakan
ls
:Saya kira jika
/sbin/init
bukan tautan simbolis, Anda harus memeriksa saran berikut lebih lanjut di jawaban lain.sumber
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.
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 upstart
atau--without sysvinit
. Pilih default waras, maka skrip yang mengemas perangkat lunak Anda untuk distro lain dapat memilih untuk menjalankan ini dengan opsi lain.sumber
Di Gentoo, lihat pid 1:
Jika ya
init
, maka sistem init adalahOpenRC
. Jika yasystemd
, maka sistem init adalahsystemd
.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.sumber
p
opsi (identik dengan-p
dan--pid
) untuk memilih dengan PID. Cuplikan di atas sebenarnya adalah output untukps u --pid 1
.Pada debian / sbin / init adalah symlink ke init default Anda
akan memberi Anda info yang Anda cari.
sumber
init
bisa saya instal di Ubuntu 14.04?Cukup dengan memasuki proses dengan PID 1 akan memberi tahu Anda:
sumber
proc
sistem file ...Juga memeriksa deskriptor file dapat membantu. Dan itu dari benar-benar menjalankan init (Debian stretch saat ini memungkinkan untuk menginstal lebih banyak sistem init) :-)
Mungkin cara yang lebih aman untuk memeriksa busybox adalah dengan
check /proc/1/exe
, karena busybox biasanya menggunakan symlink:Jadi cek bisa:
sumber
/run/systemd/system
.Tidak tahu tentang sistem lain maka Debian (wheezy) / atau Ubuntu (14.10.) Tapi saya menguji masalah tersebut dengan
file
perintah lama biasa .berikan ini:
Sistem Debian dengan
systemd
(misalnya sid) menunjukkan ini:sumber
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.file /sbin/init
kembali "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.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.
Temukan nama yang dapat dieksekusi dengan PID 1:
Jika itu systemd atau pemula, masalah terpecahkan. Jika "init", itu mungkin symlink atau sesuatu selain nama depan. Lanjutkan.
Temukan jalur nyata untuk dieksekusi (hanya berfungsi sebagai root):
Jika
init
symlink ke Pemula atau systemd, masalah terpecahkan. Kalau tidak, hampir pasti Anda memiliki SysV init. Tapi itu bisa menjadi executable yang salah nama. Lanjutkan.Temukan paket yang menyediakan executable. Sayangnya, ini tergantung pada distro:
Kemudian, jika Anda ingin membuat skrip itu (bagian paling lucu, IMHO), ini adalah one-liners saya (jalankan sebagai root):
sumber
init --version
untuk mendapatkan informasi.Ini sangat mudah untuk beberapa sistem init. Untuk systemd:
untuk pemula:
untuk hal lain, Anda dapat mengasumsikan berdasarkan distro (launchd di OS X, sysvinit di Debian, OpenRC di Gentoo).
sumber
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 .
sumber
/proc
ikatan ini ke Linux (jika dikonfigurasi dengan sesuai) dan satu atau dua lainnya - itu tentu jauh dari universal.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'
sumber
Untuk
systemd
:sumber
Solusi saya: periksa perintah yang berjalan sebagai proses dengan ID 1.
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.
sumber
sumber