Ermitteln Sie das Init-System mithilfe der Shell


90

Dies hat möglicherweise mehr mit der Erkennung von Betriebssystemen zu tun, aber ich benötige speziell das derzeit auf dem System verwendete Init-System.

Fedora 15 und Ubuntu verwenden jetzt systemd, Ubuntu verwendete Upstart (Standardeinstellung für lange Zeit bis 15.04), während andere Varianten von System V verwenden.

Ich habe eine Anwendung, die ich schreibe, um ein plattformübergreifender Daemon zu sein. Die Init-Skripte werden dynamisch basierend auf Parametern generiert, die bei configure übergeben werden können.

Ich möchte nur das Skript für das jeweilige verwendete Init-System generieren. Auf diese Weise kann das Installationsskript ohne Parameter als root ausgeführt und der Dämon automatisch "installiert" werden.

Das habe ich mir ausgedacht:

  • Suchen Sie in / bin nach systemd, upstart usw.
  • Vergleichen Sie / proc / 1 / comm mit systemd, upstart usw
  • Fragen Sie den Benutzer

Was wäre der beste Weg, dies auf einer Plattform zu tun?

Art des Zusammenhangs, Kann ich mich darauf verlassen, dass bash von der Mehrheit von * nix abhängig ist oder ist es von der Distribution / dem Betriebssystem abhängig?

Zielplattformen:

  • Mac OS
  • Linux (alle Distributionen)
  • BSD (alle Versionen)
  • Solaris, Minix und andere * nix

1
Nur um meine zwei Cent hinzuzufügen, ist bash nicht standardmäßig auf FreeBSD installiert.
Chinmay Kanchi

@tjameson, hast du einen direkteren Weg gefunden? Ich suche das Gleiche, aber die Antworten hier sind nur Anweisungen, keine direkten Antworten. Insbesondere 1) zu durchsuchende Skriptpositionen und 2) Erkennung des aktiven Init-Systems, falls mehrere installiert sind (bash wurde direkt beantwortet).
n611x007

3
@naxa - Kurze Antwort, nein. Lange Antwort, man kann ziemlich weit kommen ps -p 1 -o command(druckt den Pfad zur aktuellen init). Unter Arch Linux und Fedora (IIRC) ist dies ein Symlink zur systemdBinärdatei (wahrscheinlich auf allen systemdSystemen gleich). Ein upstart, init --helpdruckt Nutzungsinformationen aus und auf meiner Box upstartwird angegeben, an wen eine E-Mail gesendet werden soll. Unter FreeBSD (sysV) gibt dies einen Fehler zurück. Es mag ähnliche Hinweise auf anderen Systemen geben, aber seitdem ich diese Frage gestellt habe, habe ich beschlossen, sie nur für alle Plattformen zu erstellen und für jede einzelne Plattform separate Pakete zu erstellen.
Beatgammit

danke super info! Ich habe gelernt, sudo lsof -a -p 1 -d txtdass dies zu noch genaueren Ergebnissen führen kann. pskann einen beliebigen Namen ausgeben, wobei lsofSie mit den tatsächlichen ausführbaren Pfad erhalten. (Siehe meine Frage unter unix.stackexchange.com/questions/102453/… )
n611x007

1
Keine der Antworten oder Kommentare in der verknüpften Frage ist bashbezogen. Die Lösungen sollten auch auf Ihren Fall anwendbar sein.
Marco

Antworten:


30

Bei der zweiten Frage lautet die Antwort " Nein", und Sie sollten sich Ressourcen für die portable Shell-Programmierung ansehen .

Was den ersten Teil angeht, muss man auf jeden Fall vorsichtig sein. Ich würde sagen , mehrere Tests durchführen , um sicherzustellen, dass - weil die Tatsache , dass jemand hat (. Für ex) systemd installiert ist , bedeutet nicht , es tatsächlich als Standard verwendet wird init. Außerdem /proc/1/commkann das Betrachten irreführend sein, da einige Installationen verschiedener Init-Programme automatisch /sbin/initeinen Symlink-Hardlink oder sogar eine umbenannte Version ihres Hauptprogramms erstellen können .

Vielleicht ist es am nützlichsten, sich den Typ der Init-Skripte anzuschauen - denn das ist es, was Sie tatsächlich erstellen werden, unabhängig davon, was sie ausführen.

