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
quelle
ps -p 1 -o command
(druckt den Pfad zur aktuelleninit
). Unter Arch Linux und Fedora (IIRC) ist dies ein Symlink zursystemd
Binärdatei (wahrscheinlich auf allensystemd
Systemen gleich). Einupstart
,init --help
druckt Nutzungsinformationen aus und auf meiner Boxupstart
wird 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.sudo lsof -a -p 1 -d txt
dass dies zu noch genaueren Ergebnissen führen kann.ps
kann einen beliebigen Namen ausgeben, wobeilsof
Sie mit den tatsächlichen ausführbaren Pfad erhalten. (Siehe meine Frage unter unix.stackexchange.com/questions/102453/… )Antworten:
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/comm
kann das Betrachten irreführend sein, da einige Installationen verschiedener Init-Programme automatisch/sbin/init
einen 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.
quelle
/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./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.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:
Sie können sagen, systemd von:
Sie können sys-v init mitteilen von:
Hier sind meine Experimente mit der folgenden Befehlszeile:
auf ec2-Instanzen (ich beziehe die AMI-ID für USA-Ost ein):
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 ...
quelle
/run/systemd/system
vorhanden ist.launchd
das Init-System unter macOS hinzufügen :[[ $(ps 1) =~ 'launchd' ]] && echo yes || echo no
Getestet auf einem MacBookPro, macOS Sierra Version 10.12if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Prozesse nutzen
Schauen Sie sich die Ausgabe einiger
ps
Befehle an, die die verschiedenen Versionen vonsystemd
& erkennen können. Dieseupstart
könnten folgendermaßen aussehen:Emporkömmling
systemd
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
systemd
zum Beispiel verwendet:Beachten Sie, dass es nicht ist
init
. Auf Ubuntu mit Upstart ist es immer noch/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 ,
systemd
die PID # 1 haben muss.generisch
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
init
ausführbare Datei abfragen , können Sie auch einige Informationen daraus abrufen. Analysieren Sie einfach die--version
Ausgabe. Zum Beispiel:Emporkömmling
systemd
HINWEIS: Die Tatsache, dass
init
sich nicht an der Standardposition befindet, ist ein kleiner Hinweis. Es befindet sich immer/sbin/init
auf Sysvinit-Systemen.sysvinit
Auch diese:
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.
quelle
pgrep systemd >/dev/null && echo init system: systemd
/usr/lib/systemd/systemd
wenn 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.pgrep systemd >/dev/null && echo init system: systemd -> init system: systemd
undtype init -> init is /sbin/init
Nicht so effizient, aber es scheint zu funktionieren.
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.
Ein vereinfachterer Ansatz derselben Lösung (der jedoch beim ersten Spiel aufhört)
quelle
Manchmal ist es so einfach wie
ls
:Ich denke, wenn
/sbin/init
es sich nicht um einen symbolischen Link handelt, müssen Sie die folgenden Vorschläge in anderen Antworten überprüfen.quelle
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.
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 upstart
oder--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.quelle
Schauen Sie sich unter Gentoo PID 1 an:
Wenn
init
ja, dann ist das Init-SystemOpenRC
. Wennsystemd
ja, dann ist das Init-Systemsystemd
.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.quelle
p
Option (identisch mit-p
und--pid
), um nach PID auszuwählen. Das obige Snippet ist eigentlich die Ausgabe fürps u --pid 1
.Unter debian / sbin / init befindet sich ein Symlink zu Ihrer Standardinitialisierung
gibt Ihnen die Informationen, die Sie suchen.
quelle
init
kann ich unter Ubuntu 14.04 installieren?Wenn Sie einfach mit PID 1 in den Prozess hineingreifen, erfahren Sie Folgendes:
quelle
proc
Dateisystem ...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) :-)
Wahrscheinlich sicherer wäre es
check /proc/1/exe
, nach Busybox zu suchen , da Busybox normalerweise Symlinks verwendet:Überprüfen Sie also Folgendes:
quelle
/run/systemd/system
.Ich kenne keine anderen Systeme als Debian (wheezy) / oder Ubuntu (14.10.), Aber ich teste solche Probleme mit dem normalen alten
file
Befehl.Gib das:
Debian-Systeme mit
systemd
(zB sid) zeigen dies:quelle
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.file /sbin/init
auf 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.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.
Finden Sie den Namen der ausführbaren Datei mit PID 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.
Finden Sie den tatsächlichen Pfad für die ausführbare Datei (arbeiten Sie nur als root):
Wenn
init
es 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.Suchen Sie das Paket, das die ausführbare Datei bereitstellt. Leider ist dies distroabhängig:
Dann, wenn Sie das skripten möchten (der lustigste Teil, IMHO), sind dies meine Einzeiler (als root ausgeführt):
quelle
init --version
die Informationen abrufen.Dies ist für einige Init-Systeme sehr einfach. Für systemd:
für Emporkömmling:
für alles andere kann man einfach von der Distribution ausgehen (gestartet unter OS X, sysvinit unter Debian, OpenRC unter Gentoo).
quelle
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 .
quelle
/proc
dieser Funktion an Linux (sofern geeignet konfiguriert) und an ein oder zwei andere gebunden ist - das ist sicherlich alles andere als universell.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'
quelle
Für
systemd
:quelle
Meine Lösung: Überprüfen Sie den als Prozess ausgeführten Befehl mit der ID 1.
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.
quelle
quelle