Détecter le système init à l'aide du shell

90

Cela a peut-être plus à voir avec la détection des systèmes d'exploitation, mais j'ai particulièrement besoin du système init actuellement utilisé sur le système.

Fedora 15 et Ubuntu utilisent maintenant systemd, Ubuntu utilisait Upstart (valeur par défaut jusqu'à 15.04), tandis que d'autres utilisent des variantes de System V.

J'ai une application que je suis en train d'écrire pour être un démon multi-plateforme. Les scripts d'initialisation sont générés dynamiquement en fonction de paramètres pouvant être transmis lors de la configuration.

Ce que j'aimerais faire, c'est générer uniquement le script pour le système d'init particulier qu'ils utilisent. De cette façon, le script d'installation peut être exécuté raisonnablement sans paramètre en tant que root et le démon peut être "installé" automatiquement.

C'est ce que je suis venu avec:

  • Recherchez systemd, upstart, etc. dans / bin
  • Comparez / proc / 1 / comm avec le systemd, upstart, etc
  • Demander à l'utilisateur

Quel serait le meilleur moyen de procéder de la sorte?

Type de parenté, puis-je compter sur bash pour être sur la majorité de * nix ou est-ce que cela dépend de la distribution / du système d'exploitation?

Plateformes cibles:

  • Mac OS
  • Linux (toutes les distributions)
  • BSD (toutes les versions)
  • Solaris, Minix et autres * nix
beatgammit
la source
1
Juste pour ajouter mes deux cents, bash n’est pas installé par défaut sur FreeBSD.
Chinmay Kanchi
@tjameson, avez-vous trouvé un moyen plus direct? Je cherche la même chose mais les réponses ici ne sont que des directions, pas des réponses directes. En particulier 1) les emplacements de script à rechercher et 2) la détection du système init en vigueur, au cas où plusieurs seraient installés (la réponse a été donnée à bash).
n611x007
3
@naxa - Réponse courte, non. Réponse longue, vous pouvez aller assez loin avec ps -p 1 -o command(affiche le chemin d'accès au courant init). Sur Arch Linux et Fedora (IIRC), il s’agit d’un lien symbolique vers le systemdbinaire (probablement le même sur tous les systemdsystèmes). Le sur upstart, init --helpimprimera les informations d'utilisation, et sur ma boîte, upstartest mentionné où il est dit à qui envoyer un courriel. Sur FreeBSD (sysV), cela retournera une erreur. Il peut y avoir des indices similaires sur d’autres systèmes, mais depuis que je pose cette question, j’ai décidé de les créer pour toutes les plateformes et de créer des packages distincts pour chacune d’elles.
beatgammit
merci super info! Sautant de ce que j’ai appris, cela sudo lsof -a -p 1 -d txtpeut donner des résultats encore plus exacts. pspeut imprimer un nom arbitraire, alors que lsofvous obtiendrez le vrai chemin d’exécutable. (Voir ma question unix.stackexchange.com/questions/102453/… )
n611x007
1
Aucune des réponses ou commentaires de la question liée n'est en rapport avec bash. Les solutions devraient également s'appliquer à votre cas.
Marco

Réponses:

30

Pour la deuxième question, la réponse est non et vous devriez jeter un coup d'œil à Ressources pour la programmation shell portable .

Pour ce qui est de la première partie, il faut d’abord faire attention. Je dirais de faire plusieurs tests pour être sûr - parce que le fait que quelqu'un ait installé systemd (par exemple) ne signifie pas qu'il est réellement utilisé par défaut init. En outre, regarder /proc/1/commpeut être trompeur, car certaines installations de différents programmes init peuvent automatiquement créer /sbin/initun lien symbolique ou même une version renommée de leur programme principal.

Le plus utile serait peut-être d’examiner le type de script init, car c’est ce que vous allez réellement créer, quel que soit son exécution.

En passant , vous pouvez également consulter OpenRC, qui vise à fournir une structure de scripts init compatible avec les systèmes Linux et BSD.

rozcietrzewiacz
la source
2
Qu'entendez-vous par "regardez le type de scripts d'init"? Souvent, différents systèmes init placent leurs scripts / fichiers ailleurs /etc/init, comme le fait systemd /etc/systemd. Si je devais avoir mon script grok ces derniers, cela pourrait prendre un peu de temps. Oh, et merci pour le lien BTW pour la programmation de shell portable.
beatgammit
1
Je voulais dire que certaines implémentations d'init peuvent être ajustées pour utiliser les types et les emplacements de différents scripts d'init (comme /etc/rc.d/ou /etc/init.d/). Et vous devez ajuster correctement votre programme au moment de l'installation pour utiliser la structure utilisée sur le système donné.
rozcietrzewiacz
2
Alors, dites-vous qu’il n’existe aucun moyen fiable de détecter le système init par programme? Demander à l'utilisateur de passer des paramètres est certainement plus sûr, mais si l'utilisateur ne transmet rien, quel serait le meilleur moyen de deviner?
beatgammit
Je ne sais pas du tout quel sera le meilleur moyen pour votre programme - tout dépend des systèmes que le programme exécutera. Je n'ai pas utilisé trop de distributions, mais j'essayais de partager mes observations pour vous aider. Vous êtes sur le point d'essayer un script difficile et j'ai essayé de vous donner un aperçu du terrain - vous devez arriver vous-même à la réponse finale ou attendre d'autres astuces.
rozcietrzewiacz
Cool, merci pour toute votre aide. Vous m'avez certainement orienté dans la bonne direction.
beatgammit
58

J'ai moi-même abordé ce problème et décidé de faire des tests. Je suis tout à fait d’accord avec la réponse selon laquelle il faut emballer séparément chaque distribution, mais il existe parfois des problèmes pratiques qui l’empêchent (notamment le manque de main-d’œuvre).

Donc, pour ceux qui veulent "détecter automatiquement", voici ce que j'ai découvert sur un nombre limité de distributions (voir ci-dessous):

  • Vous pouvez identifier dès le départ:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
  • Vous pouvez dire à systemd de:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
  • Vous pouvez dire à sys-v init de:

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

Voici mes expériences avec la ligne de commande suivante:

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

sur les instances ec2 (j'inclus l'identifiant d'AMI us-east):

  • ArchLinux: using systemd (depuis le 2012.10.06 )
  • CentOS6.4 ami-52009e3b: utilisation de la version récente
  • CentOS7 ami-96a818fe: utilisation de systemd
  • Debian 6 ami-80e915e9: utiliser sysv-init
  • Debian 7.5 ami-2c886c44: utiliser sysv-init
  • Debian 7.6 GCE conteneur-vm: utiliser sysv-init
  • RHEL 6.5 ami-8d756fe4: utilisation récente
  • SLES 11 ami-e8084981: utilisation de sysv-init
  • Ubuntu 10.04 ami-6b350a02: utiliser Upstart
  • Ubuntu 12.04 ami-b08b6cd8: utiliser upstart
  • Ubuntu 14.04 ami-a427efcc: utiliser upstart
  • Ubuntu 14.10 et moins: utilisation de systemd
  • AWS linux 2014.3.2 ami-7c807d14: utilisation de la version récente
  • Fedora 19 ami-f525389c: utilisation de systemd
  • Fedora 20 ami-21362b48: utilisation de systemd

Juste pour être clair: je ne prétends pas que c'est infaillible! ce n'est certainement pas le cas. Notez également que par commodité, j'utilise des correspondances bash regexp, qui ne sont pas disponibles partout. Ce qui précède me suffit pour le moment. Cependant, si vous trouvez une distribution où elle échoue, faites-le moi savoir et j'essaierai de la réparer s'il existe une AMI EC2 qui reproduit le problème ...

TvE
la source
5
Selon la documentation de systemd ( sd_booted (3) ), la méthode correcte pour vérifier systemd consiste à vérifier si le répertoire /run/systemd/systemexiste.
Robie Basak
1
J'ajouterai à cette détection launchd, le système init sur macOS: [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo notesté sur un MacBookPro, macOS Sierra Version 10.12
Tony
Je voudrais aussi ajouter busybox:if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Astrinus
18

Utiliser des processus

En regardant le résultat de quelques pscommandes capables de détecter les différentes versions de systemd& upstart, qui pourraient être conçues comme suit:

parvenu

$ 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

Faire attention au nom du processus qui est le PID # 1 peut aussi potentiellement éclairer le système init utilisé. Sur Fedora 19 (qui utilise systemd, par exemple:

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

Remarquez que non init. Sur Ubuntu avec Upstart c'est encore /sbin/init.

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

NOTE: Mais utilisez ceci avec un peu de prudence. Rien dans la pierre ne dit qu'un système d'initialisation particulier utilisé sur une distribution donnée doit avoir systemdle PID # 1.

générique

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

Regardez les processus avec ppid 1 (enfants du processus init). Certains noms de processus enfants peuvent pointer vers le système init utilisé.

Le système de fichiers

Si vous interrogez l' initexécutable, vous pouvez également obtenir des informations à ce sujet. Simplement analyser la --versionsortie. Par exemple:

parvenu

$ 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

REMARQUE: le fait de initne pas se trouver à son emplacement standard est un indice. Il est toujours situé /sbin/initsur les systèmes sysvinit.

sysvinit

$ type init
init is /sbin/init

Aussi ceci:

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

Conclusions

Il ne semble donc pas exister de solution unique, mais vous pouvez formuler une série de vérifications permettant de déterminer le système d’initialisation que vous utilisez avec un degré de confiance assez élevé.

slm
la source
Que diriez-vous de:pgrep systemd >/dev/null && echo init system: systemd
Marco
Merci, c’est exactement ce que je recherchais: quelques étapes à suivre pour essayer de déterminer le système init.
user369450
1
Le PID n ° 1 ne le sera pas nécessairement /usr/lib/systemd/systemdsi systemd est utilisé, c'est une fausse hypothèse. Sur mon système, par exemple, le PID n ° 1 est /sbin/init(j'utilise systemd). C'est dépendant de la distribution.
Marco
Sur mon installation de kubuntu 15.04, il semble que les deux aient systemd et sysvinit. Je ne sais pas pourquoi ni ce que ça veut dire, rien que dire ... pgrep systemd >/dev/null && echo init system: systemd -> init system: systemdettype init -> init is /sbin/init
dotnetCarpenter le
12

Pas si efficace que ça mais ça a l'air de marcher.

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

Il imprimera plus de lignes si plus d'une chaîne correspond, ce qui pourrait être traduit par "Je ne peux pas deviner". Les chaînes utilisées dans grep peuvent être légèrement modifiées, mais lorsqu’elles ont été testées dans l’os suivant, j’ai toujours une ligne.

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (Mise à jour 7 de Nahant) [SYSVINIT]
  • Ubuntu 16.04.1 LTS [SYSTEMD]
  • Ubuntu 14.04.2 LTS [UPSTART]
  • Fedora version 23 (shell en ligne) [SYSTEMD]
  • Debian GNU / Linux 7 (shell en ligne) [SYSTEMD]

Une approche plus simpliste de la même solution (mais cela s'arrête au premier match)

strings /sbin/init |
  awk 'match($0, /(upstart|systemd|sysvinit)/) { print toupper(substr($0, RSTART, RLENGTH));exit; }'
Marinos An
la source
belle première réponse. Bienvenue sur unix.se!
Olivier Dulac
Je viens d’essayer ceci sur une image de menu fixe par défaut Gentoo avec OpenRC, qui a renvoyé SYSVINIT. Selon wiki.gentoo.org/wiki/Comparison_of_init_systems, la valeur par défaut de Gentoo est OpenRC, mais il semble qu'OpenRC utilise sysvinit. Lorsque je tente ensuite les commandes OpenRC, je reçois le message "Vous essayez d'exécuter un service OpenRC sur un système sur lequel openrc n'a pas démarré." Existe-t-il un moyen de distinguer sysvinit proprement dit d'OpenRC à l'aide de sysvinit?
Tudor
9

Parfois, c'est aussi simple que d'utiliser ls :

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

J'imagine que s'il /sbin/initne s'agit pas d'un lien symbolique, vous devrez vérifier les suggestions suivantes dans les autres réponses.

Skippy le Grand Gourou
la source
3
  1. C’est ce à quoi servent les packages spécifiques à la distribution. Pour installer le logiciel correctement, il ne suffit pas de détecter le système init. Beaucoup de distributions utilisent SysVinit mais toutes n'écrivent pas leurs scripts init de la même manière. Pour résoudre ce problème, la meilleure solution consiste à inclure toutes les variantes et à les regrouper à l’aide de fichiers de spécification avec des noms de dépendances spécifiques à la distribution pour les distributions rpm, les fichiers deb pour les systèmes apt, etc. peut écrire avec des dépendances, des scripts, des scripts d'initialisation, etc. Ne réinventez pas la roue ici.

  2. Ce qui nous ramène à 1. Si vous avez besoin de bash, cela devrait être une dépendance. Vous pouvez spécifier cette vérification dans vos scripts de configuration, mais elle devrait également figurer dans les descriptions de paquet.

Modifier: utilisez des indicateurs sur votre script de configuration, tels que --with upstartou --without sysvinit. Choisissez une valeur par défaut, les scripts qui conditionnent votre logiciel pour d’autres distributions peuvent choisir de l’exécuter avec d’autres options.

Caleb
la source
Hmph, il semble donc que je ne peux pas avoir de solution "un script pour tous les gouverner". J'ai vu beaucoup de programmes qui utilisent autoconf ou similaire pour gérer des tâches multiplates-formes, mais cela ne semble pas être le bon outil pour mon application. La maintenance des versions pour chaque plate-forme est-elle vraiment la seule solution fiable?
beatgammit
Un script d'installation pour tous les gouverner est un BadIdea. Il finit par manquer plus d'endroits que cela ne fonctionne. Autoconf est bon dans la mesure du possible. Travaillez dur pour que votre logiciel soit le plus générique possible et incluez d'autres scripts d'initialisation dans votre package. Spécifications du package d'installation pour plusieurs distributions principales. Si votre logiciel est bon, vous pouvez demander à d’autres personnes de vous aider à le packager pour d’autres systèmes.
Caleb
@tjameson: Je viens de me rendre compte que j'avais oublié l'élément le plus important. Ce genre de chose est généralement fait avec des commutateurs passés au script configure. Les routines de construction / paquetage de chaque distribution peuvent appeler différents commutateurs, et votre configuration / fabrication n'a qu'à savoir quel commutateur elle a été transmise, et non à détecter toutes les configurations logicielles possibles.
Caleb
@ Caleb- Oui, j'ai déjà cette logique là-dedans, mais bonne prise. J'espérais trouver un moyen de renifler le système init pour qu'il utilise une supposition intelligente par défaut.
beatgammit
2

Sur Gentoo, regardez 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]

Si c'est le cas init, le système init est OpenRC. Si c'est le cas systemd, le système init est systemd.

Vous pouvez détecter Gentoo avec [ -f /etc/gentoo-release ].

Une autre méthode sur Gentoo consiste à utiliser profile-config show, qui montrera quel profil par défaut est utilisé. Tous les profils, sauf les deux se terminant par / systemd, utilisent l'init OpenRC. N'oubliez pas que ces éléments ne sont représentatifs que d'un paramètre par défaut et qu'il est possible que l'utilisateur ait pris des mesures pour remplacer ce paramètre par défaut.

casey
la source
Question idiote, mais comment puis-je vérifier le pid 1?
Faheem Mitha
Utilisez l' poption (identique à -pet --pid) pour sélectionner par PID. L'extrait ci-dessus est en fait la sortie pour ps u --pid 1.
José M. Benítez
2

Sur debian / sbin / init est un lien symbolique vers votre init par défaut afin

ls -l /sbin/init

vous donnera l'information que vous cherchez.

$ ls -l /sbin/init 
lrwxrwxrwx 1 root root 20 nov 18 13:15 /sbin/init -> /lib/systemd/systemd
rmorelli74
la source
1
Pas si. Sur Ubuntu 14.04 avec Upstart, ce n'est pas un lien symbolique.
Muru
Installez un autre système init et vérifiez à nouveau.
rmorelli74
Et quel autre initpuis-je installer sur Ubuntu 14.04?
Muru
... pourquoi pas sysv ou systemd?
rmorelli74
1
Je ne veux pas faire de votes, je veux juste que vous précisiez à quelle version de Debian il est applicable. (Et peut-être reformuler "basé sur Debian" en "Debian" uniquement, pour que cela devienne correct.)
muru
2

En entrant simplement dans le processus avec le PID 1, vous apprendrez:

strings /proc/1/exe |grep -q sysvinit
strings /proc/1/exe |grep -q systemd
Cyrille Pontvieux
la source
Tous les OSeS mentionnés n'ont pas un procsystème de fichiers ...
Toby Speight
2

L'inspection des descripteurs de fichiers peut également aider. Et c'est à partir de l'initialisation en cours (l'étirement de Debian permet actuellement d'installer plus de systèmes d'initialisation) :-)