Als Randnotiz können Sie auch einen Blick auf OpenRC werfen, das darauf abzielt, eine Struktur von Init-Skripten bereitzustellen, die sowohl mit Linux- als auch BSD-Systemen kompatibel ist.


2
Was meinen Sie mit "Sehen Sie sich den Init-Skript-Typ an"? Oft legen verschiedene Init-Systeme ihre Skripte / Dateien irgendwo anders ab /etc/init, wie systemd sie einfügt /etc/systemd. Wenn ich mein Drehbuch so schreiben würde, könnte es eine Weile dauern. Oh, und danke für den Link BTW für die portable Shell-Programmierung.
Beatgammit

1
Ich wollte damit sagen, dass einige Init-Implementierungen angepasst werden können, um die Typen und Speicherorte verschiedener Init-Skripte (wie /etc/rc.d/oder /etc/init.d/) zu verwenden. Und Sie sollten Ihr Programm zur Installationszeit richtig anpassen , um die auf dem gegebenen System verwendete Struktur zu nutzen.
Rozcietrzewiacz

2
Wollen Sie damit sagen, dass es keine zuverlässige Möglichkeit gibt, das Init-System programmgesteuert zu erkennen? Das Eingeben von Parametern durch den Benutzer ist sicherlich sicherer. Wenn der Benutzer jedoch nichts eingibt, wie lässt sich dies am besten erraten?
Beatgammit

Ich habe keine Ahnung, was der beste Weg für Ihr Programm sein wird - es hängt alles davon ab, auf welchen Systemen das Programm letztendlich ausgeführt wird. Ich habe nicht zu viele Distributionen verwendet, aber ich habe versucht, meine Beobachtungen zu teilen, um Ihnen zu helfen. Es ist ein schwieriges Skript, das Sie versuchen werden, und ich habe versucht, Ihnen einen Einblick in das Feld zu geben - Sie müssen selbst zur endgültigen Antwort kommen oder auf weitere Hinweise warten.
Rozcietrzewiacz

Cool, danke für all deine Hilfe. Sie haben mich definitiv in die richtige Richtung gelenkt.
Beatgammit

58

Ich habe mich selbst mit diesem Problem befasst und mich dazu entschlossen, einige Tests durchzuführen. Ich stimme voll und ganz der Antwort zu, dass man für jede Distribution ein separates Paket erstellen sollte, aber manchmal gibt es praktische Probleme, die dies verhindern (nicht zuletzt Arbeitskräfte).

Also für diejenigen, die automatisch erkennen möchten, ist hier, was ich auf einem begrenzten Satz von Distributionen herausgefunden habe (mehr unten):

  • Sie können Emporkömmling von sagen:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
  • Sie können sagen, systemd von:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
  • Sie können sys-v init mitteilen von:

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

Hier sind meine Experimente mit der folgenden Befehlszeile:

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

auf ec2-Instanzen (ich beziehe die AMI-ID für USA-Ost ein):

  • ArchLinux: using systemd (seit 2012.10.06 )
  • CentOS6.4 ami-52009e3b: Verwenden von Upstart
  • CentOS7 ami-96a818fe: using systemd
  • Debian 6 ami-80e915e9: unter Verwendung von sysv-init
  • Debian 7.5 ami-2c886c44: unter Verwendung von sysv-init
  • Debian 7.6 GCE container-vm: Verwenden von sysv-init
  • RHEL 6.5 ami-8d756fe4: Verwenden von Upstart
  • SLES 11 ami-e8084981: using sysv-init
  • Ubuntu 10.04 ami-6b350a02: mit upstart
  • Ubuntu 12.04 ami-b08b6cd8: mit upstart
  • Ubuntu 14.04 ami-a427efcc: mit upstart
  • Ubuntu 14.10 und jünger: mit systemd
  • AWS Linux 2014.3.2 ami-7c807d14: Verwenden von Upstart
  • Fedora 19 ami-f525389c: using systemd
  • Fedora 20 ami-21362b48: using systemd

Nur um klar zu sein: Ich behaupte nicht, dass dies narrensicher ist! ist es mit ziemlicher Sicherheit nicht. Beachten Sie auch, dass ich der Einfachheit halber Bash-Regexp-Übereinstimmungen verwende, die nicht überall verfügbar sind. Das oben Genannte ist gerade gut genug für mich. Wenn Sie jedoch eine Distribution finden, bei der ein Fehler auftritt, lassen Sie es mich bitte wissen, und ich werde versuchen, den Fehler zu beheben, wenn ein EC2-AMI das Problem reproduziert ...


