Виявити систему init за допомогою оболонки


90

Це може бути пов’язане з виявленням операційних систем, але мені спеціально потрібна система init, яка зараз використовується в системі.

Fedora 15 і Ubuntu тепер використовують systemd, Ubuntu використовували Upstart (тривалий час за замовчуванням до 15.04), інші використовують варіанти System V.

У мене є додаток, який я пишу, щоб бути демонстратором на різних платформах. Сценарії init динамічно генеруються на основі параметрів, які можна передавати під час налаштування.

Що я хотів би зробити, це лише генерувати сценарій для конкретної системи init, яку вони використовують. Таким чином, сценарій встановлення може запускатися розумно без параметрів як root, а демон може бути "встановлений" автоматично.

Ось що я придумав:

  • Шукайте systemd, upstart тощо в / bin
  • Порівняйте / proc / 1 / comm з systemd, upstart тощо
  • Запитайте користувача

Який би кращий крос / платформний спосіб зробити це?

Вигляд спорідненого: Чи можу я залежати від того, щоб баш був на більшості * nix, чи це залежить від розподілу / ОС?

Цільові платформи:

  • Mac OS
  • Linux (усі дистрибутиви)
  • BSD (усі версії)
  • Solaris, Minix та інші * nix

1
Просто для додання моїх двох центів, bash не встановлений за замовчуванням на FreeBSD.
Чінмай Канчі

@tjameson, ти знайшов більш прямий спосіб? Я шукаю те саме, але відповіді тут - це лише вказівки, а не прямі відповіді. Зокрема, 1) розташування скриптів для пошуку та 2) виявлення діючої системи init, якщо їх встановлено декілька (відповідь Баша відповіла безпосередньо).
n611x007

3
@naxa - коротка відповідь, ні. Довга відповідь, ви можете досить далеко ps -p 1 -o command(друкує шлях до течії init). Для Arch Linux та Fedora (IIRC) це символьне посилання на systemdбінарне (можливо, те саме для всіх systemdсистем). Увімкнено upstart, init --helpбуде надруковано інформацію про використання, а в моєму вікні upstartвказано, де зазначено кому надсилати електронну пошту. У FreeBSD (sysV) це поверне помилку. У інших системах можуть бути подібні підказки, але, задавши це питання, я вирішив просто створити їх для всіх платформ і скласти окремі пакети для кожної.
beatgammit

дякую чудову інформацію! Скачучи з цього, я дізнався, що sudo lsof -a -p 1 -d txtможе дати ще більш точні результати. psможе надрукувати довільне ім’я, тоді як з lsofвами ви отримаєте реальний виконуваний шлях. (Дивіться моє запитання unix.stackexchange.com/questions/102453/… )
n611x007

1
Жодна з відповідей чи коментарів у зв’язаному питанні не пов'язана між собою. Рішення повинні бути застосовні і до вашої справи.
Марко

Відповіді:


30

На друге питання відповідь - ні, і ви повинні ознайомитись з Ресурсами для програмування портативних оболонок .

Що стосується першої частини - насамперед, ви, звичайно, повинні бути обережними. Я б сказав, щоб переконатися в тому, що ви впевнені, що той факт, що у когось встановлена ​​система (наприклад,), не означає, що він фактично використовується як за замовчуванням init. Крім того, перегляд /proc/1/commможе ввести в оману, оскільки деякі установки різних програм init можуть автоматично зробити /sbin/initжорстке посилання на симпосилання або навіть перейменовану версію їх основної програми.

Можливо, найкориснішим може бути перегляд типу скриптів init - адже це саме те, що ви насправді створюєте, незалежно від того, що ними керує.

В якості додаткової примітки ви також можете ознайомитись з OpenRC, який має на меті створити структуру скриптів init, сумісну як з системами Linux, так і з BSD.


2
Що ви маєте на увазі під «поглядом на тип сценаріїв init»? Часто різні системи init розміщують свої сценарії / файли десь окрім того /etc/init, як системний додає їх /etc/systemd. Якби я мав свої сценарії grok ці, це може зайняти трохи часу. О, і дякую за посилання BTW за програмування портативних оболонок.
beatgammit

1
Я мав на увазі сказати, що деякі реалізації init можуть бути скориговані для використання різних типів та місць сценаріїв (наприклад, /etc/rc.d/або /etc/init.d/). І слід правильно налаштувати свою програму під час встановлення, щоб використовувати структуру, яка використовується в даній системі.
rozcietrzewiacz