$ 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

Le moyen le plus sûr de rechercher une busybox serait de le faire check /proc/1/exe, puisque busybox utilise généralement des liens symboliques:

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

Donc, vérifier pourrait être:

{ 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
la source
De plus, les systèmes avec systemd ont généralement un répertoire /run/systemd/system.
Pevik
2

Je ne connais pas d’autres systèmes que Debian (Wheezy) / ou Ubuntu (14.10.), Mais j’ai testé de tels problèmes avec la filecommande plain old .

file /sbin/init

donne ça:

/sbin/init: symbolic link to 'upstart'

Les systèmes Debian avec systemd(par exemple, sid) montrent ceci:

# file /sbin/init 
/sbin/init: symbolic link to /lib/systemd/systemd
Zzeroo
la source
Sur quel système l'avez-vous testé? Debian / Ubuntu n’existe pas et cela ne fonctionne pas sous Debian. L'avez-vous essayé sur Ubuntu?
terdon
Désolé pour cette confusion, je veux dire Debian (Wheezy) / ou Ubuntu (14.10.). Sortie sur 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 signifie que nous utilisons SYSV ici. La sortie pour Ubuntu est montrée dans ma réponse.
Zzeroo
Exactement, votre solution ne semble donc fonctionner que s’il s’agit d’utiliser upstart et Ubuntu.
terdon
@terdon: Sur les systèmes (RHEL, Fedora) exécutant systemd, il renvoie "lien symbolique vers ... systemd"; sur les systèmes (Ubuntu) en cours d'exécution upstart, il retourne "link symbolic to upstart"; sur les systèmes (RHEL, Ubuntu, Debian) exécutant SysV init, il retourne "exécutable". Bien que ce ne soit pas une enquête exhaustive et que cette méthode ne soit clairement pas infaillible à 100%, elle est clairement beaucoup plus proche de "fonctionne pour au moins les distributions principales" plutôt que "seulement pour les utilisateurs récents et Ubuntu"!
psmears
1
@psmears si cela fonctionne aussi pour certains systèmes systemd, c'est en effet mieux (mais ce n'est pas mentionné dans cette réponse). Je viens de tester sur sysvinit, Debian et trois Ubuntus (10.04, 12.04 et 14.04, tous démarrant) et je suis file /sbin/initretourné "exécutable" sur tous les systèmes. Il retourne également la même chose sur CentOS 5.8, SLES 10, Ubuntu 8.04, en gros tous les systèmes sur lesquels je peux mettre la main. Donc, autant que je sache, cela ne fonctionne même pas pour Ubuntu et Upstart.
terdon
2

