Ich bin kürzlich auf zwei verschiedene Probleme auf zwei verschiedenen Linux-Hosts gestoßen. Jeder erforderte eine einzigartige Umgehung, da ich noch keine wirkliche Lösung finden musste. Die Methode zum Bereitstellen jeder Umgehung war jedoch dieselbe:Führen Sie einen Befehl während oder kurz nach dem Start von Linux aus.
Die rc.local
Datei war – und ist in einigen Fällen immer noch – der Ort für Linux-Systemadministratoren, um Befehle abzulegen, die beim Start ausgeführt werden müssen. Verwendung der rc.local
Datei ist nicht nur veraltet, sondern hat nach ein paar Stunden Versuchen auf jeden Fall nicht funktioniert. Dies obwohl die systemd
Dokumentation erwähnt die Verwendung eines "Generators", der systemd
generiert Dienste aus einer rc.local
Datei, falls vorhanden. (Das scheint ein guter Weg zu sein, um die Ablehnung zu erzwingen – dafür zu sorgen, dass es nicht funktioniert.)
Die Details meines spezifischen Problems sind für diese Diskussion nicht besonders relevant, daher werde ich einen einfachen und leicht zu verfolgenden Befehl als Inhalt unserer lokalen Startdatei verwenden. Wir werden eine Zeile mit Datumsstempel zu einer lokalen Protokolldatei hinzufügen, um zu überprüfen, ob das Bash-Programm, das wir beim Start ausführen müssen, tatsächlich funktioniert.
Boot vs. Startup
Das Verständnis des Boot- und Startvorgangs von Linux ist wichtig, um Linux zu konfigurieren und Startprobleme zu lösen. In Wirklichkeit gibt es zwei Abfolgen von Ereignissen, die erforderlich sind, um einen Linux-Computer zu booten und ihn nutzbar zu machen:Booten und Hochfahren. Die Bootsequenz beginnt mit dem Einschalten des Computers und endet mit der Initialisierung des Kernels und systemd
gestartet wird. Der Startvorgang übernimmt dann und beendet die Aufgabe, den Linux-Computer in einen betriebsbereiten Zustand zu versetzen.
Insgesamt ist der Boot- und Startvorgang von Linux ziemlich einfach zu verstehen. Es besteht aus den folgenden Schritten, die später ausführlicher beschrieben werden:
- BIOS Power-On Self-Test (POST)
- Bootloader (GRUB2)
- Kernel
systemd
Eine viel detailliertere Beschreibung sowohl der Boot- als auch der Startsequenz finden Sie in meinem Artikel Eine Einführung in die Linux-Boot- und Startprozesse.
Lokaler Start
Systemadministratoren fügen der Startsequenz manchmal Befehle hinzu, die lokal nützlich sind. Diese Ergänzungen können darauf abzielen, lokale Prozesse zu starten oder auszuführen, die nicht Teil des standardmäßigen systemd
sind Anfang. Es ist möglich, einen neuen systemd
hinzuzufügen Service-Unit, um jedes Programm zu starten, das beim Start benötigt wird, aber die alte rc.local
-Methode stellte eine einzige ausführbare Datei für alle lokalen Startanforderungen bereit. Auch wir können diesen Single-File-Ansatz mit systemd
verwenden . Die Eleganz dieser Lösung besteht darin, dass sie es einfach macht, zu einem späteren Zeitpunkt weitere Startbefehle hinzuzufügen, ohne dass weitere Diensteinheiten zu systemd
hinzugefügt werden müssen .
Unsere Lösung besteht darin, ein einzelnes systemd
zu erstellen service unit und platzieren Sie alle erforderlichen Linux-Befehle in der ausführbaren Datei. Diese Lösung besteht aus zwei Teilen. Eines ist offensichtlich:Wir brauchen eine ausführbare Datei. Und zweitens müssen wir eine Diensteinheit für systemd
erstellen die die ausführbare Datei ausführt.
Erstellen Sie die ausführbare Datei
Dies ist eine triviale Übung für jeden Systemadministrator, der mit der Bash-Programmierung vertraut ist. Tatsächlich erstellen wir ein Bash-Programm und platzieren es im Linux Filesystem Hierarchical Standard (FHS)-Speicherort für lokale ausführbare Dateien, /usr/local/bin
. Es könnte argumentiert werden, diese ausführbare Datei an einem anderen Ort zu platzieren, aber /usr/local/bin
ist diejenige, die für mich am sinnvollsten ist, da dieser Speicherort es dem Systemadministrator erleichtert, das Skript bei Bedarf über die Befehlszeile auszuführen. Der /usr/local/bin
Verzeichnis ist immer im $PATH
jedes Benutzers , einschließlich des Root-Benutzers.
Erstellen Sie mystartup.sh
hier gezeigte Datei und legen Sie sie in /usr/local/bin
ab (Stellen Sie sicher, dass es ausführbar ist). Stellen Sie sicher, dass Sie den für Ihre Distribution richtigen Speicherort für Bash verwenden. Zum Beispiel finden Debian-basierte Distributionen Bash unter /bin/bash
.
#!/usr/bin/bash
################################################################################
# mystartup.sh
#
# This shell program is for testing a startup like rc.local using systemd.
# By David Both
# Licensed under GPL V2
#
################################################################################
# This program should be placed in /usr/local/bin
################################################################################
# This is a test entry
echo `date +%F" "%T` "Startup worked" >> /root/mystartup.log
Hinweis: Die Kommentare in den enthaltenen Dateien sagen Ihnen, wo sie abgelegt werden müssen.
Stellen Sie sicher, dass Sie diese ausführbare Datei testen, indem Sie sie über die Befehlszeile ausführen. Wenn Sie dieses Shell-Skript zum ersten Mal ausführen, sollten Sie eine neue Datei sehen, /root/mystartup.log
, mit Uhrzeit und Datum zusammen mit dem Text "Startup worked"
. Wir erstellen diese Protokolldatei und fügen ihr jedes Mal Zeilen hinzu, wenn das Skript als einfacher Test ausgeführt wird, um sicherzustellen, dass unser Skript funktioniert.
Führen Sie das Skript noch ein paar Mal aus. Ihre Ergebnisse sollten denen hier ähneln:
[root@testvm1 ~]# mystartup.sh
[root@testvm1 ~]# cat mystartup.log
2019-09-12 19:58:00 Startup worked
2019-09-12 19:58:17 Startup worked
2019-09-12 19:58:54 Startup worked
2019-09-12 19:59:00 Startup worked
2019-09-12 20:01:08 Startup worked
2019-09-12 20:04:01 Startup worked
2019-09-12 20:04:13 Startup worked
2019-09-12 20:06:11 Startup worked
2019-09-12 20:06:28 Startup worked
2019-09-16 09:51:21 Startup worked
2019-09-16 09:51:51 Startup worked
Das ist alles, was wir tun müssen, um die Datei zu erstellen, die möglicherweise unsere lokalen Startbefehle enthält. Fügen Sie dieser Datei einfach alles hinzu, was beim Start ausgeführt werden muss.
Systemd-Dienst erstellen
Die Service-Unit, die wir jetzt erstellen werden, ist ein Standard-systemd
Service-Einheit-Datei. Diese einfache Datei wird nur zum Ausführen von mystartup.sh
verwendet Skript beim Start.
Erstellen Sie eine neue Datei, /usr/local/lib/systemd/system/mystartup.service
, und fügen Sie den unten gezeigten Inhalt hinzu:
################################################################################
# mystartup.service
#
# This service unit is for testing my systemd startup service
# By David Both
# Licensed under GPL V2
#
################################################################################
# This program should be placed in /usr/local/lib/systemd/system/.
# Create a symlink to it from the /etc/systemd/system directory.
################################################################################
[Unit]
Description=Runs /usr/local/bin/mystartup.sh
[Service]
ExecStart=/usr/local/bin/mystartup.sh
[Install]
WantedBy=multi-user.target
Diese Datei muss nicht ausführbar sein. Diese Datei könnte sich auch in /etc/systemd/system
befinden , aber als lokale Datei wird sie besser in /usr/local
abgelegt Zweig der Verzeichnisstruktur, mit einem Link darauf von /etc/systemd.system
.
Gehen Sie nun zu /etc/systemd/system
und erstellen Sie den symbolischen Link in der Service-Unit-Datei:
[root@testvm1 system]# ln -s /usr/local/lib/systemd/system/mystartup.service
Testen Sie die Serviceeinheit
Wir sollten die endgültige Service-Unit-Datei testen, bevor wir den Linux-Host für den abschließenden Test neu starten. Lassen Sie uns zuerst überprüfen, ob systemd
sieht den Dienst:
[root@testvm1 ~]# systemctl status mystartup
● mystartup.service - Runs /usr/local/bin/mystartup.sh
Loaded: loaded (/usr/local/lib/systemd/system/mystartup.service; linked; vendor preset: disabled)
Active: inactive (dead)
[root@testvm1 ~]#
Dieses Ergebnis sagt uns, dass der Dienst von systemd
erkannt wird . Lassen Sie uns nun den Dienst starten. Dadurch wird das Skript ausgeführt, aber der neue Dienst wird nicht so konfiguriert, dass er beim Booten ausgeführt wird:
[root@testvm1 ~]# systemctl start mystartup
Überprüfen Sie den Inhalt der Protokolldatei, um sicherzustellen, dass die neue Zeile hinzugefügt wurde.
Dienst aktivieren
Alles, was übrig bleibt, ist, den Dienst so zu aktivieren, dass er beim Start ausgeführt wird:
[root@testvm1 ~]# systemctl enable mystartup
Created symlink /etc/systemd/system/multi-user.target.wants/mystartup.service →
/usr/local/lib/systemd/system/mystartup.service.
[root@testvm1 ~]#
Abschlusstest
Schauen wir uns vor dem Neustart das journalctl
an Befehl und wie wir ihn verwenden können, um die Journaleinträge anzuzeigen, die sich auf mystartup.service
beziehen . Wir können auch das journalctl
verwenden Befehl, um dies zu überprüfen, da systemd
führt ein Tagebuch über alles, was es tut.
Im folgenden Befehl wird der -u
Option zeigt nur Einträge für mystartup
Einheit:
[root@testvm1 ~]# journalctl -u mystartup
-- Logs begin at Mon 2019-04-15 22:50:27 EDT, end at Mon 2019-09-16 11:44:30 EDT. --
Sep 16 11:09:28 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]#
Starten Sie nun den Linux-Host neu und überprüfen Sie die Protokolldatei, um sicherzustellen, dass eine neue Zeile hinzugefügt wurde:
[root@testvm1 ~]# systemctl status mystartup
● mystartup.service - Runs /usr/local/bin/mystartup.sh
Loaded: loaded (/usr/local/lib/systemd/system/mystartup.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2019-09-16 11:45:59 EDT; 1min 30s ago
Process: 819 ExecStart=/usr/local/bin/mystartup.sh (code=exited, status=0/SUCCESS)
Main PID: 819 (code=exited, status=0/SUCCESS)
Sep 16 11:45:55 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]# journalctl -u mystartup
-- Logs begin at Mon 2019-04-15 22:50:27 EDT, end at Mon 2019-09-16 11:47:45 EDT. --
Sep 16 11:09:28 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
-- Reboot --
Sep 16 11:45:55 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]#
Schlussfolgerung
Das Bash-Shell-Skript, das wir für dieses Experiment erstellt haben, wird beim Start einmal ausgeführt und dann beendet. Es verbleibt nicht als Daemon im Speicher, weil es nicht dafür konzipiert wurde.
Falls Sie es nicht bemerkt haben, kann das Verfahren, das wir zum Erstellen unseres lokalen Startdienstes verwendet haben, auch zum Erstellen eines neuen Dienstes für systemd
verwendet werden . Es ist nicht so schwer, sobald wir wissen, wie es geht.
Aktualisieren
Kurz nachdem dieser Artikel veröffentlicht wurde, erhielt ich eine E-Mail von Tom Murphy, der mich über die Existenz von rc-local
informierte Dienst, der Teil von systemd
ist . Ich weiß diese E-Mail zu schätzen, da ich diesen Dienst nicht kannte und so etwas Neues gelernt habe.
Es ist möglich, Unterstützung für die alte rc.local
hinzuzufügen Datei, indem Sie den Dienst mit dem Befehl systemctl enable rc-local
aktivieren . Die Befehle in der Datei rc.local werden beim nächsten Start ausgeführt. Natürlich können Sie systemctl enable rc-local
verwenden um rc.local
auszuführen sofort.
Es ist jedoch immer noch wahr, dass rc.local veraltet ist. Die Manpage für systemd-rc-local-generator
heißt es:„Unterstützung für /etc/rc.local wird nur aus Gründen der Kompatibilität mit bestimmten System V-Systemen bereitgestellt. Es wird jedoch dringend empfohlen, die Verwendung dieses Skripts heute zu vermeiden und stattdessen geeignete Unit-Dateien mit geeigneten Abhängigkeiten für alle Skripts bereitzustellen, die während des Boot-Vorgangs ausgeführt werden.“
Ressourcen
-
Linux Filesystem Hierarchical Standard (FHS) DataBook für Linux
-
GNU GRUB-Informationen
-
GNU GRUB-Handbuch
-
Master Boot Record
-
Multiboot-Spezifikation
-
systemd-Informationen
-
systemd Bootvorgang
-
systemd-Index der Manpages
-
Eine Einführung in die Boot- und Startup-Prozesse von Linux
[Möchten Sie Red Hat Enterprise Linux ausprobieren? Jetzt kostenlos herunterladen.]