Определить систему инициализации с помощью оболочки

90

Это может иметь большее отношение к обнаружению операционных систем, но мне особенно нужна система инициализации, используемая в настоящее время в системе.

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

У меня есть приложение, которое я пишу, чтобы стать кроссплатформенным демоном. Сценарии инициализации генерируются динамически на основе параметров, которые могут быть переданы при конфигурировании.

То, что я хотел бы сделать, это только создать сценарий для конкретной системы инициализации, которую они используют. Таким образом, скрипт установки может быть запущен без параметров в качестве пользователя root, а демон может быть автоматически «установлен».

Вот что я придумал:

  • Поиск systemd, upstart и т. Д. В / bin
  • Сравните / proc / 1 / comm с systemd, upstart и т. Д.
  • Спросите пользователя

Каков наилучший кроссплатформенный способ сделать это?

Вид связанных, Могу ли я рассчитывать на то, что bash будет работать на большинстве * nix или это зависит от дистрибутива / ОС?

Целевые платформы:

  • Mac OS
  • Linux (все дистрибутивы)
  • BSD (все версии)
  • Solaris, Minix и другие * nix
beatgammit
источник
1
Чтобы добавить мои два цента, bash не устанавливается по умолчанию во FreeBSD.
Чинмай Канчи
@tjameson, ты нашел более прямой путь? Я ищу то же самое, но ответы здесь - просто указания, а не прямые ответы. В частности, 1) местоположения сценариев для поиска и 2) обнаружение действующей системы инициализации, если установлено несколько (ответ bash был получен напрямую).
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
Ни один из ответов или комментариев в связанном вопросе не связан с bash. Решения должны быть применимы и к вашему делу.
Марко

Ответы:

30

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

Что касается первой части - прежде всего, вам, безусловно, нужно быть осторожным. Я бы сказал, чтобы выполнить несколько тестов, чтобы убедиться - потому что тот факт, что кто-то действительно установил systemd (например), не означает, что он действительно используется по умолчанию init. Кроме того, рассмотрение /proc/1/commможет вводить в заблуждение, потому что некоторые установки различных программ инициализации могут автоматически сделать /sbin/initсимволическую ссылку жесткой или даже переименованной версией их основной программы.

Возможно, самой полезной вещью может быть просмотр типа сценариев инициализации - потому что это то, что вы на самом деле будете создавать, независимо от того, что их запускает.

В качестве примечания вы можете также взглянуть на OpenRC, целью которого является предоставить структуру сценариев инициализации, совместимых как с Linux, так и с системами BSD.

rozcietrzewiacz
источник
2
Что вы подразумеваете под «посмотрите на тип сценариев инициализации»? Часто разные системы инициализации помещают свои скрипты / файлы куда-то еще /etc/init, как это делает systemd /etc/systemd. Если бы у меня был такой сценарий, это могло бы занять некоторое время. О, и спасибо за ссылку BTW для программирования портативной оболочки.
beatgammit
1
Я хотел сказать, что некоторые реализации init могут быть настроены так, чтобы использовать различные типы и местоположения сценариев init (например, /etc/rc.d/or /etc/init.d/). И вы должны правильно настроить вашу программу во время установки, чтобы использовать структуру, которая используется в данной системе.
rozcietrzewiacz
2
Итак, вы говорите, что нет надежного способа программного определения системы инициализации? Передача параметров пользователем, безусловно, безопаснее, но если пользователь ничего не передает, каков будет лучший способ угадать?
ритммит
Я понятия не имею, что будет лучшим способом для вашей программы - все зависит от того, на каких системах будет работать программа. Я не использовал слишком много дистрибутивов, но я пытался поделиться своими наблюдениями, чтобы помочь вам. Это сложный сценарий, который вы собираетесь попробовать, и я попытался дать вам некоторое представление о поле - вы должны прийти к окончательному ответу самостоятельно или дождаться новых подсказок.
rozcietrzewiacz
Круто, спасибо за вашу помощь. Вы определенно указали мне в правильном направлении.
ритммит
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 с восточной стороны США):

  • ArchLinux: использование systemd (с 2012.10.06 )
  • CentOS6.4 ami-52009e3b: использование upstart
  • 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: использование upstart
  • SLES 11 ami-e8084981: использование sysv-init
  • Ubuntu 10.04 ami-6b350a02: использование upstart
  • Ubuntu 12.04 ami-b08b6cd8: использование upstart
  • Ubuntu 14.04 ami-a427efcc: использование upstart
  • Ubuntu 14.10 и младше: использование systemd
  • AWS linux 2014.3.2 ami-7c807d14: использование upstart
  • Fedora 19 ami-f525389c: использование systemd
  • Fedora 20 ami-21362b48: использование systemd