5
Gemäß der Systemd-Dokumentation ( sd_booted (3) ) besteht die richtige Möglichkeit, nach Systemd zu suchen , darin, zu überprüfen, ob das Verzeichnis /run/systemd/systemvorhanden ist.
Robie Basak

1
Ich werde zu dieser Erkennung launchddas Init-System unter macOS hinzufügen : [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo noGetestet auf einem MacBookPro, macOS Sierra Version 10.12
Tony

Ich würde auch busybox hinzufügen:if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Astrinus

18

Prozesse nutzen

Schauen Sie sich die Ausgabe einiger psBefehle an, die die verschiedenen Versionen von systemd& erkennen können. Diese upstartkönnten folgendermaßen aussehen:

Emporkömmling

$ 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

Wenn Sie auf den Namen des Prozesses achten, der PID # 1 ist, kann dies möglicherweise auch Aufschluss darüber geben, welches Init-System verwendet wird. Auf Fedora 19 (das systemdzum Beispiel verwendet:

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

Beachten Sie, dass es nicht ist init. Auf Ubuntu mit Upstart ist es immer noch /sbin/init.

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

HINWEIS: Verwenden Sie dies jedoch mit Vorsicht. Es ist nichts in Stein gemeißelt, was besagt, dass ein bestimmtes Init-System, das in einer bestimmten Distribution verwendet wird , systemddie PID # 1 haben muss.

generisch

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

Sehen Sie sich Prozesse mit ppid 1 an (Kinder des init-Prozesses). (Einige der) untergeordneten Prozessnamen verweisen möglicherweise auf das verwendete Init-System.

Das Dateisystem

Wenn Sie die initausführbare Datei abfragen , können Sie auch einige Informationen daraus abrufen. Analysieren Sie einfach die --versionAusgabe. Zum Beispiel:

Emporkömmling

$ 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

HINWEIS: Die Tatsache, dass initsich nicht an der Standardposition befindet, ist ein kleiner Hinweis. Es befindet sich immer /sbin/initauf Sysvinit-Systemen.

sysvinit

$ type init
init is /sbin/init

Auch diese:

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

Schlussfolgerungen

Es scheint also keine Möglichkeit zu geben, dies zu tun, aber Sie könnten eine Reihe von Überprüfungen formulieren, die genau bestimmen, welches Init-System Sie mit einem relativ hohen Maß an Sicherheit verwenden.


Wie wäre es mit:pgrep systemd >/dev/null && echo init system: systemd
Marco

Vielen Dank, genau das habe ich gesucht: einige Schritte, um zu versuchen, das Init-System zu bestimmen.
user369450

1
Die PID # 1 muss nicht unbedingt sein, /usr/lib/systemd/systemdwenn systemd verwendet wird, es ist eine falsche Annahme. Auf meinem System ist zum Beispiel PID # 1 /sbin/init(ich verwende systemd). Es ist vertriebsabhängig.
Marco

Auf meiner Kubuntu 15.04-Installation habe ich anscheinend sowohl systemd als auch sysvinit. Ich weiß nicht warum oder was das bedeutet, nur sagen .. pgrep systemd >/dev/null && echo init system: systemd -> init system: systemdundtype init -> init is /sbin/init
dotnetCarpenter

12

Nicht so effizient, aber es scheint zu funktionieren.

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

Es werden mehr Zeilen gedruckt, wenn mehr als eine Zeichenfolge übereinstimmt, was in "Kann nicht raten" übersetzt werden könnte. Die in grep verwendeten Strings könnten leicht modifiziert werden, aber wenn ich sie im folgenden Betriebssystem teste, bekomme ich immer eine Zeile.

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (Nahant Update 7) [SYSVINIT]
  • Ubuntu 16.04.1 LTS [SYSTEMD]
  • Ubuntu 14.04.2 LTS [UPSTART]
  • Fedora Release 23 (Online-Shell) [SYSTEMD]
  • Debian GNU / Linux 7 (Online-Shell) [SYSTEMD]

Ein vereinfachterer Ansatz derselben Lösung (der jedoch beim ersten Spiel aufhört)

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

nette erste antwort. Willkommen bei unix.se!
Olivier Dulac

Ich habe dies gerade auf einem Gentoo-Standard-Docker-Image mit installiertem OpenRC versucht und es gab SYSVINIT zurück. Laut wiki.gentoo.org/wiki/Comparison_of_init_systems ist der Standard für Gentoo OpenRC, aber es scheint, dass OpenRC sysvinit verwendet. Wenn ich dann OpenRC-Befehle versuche, erhalte ich die Meldung "Sie versuchen, einen OpenRC-Dienst auf einem System auszuführen, auf dem openrc nicht gestartet wurde." Gibt es eine Möglichkeit, mit sysvinit zwischen sysvinit proper und OpenRC zu unterscheiden?
Tudor

9

Manchmal ist es so einfach wie ls :

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

Ich denke, wenn /sbin/inites sich nicht um einen symbolischen Link handelt, müssen Sie die folgenden Vorschläge in anderen Antworten überprüfen.


3
  1. Dies ist, wofür distro-spezifische Pakete sind. Die ordnungsgemäße Installation von Software ist viel mehr als nur das Erkennen des Init-Systems. Viele Distributionen verwenden SysVinit, aber nicht alle schreiben ihre Init-Skripte auf die gleiche Weise. Der richtige Weg, dies zu lösen, besteht darin, alle verschiedenen Varianten einzuschließen und sie dann mit Spezifikationsdateien mit distro-spezifischen Abhängigkeitsnamen für rpm-Distributionen, deb-Dateien für apt-basierte Systeme usw. zu bündeln. Fast alle Distributionen haben eine Art von Paketspezifikation, die Sie haben kann schreiben, dass Abhängigkeiten, Skripte, Init-Skripte usw. enthält. Erfinden Sie das Rad hier nicht neu.

  2. Nein, das bringt uns zurück zu 1. Wenn Sie bash brauchen, sollte es eine Abhängigkeit sein. Sie können diese Prüfung als Teil Ihrer Konfigurationsskripts angeben, sie sollte jedoch auch in den Paketbeschreibungen enthalten sein.

Bearbeiten: Verwenden Sie in Ihrem Konfigurationsskript Flags wie --with upstartoder --without sysvinit. Wählen Sie eine vernünftige Standardeinstellung, und die Skripte, die Ihre Software für andere Distributionen verpacken, können diese mit anderen Optionen ausführen.


Hmph, es sieht also so aus, als ob ich keine "Ein-Skript-Lösung für alle Regeln" haben kann. Ich habe viele Programme gesehen, die Autoconf oder ähnliches verwenden, um plattformübergreifende Inhalte zu verarbeiten, aber es scheint nicht das richtige Tool für meine Anwendung zu sein. Ist die Verwaltung der Versionen für jede Plattform wirklich die einzige zuverlässige Lösung?
Beatgammit

Ein Installationsskript, das sie alle beherrscht, ist ein BadIdea. Es scheitert an mehr Stellen, als es funktioniert. Autoconf ist soweit gut. Arbeiten Sie hart daran, Ihr Ende der Software so allgemein wie möglich zu halten und fügen Sie alternative Init-Skripte in Ihr Paket ein. Setup-Paketspezifikationen für mehrere wichtige Distributionen. Wenn Ihre Software gut ist, können Sie andere Leute bitten, Sie beim Packen für andere Systeme zu unterstützen.
Caleb

@tjameson: Mir ist gerade klar geworden, dass ich das Wichtigste vergessen habe. Dies geschieht normalerweise mit Schaltern, die an das configure-Skript übergeben werden. Die Build- / Package-Routinen jeder Distribution können unterschiedliche Switches aufrufen, und Ihr configure / make muss nur wissen, welcher Switch übergeben wurde, und nicht alle möglichen Softwarekonfigurationen erkennen.
Caleb

@ Caleb- Ja, ich habe diese Logik schon drin, aber guten Fang. Ich hatte gehofft, das Init-System auf eine Weise zu untersuchen, die eine intelligente Vermutung als eine vernünftige Standardeinstellung darstellt.
Beatgammit

2

Schauen Sie sich unter Gentoo PID 1 an:

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]