2
Отже, ви хочете сказати, що не існує надійного способу програмного виявлення системи init? Отримати користувальницьку передачу параметрів, безумовно, безпечніше, але якщо користувач нічого не передає, що було б найкращим способом здогадатися?
beatgammit

Я не маю уявлення, що буде найкращим способом для вашої програми - все залежить від того, в яких системах програма закінчиться. Я не використовував занадто багато дистрибутивів, але намагався поділитися своїми спостереженнями, щоб допомогти вам. Це складний сценарій, який ви збираєтеся спробувати, і я спробував дати вам деякий погляд на полі - ви повинні прийти до остаточної відповіді самостійно або чекати додаткових підказок.
rozcietrzewiacz

Класно, дякую за всю допомогу. Ви точно вказали мені в правильному напрямку.
beatgammit

58

Я сам вступив у цю проблему і вирішив зробити кілька тестів. Я цілком погоджуюся з відповіддю, що слід пакувати для кожного дистрибутива окремо, але іноді виникають практичні питання, які запобігають цьому (не в останню чергу робочій силі).

Тож для тих, хто хоче «автоматично виявити», ось що я дізнався про обмежений набір дистрибутивів (докладніше нижче):

  • Ви можете сказати на початку:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
  • Ви можете сказати systemd з:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
  • Ви можете сказати sys-v init від:

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

Ось мої експерименти із наступним командним рядком:

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

на екземплярах ec2 (включаючи ідентифікатор AMI us-east):

  • ArchLinux: використовує systemd (з 2012.10.06 )
  • CentOS6.4 ami-52009e3b: за допомогою запуску
  • CentOS7 ami-96a818fe: використовує systemd
  • Debian 6 ami-80e915e9: використання sysv-init
  • Debian 7.5 ami-2c886c44: використання sysv-init
  • Debian 7.6 GCE container-vm: використання sysv-init
  • RHEL 6.5 ami-8d756fe4: використання швидкого запуску
  • SLES 11 ami-e8084981: використовуючи sysv-init
  • Ubuntu 10.04 ami-6b350a02: за допомогою запуску
  • Ubuntu 12.04 ami-b08b6cd8: за допомогою запуску
  • Ubuntu 14.04 ami-a427efcc: використання запуску
  • Ubuntu 14.10 і новіші: використовує systemd
  • AWS linux 2014.3.2 ami-7c807d14: використання запуску
  • Fedora 19 ami-f525389c: використовує systemd
  • Fedora 20 ami-21362b48: використовує systemd

Просто, щоб було зрозуміло: я не стверджую, що це нерозумно! , майже напевно, це не так. Також зауважте, що для зручності я використовую bash regexp match, які доступні не скрізь. Сказане зараз досить добре для мене. Однак якщо ви знайдете дистрибутив, де він не вдається, повідомте мене, і я спробую виправити його, якщо є EC2 AMI, який відтворює проблему ...


5
Відповідно до системної документації ( sd_booted (3) ), правильний спосіб перевірити наявність systemd - перевірити, чи /run/systemd/systemіснує каталог .
Робі Басак