Просто чтобы прояснить: я не утверждаю, что это надежно! почти наверняка это не так. Также обратите внимание, что для удобства я использую совпадения регулярных выражений bash, которые не везде доступны. Выше это достаточно хорошо для меня прямо сейчас. Однако, если вы обнаружите дистрибутив, где он не работает, пожалуйста, дайте мне знать, и я постараюсь это исправить, если есть EC2 AMI, который воспроизводит проблему ...

TVE
источник
5
Согласно документации systemd ( sd_booted (3) ), правильный способ проверить systemd - проверить, существует ли каталог /run/systemd/system.
Роби
1
Я добавлю к этому обнаружению launchd, систему инициализации в macOS: [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo noпротестировано на MacBookPro, macOS Sierra Версия 10.12
Тони
Я также добавил бы busybox: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

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

Обращение к названию процесса, который называется PID # 1, также может пролить свет на то, какая система инициализации используется. На 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

ПРИМЕЧАНИЕ: но используйте это с некоторой осторожностью. В камне нет ничего, что говорило бы о том, что конкретная система инициализации, используемая в данном дистрибутиве , должна иметь 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исполняемый файл, вы также можете получить от него некоторую информацию. Просто разбирая --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.

Systemd

$ type init
init is /usr/sbin/init

ПРИМЕЧАНИЕ. Тот факт, что initон не находится в его стандартном расположении, является подсказкой. Он всегда находится в /sbin/initсистемах sysvinit.

Sysvinit

$ type init
init is /sbin/init

Также это:

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

Выводы

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

SLM
источник
Как насчет:pgrep systemd >/dev/null && echo init system: systemd
Марко
Спасибо, это именно то, что я искал: некоторые шаги, чтобы попытаться определить систему инициализации.
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 [SYSTEMD]
  • 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/Comparison_of_init_systems для Gentoo по умолчанию используется OpenRC, но, похоже, OpenRC использует sysvinit. Затем, когда я пытаюсь выполнить команды OpenRC, я получаю сообщение «Вы пытаетесь запустить службу OpenRC в системе, которая openrc не загрузилась». Есть ли способ различить собственно sysvinit и OpenRC, используя sysvinit?
tudor
9

Иногда это так же просто, как использовать ls :

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

Я думаю, если /sbin/initэто не символическая ссылка, вам придется проверить дальнейшие предложения в других ответах.

Скиппи ле Гран Гуру
источник
3
  1. Для этого предназначены специальные дистрибутивные пакеты. Правильная установка программного обеспечения - это гораздо больше, чем просто обнаружение системы инициализации. Многие дистрибутивы используют SysVinit, но не все пишут свои сценарии инициализации одинаково. Правильный способ решить эту проблему - включить все различные варианты, а затем объединить их, используя файлы спецификаций с именами зависимых от дистрибутивов зависимостей для дистрибутивов rpm, файлы deb для систем на основе apt и т. Д. Почти во всех дистрибутивах есть какая-то спецификация пакета, которую вы Можно написать, что включает в себя зависимости, сценарии, сценарии инициализации и т. д. Не изобретайте колесо здесь.

  2. Нет. Что возвращает нас к 1. Если вам нужен bash, это должна быть зависимость. Вы можете указать эту проверку как часть ваших скриптов configure, но она также должна быть в описании пакета.

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

Калеб
источник
Хммм, похоже, у меня не может быть решения «один сценарий, чтобы управлять ими всеми». Я видел много программ, которые используют autoconf или аналогичные для обработки кроссплатформенных вещей, но не похоже, что это правильный инструмент для моего приложения. Является ли поддержка версий для каждой платформы действительно единственным надежным решением?
beatgammit
Один сценарий установки, который управляет ими, - это BadIdea. Это заканчивает тем, что терпит неудачу больше мест, чем это работает. Autoconf хорош, насколько это возможно. Приложите все усилия к тому, чтобы ваш конец программного обеспечения был как можно более универсальным и включите в свой пакет альтернативные сценарии инициализации. Настройка пакета спецификаций для нескольких основных дистрибутивов. Если у вас хорошее программное обеспечение, вы можете попросить других людей помочь вам с его упаковкой для других систем.
Калеб
@tjameson: я только что понял, что забыл самый важный бит. Такого рода вещи обычно выполняются с помощью переключателей, передаваемых в скрипт конфигурации. Процедуры сборки / упаковки каждого дистрибутива могут вызывать разные коммутаторы, и ваш configure / make должен только знать, через какой коммутатор он был передан, а не обнаруживать все возможные конфигурации программного обеспечения.
Калеб
@ Калеб: Да, у меня уже есть эта логика, но хороший улов. Я надеялся, что способ обнюхать систему инициализации, чтобы использовать разумное предположение, чем здравый смысл.
ритммит
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, то система инициализации есть OpenRC. Если это так systemd, то система инициализации есть systemd.

Вы можете обнаружить Gentoo с помощью [ -f /etc/gentoo-release ].

В Gentoo используется другой метод profile-config show, который покажет, какой профиль по умолчанию используется. Все профили, кроме двух, заканчивающихся на / systemd, используют инициализацию OpenRC. Имейте в виду, что они являются только репрезентативными по умолчанию, и вполне возможно, что пользователь предпринял шаги для отмены этого по умолчанию и может не указывать на фактически используемый менеджер инициализации.

Casey
источник
Тупой вопрос, а как мне проверить pid 1?
Фахим Митха
Используйте 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
rmorelli74
источник
1
Не так. В Ubuntu 14.04 с Upstart это не символическая ссылка.
Муру
Установите другую систему инициализации и проверьте снова.
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
Сириль Понтвье
источник
Не у всех упомянутых OSeS есть procфайловая система ...
Тоби Спейт
2

Также может помочь проверка файловых дескрипторов. И это из фактического запуска init (Debian stretch в настоящее время позволяет устанавливать больше систем инициализации) :-)