Wenn initja, dann ist das Init-System OpenRC. Wenn systemdja, dann ist das Init-System systemd.

Sie können Gentoo mit erkennen [ -f /etc/gentoo-release ].

Eine andere Methode unter Gentoo ist die Verwendung profile-config show, mit der angezeigt wird, welches Standardprofil verwendet wird. Alle Profile außer den beiden, die auf / systemd enden, verwenden den OpenRC-Init. Beachten Sie, dass diese nur für eine Standardeinstellung repräsentativ sind und dass der Benutzer möglicherweise Schritte unternommen hat, um diese Standardeinstellung zu überschreiben, und dass sie möglicherweise nicht den tatsächlich verwendeten init-Manager angibt.


Dumme Frage, aber wie überprüfe ich auf PID 1?
Faheem Mitha

Verwenden Sie die pOption (identisch mit -pund --pid), um nach PID auszuwählen. Das obige Snippet ist eigentlich die Ausgabe für ps u --pid 1.
José M. Benítez

2

Unter debian / sbin / init befindet sich ein Symlink zu Ihrer Standardinitialisierung

ls -l /sbin/init

gibt Ihnen die Informationen, die Sie suchen.

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

1
Nicht so. Unter Ubuntu 14.04 mit Upstart ist dies kein Symlink.
muru