J'ai également eu le même problème et fait beaucoup de tests sur certaines machines RedHat / CentOS / Debian / Ubuntu / Mint. C'est ce que j'ai fini avec, avec de bons résultats.

  1. Trouvez le nom de l'exécutable avec le PID 1:

    ps -p 1

    Si c'est systemd ou Upstart, le problème est résolu. Si c'est "init", il peut s'agir d'un lien symbolique ou de quelque chose d'autre qu'un nom initial. Aller de l'avant.

  2. Trouvez le vrai chemin pour l'exécutable (ne travaillez que comme root):

    ls -l `which init`

    Si initest un lien symbolique vers Upstart ou systemd, le problème est résolu. Sinon, il est presque certain que vous avez initié SysV. Mais cela peut être un exécutable mal nommé. Aller de l'avant.

  3. Trouvez le paquet qui fournit l'exécutable. Malheureusement, cela dépend de la distro:

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

Ensuite, si vous voulez écrire un script (la partie la plus drôle, à mon humble avis), voici mes one-liners (exécutés en tant que 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
la source
1
Tous les systèmes d’exploitation spécifiés n’ont pas dpkg ou rpm (ce problème n’est pas spécifique à votre réponse, BTW).
Toby Speight
@ toby-speight Oui, bien sûr. Notez que je l'ai dit dans ma réponse, juste pour que la limitation soit claire.
Emerson Prado
En ce qui concerne l'étape 3, vous pouvez exécuter init --versionpour obtenir les informations.
Jarno
1

C'est vraiment facile pour certains systèmes init. Pour systemd:

test -d /run/systemd/system

pour le débutant:

initctl --version | grep -q upstart

pour toute autre chose, vous pouvez simplement supposer basé sur la distribution (lancé sur OS X, sysvinit sur Debian, OpenRC sur Gentoo).

CameronNemo
la source
"suppose basé sur la distribution" ne fonctionne pas pour Debian, où au moins trois entrées différentes sont supportées ...
Toby Speight
1

Voici un script bash pour effectuer la détection. Il ne vérifie que les versions récente et système du système, mais devrait être facile à étendre. J'ai pris cela dans le code que j'ai contribué au script d'installation du pilote 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
la source
1
Je pense que l’utilisation de /procliens entre cela et Linux (si correctement configuré) et un ou deux autres - c’est certainement loin d’être universelle.
Toby Speight
1

Il y a de nombreux pièges de compatibilité lors du test de systemd vs initd. Cela fonctionne réellement sur OpenSuSE 42.1:ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'

David Lakatos
la source
1

Pour systemd:

if [[ `systemctl is-system-running` =~ running ]]; then echo using systemd; fi
Guilhermebr
la source
vote négatif parce que cette réponse ne fournit aucune information nouvelle ou différente par rapport aux nombreuses réponses existantes.
Jayhendren
@ Jayhendren Je ne vois pas cet extrait ailleurs. Il n'est pas complet en lui-même et devrait probablement servir de commentaire contre la réponse unix.stackexchange.com/a/164092/100397 de TvE
roaima
Oh tu as raison @roaima. Ce n'est pas exactement la même chose que les autres. J'ai cherché dans la page une chaîne pas trop spécifique :)
jayhendren
1
Cela semble être de loin la réponse la plus correcte :)
Jack O'Connor
1

Ma solution: vérifiez la commande en cours d'exécution en tant que processus avec l'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

Pour le moment, je n'ai accès qu'aux machines Init et SystemD. Je ne peux donc pas dire comment Upstart ou macOS (OS X) seront détectés, mais je vais continuer à chercher.

t0r0X
la source
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
la source