$ 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, так как busybox обычно использует символические ссылки:

$ 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"
pevik
источник
Также системы с 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
zzeroo
источник
На какой системе вы это тестировали? Debian / Ubuntu не существует, и это не работает в Debian. Вы пробовали это на Ubuntu?
Тердон
Извините за эту путаницу, я имею в виду 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), запускающих upstart, он возвращает «символическую ссылку на upstart»; в системах (RHEL, Ubuntu, Debian), в которых запущен SysV init, возвращается «исполняемый файл». Хотя это вряд ли всесторонний обзор, и этот метод явно не на 100% надежен, он явно гораздо ближе к «работает по крайней мере для основных дистрибутивов», чем к «только выскочке и Ubuntu»!
psmears
1
@psmears, если он также работает для некоторых систем systemd, это действительно лучше (но не упоминается в этом ответе). Я только что протестировал Debian с sysvinit и тремя Ubuntus (10.04, 12.04 и 14.04, все с upstart) и 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

    Если это systemd или 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  

Затем, если вы хотите написать это (самая забавная часть, ИМХО), это мои однострочники (запускаются с правами 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 (эта проблема относится не только к вашему ответу, кстати).
Тоби Спейт
@ toby-speight Да, конечно. Заметьте, я так и сказал в своем ответе, просто чтобы прояснить ограничение.
Эмерсон Прадо
Что касается шага 3, вы можете запустить, init --versionчтобы получить информацию.
Ярно
1

Это действительно легко для некоторых систем инициализации. Для systemd:

test -d /run/systemd/system

для выскочки:

initctl --version | grep -q upstart

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

CameronNemo
источник
«Предположим, основанный на дистрибутиве» не работает для Debian, где поддерживаются как минимум три разных init ...
Toby Speight
1

Вот скрипт bash для обнаружения. На данный момент он проверяет только upstart и systemd, но его легко расширить. Я взял это из кода, который я внес в скрипт установки драйвера 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 (если он настроен соответствующим образом) и одним или двумя другими - это, безусловно, далеко не универсально.
Тоби Спейт
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
guilhermebr
источник
отрицательное голосование, потому что этот ответ не дает никакой новой или иной информации по сравнению с многочисленными существующими ответами.
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), но я продолжу поиск.

t0r0X
источник
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
источник