Installieren Sie ein anderes Init-System und überprüfen Sie es erneut.
rmorelli74

Und welches andere initkann ich unter Ubuntu 14.04 installieren?
muru

... warum nicht sysv oder systemd?
rmorelli74

1
Ich möchte nicht abstimmen, ich möchte nur, dass Sie angeben, auf welche Version von Debian es anwendbar ist. (Und vielleicht "Debian-based" in "Debian" umformulieren, damit es korrekt wird.)
muru

2

Wenn Sie einfach mit PID 1 in den Prozess hineingreifen, erfahren Sie Folgendes:

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

Nicht alle genannten Betriebssysteme haben ein procDateisystem ...
Toby Speight

2

Auch das Einsehen von Dateideskriptoren kann helfen. Und es ist von der tatsächlichen Ausführung von init (Debian erlaubt derzeit die Installation weiterer init-Systeme) :-)

$ 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

Wahrscheinlich sicherer wäre es check /proc/1/exe, nach Busybox zu suchen , da Busybox normalerweise Symlinks verwendet:

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

Überprüfen Sie also Folgendes:

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

Auch Systeme mit systemd haben normalerweise ein Verzeichnis /run/systemd/system.
Pevik

2

Ich kenne keine anderen Systeme als Debian (wheezy) / oder Ubuntu (14.10.), Aber ich teste solche Probleme mit dem normalen alten fileBefehl.

file /sbin/init

Gib das:

/sbin/init: symbolic link to 'upstart'

Debian-Systeme mit systemd(zB sid) zeigen dies:

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

Auf welchem ​​System haben Sie es getestet? Es gibt kein Debian / Ubuntu und dies funktioniert nicht unter Debian. Hast du es auf Ubuntu ausprobiert?
Terdon

Entschuldigung für diese Verwirrung, ich meine Debian (wheezy) / oder Ubuntu (14.10.). Ausgabe auf 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 bedeutet, dass wir hier SYSV verwenden. Die Ausgabe für Ubuntu wird in meiner Antwort angezeigt.
Zzeroo

Genau, Ihre Lösung scheint also nur zu funktionieren, wenn man zufällig Upstart und Ubuntu verwendet.
Terdon

@terdon: Auf Systemen (RHEL, Fedora), auf denen systemd ausgeführt wird, wird "symbolische Verknüpfung zu ... systemd" zurückgegeben. Auf Systemen (Ubuntu), auf denen upstart ausgeführt wird, wird "symbolischer Link zu upstart" zurückgegeben. Auf Systemen (RHEL, Ubuntu, Debian), auf denen SysV init ausgeführt wird, wird "executable" zurückgegeben. Während dies keine umfassende Umfrage ist und diese Methode eindeutig nicht 100% narrensicher ist, liegt sie eindeutig näher an "Funktioniert zumindest für die großen Distributionen" als an "Nur Emporkömmlinge und Ubuntu"!
Psmears