1
Додаю до цього детектування launchdсистему init на macOS: [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo noпротестовано на MacBookPro, macOS Sierra Версія 10.12
Тоні

Я також додам if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
зайнятий

18

Використання процесів

Дивлячись на вихід з пари psкоманд, які можуть виявити різні версії systemd& upstart, які можна було б створити так:

вискочити

$ 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

системний

$ 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

Звертаючи увагу на назву процесу, який є PID №1, також потенційно можна пролити світло, на яке використовується система init. У Fedora 19 (який використовує systemd, наприклад:

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

Зверніть увагу, це не так init. У Ubuntu та Upstart все ще /sbin/init.

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

ПРИМІТКА. Але використовуйте це з невеликою обережністю. У камені не встановлено нічого, що говорить про те, що певна система init, що використовується в даному дистрибутиві , повинна мати systemdPID №1.

родовий

$ (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

Подивіться на процеси з ppid 1 (діти процесу init). (Деякі назви дочірніх процесів можуть вказувати на систему init, яка використовується.

Файлова система

Якщо ви допитуєте initвиконуваний файл, ви також можете отримати інформацію з нього. Просто проаналізуйте --versionвихід. Наприклад:

вискочити

$ 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.

системний

$ type init
init is /usr/sbin/init

ПРИМІТКА . Те, що initзнаходиться не в стандартному місці, є дещо натяком. Він завжди знаходиться в /sbin/initсистемах sysvinit.

сисвініт

$ type init
init is /sbin/init

Також це:

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

Висновки

Тому, схоже, немає жодного способу зробити це, але ви можете сформулювати набір перевірок, які б точно визначили, яка система init використовується з досить високою довірою.


Як щодо:pgrep systemd >/dev/null && echo init system: systemd
Марко

Дякую, саме це я шукав: кілька кроків, щоб спробувати визначити систему init.
user369450

1
PID №1 не обов'язково має бути, /usr/lib/systemd/systemdякщо використовується systemd, це помилкове припущення. Наприклад, у моїй системі PID №1 є /sbin/init(я використовую systemd). Це залежить від розподілу.
Марко

У моїй установці kubuntu 15.04, схоже, є і systemd, і sysvinit. Не знаю, чому або що це означає, просто сказавши .. pgrep systemd >/dev/null && echo init system: systemd -> init system: systemdіtype init -> init is /sbin/init
dotnetCarpenter

12

Це не так ефективно, але я, здається, працює.

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

Він надрукує більше рядків, якщо збігається більше одного рядка, який можна було б перекласти на "Не можу здогадатися". Струни, які використовуються в grep, можуть бути дещо змінені, але коли я тестувався в наступному, я завжди отримував один рядок.

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (оновлення Nahant 7) [SYSVINIT]
  • Ubuntu 16.04.1 LTS [СИСТЕМА]
  • Ubuntu 14.04.2 LTS [UPSTART]
  • Випуск Fedora 23 (онлайн-оболонка) [SYSTEMD]
  • Debian GNU / Linux 7 (онлайн-оболонка) [SYSTEMD]

Більш спрощений підхід до того ж рішення (але він зупиняється на першому матчі)

strings /sbin/init |
  awk 'match($0, /(upstart|systemd|sysvinit)/) { print toupper(substr($0, RSTART, RLENGTH));exit; }'

приємна перша відповідь. Ласкаво просимо на unix.se!
Олів'є Дулак

Я щойно спробував це на зображенні докера Gentoo за замовчуванням із встановленим OpenRC, і він повернув SYSVINIT. Згідно з wiki.gentoo.org/wiki/Comppare_of_init_systems типовим для Gentoo є OpenRC, але, схоже, OpenRC використовує sysvinit. Після цього я намагаюся виконати команди OpenRC, я отримую "Ви намагаєтеся запустити службу OpenRC у системі, яка openrc не завантажувалася." Чи є спосіб відрізнити власне sysvinit від OpenRC за допомогою sysvinit?
тудор

9

Іноді це так просто, як використання ls :

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

Я думаю, якщо /sbin/initце не символічне посилання, вам доведеться перевірити подальші пропозиції в інших відповідях.


3
  1. Саме для цього призначені специфічні для дистрибутива пакети. Існує набагато більше, ніж правильно встановити програмне забезпечення, ніж просто виявити систему init. У багатьох дистрибутивах використовується SysVinit, але не всі вони пишуть свої init сценарії однаково. Правильний спосіб вирішити це - включити всі різні варіанти, а потім зв'язати їх за допомогою специфікаційних файлів із специфічними для дистрибутивів іменами залежностей для rpm distros, файлів deb для систем, що базуються на підходах тощо. Майже у всіх дистрибутивах є певна специфікація пакета може писати, що включає залежності, сценарії, скрипти init тощо. Не вигадуйте колесо тут.

  2. Ні. Що повертає нас до 1. Якщо вам потрібен удар, це повинна бути залежність. Ви можете вказати цю перевірку як частину своїх сценаріїв налаштування, але вона також повинна бути в описах пакунків.

Редагувати: Використовуйте прапори на своєму скрипті налаштування, наприклад, --with upstartабо --without sysvinit. Виберіть розумний за замовчуванням, тоді сценарії, які пакують ваше програмне забезпечення для інших дистрибутивів, можуть вибирати це за допомогою інших параметрів.


Хмф, тож виглядає так, що я не можу мати один сценарій, щоб керувати ними всім. Я бачив безліч програм, які використовують autoconf або подібні для обробки міжплатформних речей, але, схоже, це не є правильним інструментом для мого застосування. Чи справді підтримка версій для кожної платформи є єдиним надійним рішенням?
beatgammit

Один сценарій встановлення для керування ними - BadIdea. Це закінчується невдачею більше місць, ніж це працює. Autoconf хороший наскільки це йде. Потрібно наполегливо працювати над збереженням кінця програмного забезпечення максимально універсальним і включайте альтернативні скрипти init у свій пакет. Технічні характеристики пакета для декількох основних дистрибутивів. Якщо ваше програмне забезпечення добре, ви можете залучити інших людей, які допоможуть вам упакувати його для інших систем.
Калеб

@tjameson: Я щойно зрозумів, що забув найважливіший біт. Така річ зазвичай робиться за допомогою перемикачів, переданих до сценарію налаштування. Кожна програма збору / пакету дистрибутива може викликати різні комутатори, а ваш конфігурація / make повинен знати лише, через який комутатор він був переданий, а не виявляти всі можливі конфігурації програмного забезпечення.
Калеб

@ Caleb- Так, у мене вже є така логіка, але хороший улов. Я сподівався на спосіб нюхати систему init, щоб використовувати розумну здогадку, ніж здоровий замовчування.
beatgammit

2

На Gentoo подивіться на 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]

Якщо це так init, то система init є OpenRC. Якщо це так systemd, то система init є systemd.

Ви можете виявити Gentoo за допомогою [ -f /etc/gentoo-release ].

Ще один метод на Gentoo - це використання profile-config show, який покаже, який профіль використовується за замовчуванням. Усі профілі, крім двох, що закінчуються на / systemd, використовують ініціативу OpenRC. Майте на увазі, що вони є лише представниками за замовчуванням, і можливо, що користувач вжив заходів для того, щоб замінити цей дефолт і не може вказувати на фактично використовуваний керуючий інструмент.


Дурне запитання, але як я можу перевірити номер 1?
Faheem Mitha

За допомогою pпараметра (ідентичного -pта --pid) виберіть PID. Наведений фрагмент насправді є результатом для ps u --pid 1.
Хосе М. Бенітес

2

На debian / sbin / init - це символьне посилання на ваш init за замовчуванням

ls -l /sbin/init

дасть вам інформацію, яку ви шукаєте.

$ ls -l /sbin/init 
lrwxrwxrwx 1 root root 20 nov 18 13:15 /sbin/init -> /lib/systemd/systemd

1
Не так. У Ubuntu 14.04 з Upstart це не посилання.
муру

Встановіть іншу систему init і перевірте ще раз.
rmorelli74

А які ще initя можу встановити на Ubuntu 14.04?
муру

... чому б не sysv чи systemd?
rmorelli74

1
Я не хочу зволікати, я просто хочу, щоб ви вказали, до якої версії Debian вона застосовна. (І, можливо, перефразовуйте лише "Debian" на "Debian", щоб воно стало правильним.)
muru

2

Просто перебравшись у процес із PID 1, ви скажете:

strings /proc/1/exe |grep -q sysvinit
strings /proc/1/exe |grep -q systemd

Не всі згадані ОСeS мають procфайлову систему ...
Toby Speight

2

Також може допомогти перевірка дескрипторів файлів. І це від фактично запущеного init (на сьогодні розтягнення Debian дозволяють встановити більше систем 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

Напевно, більш безпечним способом перевірити наявність зайнятості було б check /proc/1/exe, оскільки зайнятий звичайно використовує символьні посилання:

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

Тож перевірка може бути:

{ 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"

Також системи з systemd зазвичай мають каталог /run/systemd/system.
pevik

2

Не знаю про інші системи, ніж Debian (wheezy) / або Ubuntu (14.10.), Але я тестую такі проблеми за допомогою простої старої fileкоманди.

file /sbin/init

дайте це:

/sbin/init: symbolic link to 'upstart'

Системи Debian з systemd(наприклад, sid) показують це:

# file /sbin/init 
/sbin/init: symbolic link to /lib/systemd/systemd

На якій системі ви її протестували? Немає такої речі, як Debian / Ubuntu, і це не працює на Debian. Ви пробували це на Ubuntu?
terdon

Вибачте за цю плутанину, я маю на увазі Debian (wheezy) / або Ubuntu (14.10.). Вихід на 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 означає, що ми тут використовуємо SYSV. Вихідні дані для ubuntu відображаються у моїй відповіді.
zzeroo

Саме так, здається, що ваше рішення спрацює лише в тому випадку, якщо хтось використовує upstart та Ubuntu.
terdon

@terdon: У системах (RHEL, Fedora), що працюють systemd, він повертає "символічне посилання на ... systemd"; у системах (Ubuntu), що працює на початку, він повертає "символічне посилання на початок"; на системах (RHEL, Ubuntu, Debian) під керуванням SysV init він повертає "виконуваний файл". Хоча це навряд чи є всебічним опитуванням, і цей метод явно не є 100% надійним, але він набагато ближче до "працює принаймні для великих дистрибутивів", а не до "тільки на початку та Ubuntu"!
psmears

1
@psmears, якщо він також працює для деяких системних систем, це справді краще (але не зазначено у цій відповіді). Я щойно перевірив Debian, який працює під управлінням sysvinit, і три Ubuntus (10.04,12.04 та 14.04, всі запущені на початку) і file /sbin/initповернувся "виконуваним" на всі системи. Він також повертає те саме на CentOS 5.8, SLES 10, Ubuntu 8.04, в основному в кожній окремій системі, на яку я можу взяти участь. Тож, наскільки я можу сказати, це навіть не працює для запуску та Ubuntu.
terdon

2

У мене також була така ж проблема, і я робив багато тестів на деяких машинах RedHat / CentOS / Debian / Ubuntu / Mint. На цьому я і закінчився з хорошими результатами.

  1. Знайдіть ім'я виконуваного файлу за допомогою PID 1:

    ps -p 1

    Якщо це система або Upstart, проблема вирішена. Якщо це "init", це може бути символьне посилання або щось інше, ніж наперед ім'я. Іди вперед.

  2. Знайдіть реальний шлях для виконуваного файлу (працюйте лише як root):

    ls -l `which init`

    Якщо initє посилання на Upstart або systemd, проблема вирішена. Інакше майже впевнено, що у вас є SysV init. Але це може бути неправильно названий виконуваний файл. Іди вперед.

  3. Знайдіть пакет, який забезпечує виконуваний файл. На жаль, це залежить від дистрофії:

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

Потім, якщо ви хочете, щоб скрипт, що (найсмішніша частина, IMHO), це мої однолінійки (запустіть як 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  

1
Не всі вказані операційні системи мають dpkg або rpm (ця проблема не характерна лише для вашої відповіді, BTW).
Toby Speight

@ toby-speight Так, звичайно. Зауважте, що я це заявив у своїй відповіді, лише щоб зрозуміти обмеження.
Емерсон Прадо

Що стосується кроку 3, ви можете запустити init --versionдля отримання інформації.
jarno

1

Для деяких систем init це дуже просто. Для системних:

test -d /run/systemd/system

для початківців:

initctl --version | grep -q upstart

для всього іншого ви можете просто припустити, що базується на дистрибутиві (запущений на OS X, sysvinit на Debian, OpenRC на Gentoo).


"припустимо, що базується на дистрибутиві" не працює для Debian, де підтримуються щонайменше три різних інтита ...
Toby Speight

1

Ось сценарій bash для виявлення. Наразі він перевіряє наявність початкових та системних систем, але їх слід легко розширити. Я взяв це з коду, який я сприяв сценарію встановлення драйверів 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
}

1
Я вважаю, що використання /procзв’язків у цілому з Linux (якщо це правильно налаштовано) та ще одним-двома іншими - це, безумовно, далеко не універсально.
Toby Speight

1

Під час тестування systemd vs initd є багато підводних можливостей сумісності. Це фактично працює на OpenSuSE 42.1:ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'


1

Для systemd:

if [[ `systemctl is-system-running` =~ running ]]; then echo using systemd; fi

відхилення, тому що ця відповідь не дає жодної нової або різної інформації порівняно з численними існуючими відповідями.
jayhendren

@jayhendren Я не бачу цього фрагмента в інших місцях. Це не є повною самою собою, і, ймовірно, краще стоятиме як коментар проти відповіді unix.stackexchange.com/a/164092/100397 від TvE
roaima

Ой ти прав @roaima. Це не зовсім так, як інші. Я шукав на сторінці не надто конкретний рядок :)
jayhendren

1
Це, здається, є найбільш правильною відповіддю :)
Джек О'Коннор

1

Моє рішення: перевірте команду, що виконується як процес з 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

На даний момент у мене є доступ лише до машин Init та SystemD, тому я не можу сказати, як буде виявлено Upstart або macOS (OS X), але я продовжуватиму пошук.


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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.