1
@psmears, wenn es auch für einige systemd-Systeme funktioniert, ist das in der Tat besser (wird aber in dieser Antwort nicht erwähnt). Ich habe gerade auf einem Debian-System mit sysvinit und drei Ubuntus-Systemen (10.04.12.04 und 14.04, alle mit Upstart) getestet und file /sbin/initauf allen Systemen "ausführbar" zurückgegeben. Das Gleiche gilt auch für CentOS 5.8, SLES 10 und Ubuntu 8.04, im Grunde für jedes einzelne System, das mir zur Verfügung steht. Also, soweit ich das beurteilen kann, funktioniert es nicht einmal für Upstart und Ubuntu.
Terdon

2

Ich hatte auch das gleiche Problem und führte viele Tests auf einigen RedHat / CentOS / Debian / Ubuntu / Mint-Maschinen durch. Dies ist, was ich mit guten Ergebnissen endete.

  1. Finden Sie den Namen der ausführbaren Datei mit PID 1:

    ps -p 1

    Wenn es sich um systemd oder Upstart handelt, ist das Problem behoben. Wenn es sich um "init" handelt, kann es sich um einen Symlink oder etwas anderes als einen Upfront-Namen handeln. Gehen Sie geradeaus.

  2. Finden Sie den tatsächlichen Pfad für die ausführbare Datei (arbeiten Sie nur als root):

    ls -l `which init`

    Wenn inites sich um einen Symlink zu Upstart oder systemd handelt, ist das Problem behoben. Ansonsten ist es fast sicher, dass Sie SysV init haben. Aber es kann eine falsch benannte ausführbare Datei sein. Gehen Sie geradeaus.

  3. Suchen Sie das Paket, das die ausführbare Datei bereitstellt. Leider ist dies distroabhängig:

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

Dann, wenn Sie das skripten möchten (der lustigste Teil, IMHO), sind dies meine Einzeiler (als root ausgeführt):

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
Nicht alle angegebenen Betriebssysteme haben dpkg oder rpm (dieses Problem bezieht sich nicht nur auf Ihre Antwort, BTW).
Toby Speight

@ toby-speight Ja, sicher. Beachten Sie, dass ich dies in meiner Antwort angegeben habe, um die Einschränkung deutlich zu machen.
Emerson Prado

In Schritt 3 können Sie init --versiondie Informationen abrufen.
Jarno

1

Dies ist für einige Init-Systeme sehr einfach. Für systemd:

test -d /run/systemd/system

für Emporkömmling:

initctl --version | grep -q upstart

für alles andere kann man einfach von der Distribution ausgehen (gestartet unter OS X, sysvinit unter Debian, OpenRC unter Gentoo).


"assume based on the distro" funktioniert nicht für Debian, wo mindestens drei verschiedene Inits unterstützt werden ...
Toby Speight

1

Hier ist ein Bash-Skript, um die Erkennung durchzuführen. Es prüft im Moment nur auf Upstart und Systemd, sollte aber leicht zu erweitern sein. Ich habe dies dem Code entnommen , den ich zum DisplayLink-Treiberinstallationsskript beigetragen habe .

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
Ich denke, dass die Verwendung /procdieser Funktion an Linux (sofern geeignet konfiguriert) und an ein oder zwei andere gebunden ist - das ist sicherlich alles andere als universell.
Toby Speight

1

Beim Testen von systemd vs initd gibt es viele Kompatibilitätsprobleme. Dies funktioniert tatsächlich auf OpenSuSE 42.1:ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'


1

Für systemd:

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

Downvoting, weil diese Antwort im Vergleich zu den zahlreichen vorhandenen Antworten keine neuen oder anderen Informationen liefert.
Jayhendren

@ Jayhendren Ich sehe dieses Snippet nicht woanders. Es ist an sich nicht vollständig und würde wahrscheinlich besser als Kommentar gegen die Antwort unix.stackexchange.com/a/164092/100397 von TvE
roaima 26.11.16

Oh du hast recht @roaima. Es ist nicht genau das gleiche wie die anderen. Ich suchte auf der Seite nach einer nicht allzu spezifischen Zeichenfolge :)
Jayhendren

1
Dies scheint bei weitem die richtigste Antwort zu sein :)
Jack O'Connor

1

Meine Lösung: Überprüfen Sie den als Prozess ausgeführten Befehl mit der 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

Im Moment habe ich nur Zugriff auf Init- und SystemD-Maschinen, daher kann ich nicht sagen, wie Upstart oder macOS (OS X) erkannt werden, aber ich werde weiter suchen.


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
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.