Systemd: Schreiben Sie Ihre eigenen .service und .target

    Ich hatte Linux auf meinem Heimcomputer und beeilte mich, mich mit dem neuen Betriebssystem vertraut zu machen. Es wurde mit systemd init process installiert. Dies war meine erste Einführung in dieses neue Tool. Ich benutze meinen Laptop für den Alltag und zum Programmieren. Ich wollte Arbeitsprogramme (Apache2 und MySQL) nur für eine Weile einbinden, während ich sie benutze, um die Ressourcen meines Computers nicht zu verschwenden. Zusätzlich habe ich zum Testen ein Bash-Skript geschrieben, das den Inhalt einer der MySQL-Datenbanken von der Festplatte in das RAM lädt (in tmpfs) - auf diese Weise werden Tests viel schneller durchgeführt. Theoretisch könnte ich meinen Arbeitstag so beginnen:
    systemctl start apache2.service
    systemctl start mysqld.service
    /root/scripts/mysqld-tmpfs start
    

    Und beenden Sie es:
    systemctl stop apache2.service
    systemctl stop mysqld.service
    /root/scripts/mysqld-tmpfs stop
    

    Aber ich wollte die Dinge „richtig“ machen.

    Was wollte ich


    Ich wollte 2 Ziele erreichen:
    1. Ich war zu faul, um 2 Befehle zu schreiben (Starten von Apache und Starten von MySQL), weil Ich wusste, dass beide Programme immer synchron ein- und ausgeschaltet werden. Ich wollte diese Operation mit einem Team durchführen.
    2. Der Fall roch nach Ärger, wenn der Computer neu gestartet wird, während sich meine Datenbank in tmpfs befindet - alle Dateien gehen verloren. Natürlich habe ich Backups erstellt, aber ich war wieder zu faul, um sie nach jedem unvorhergesehenen Neustart manuell wiederherzustellen.


    Was habe ich gemacht


    Infolgedessen habe ich Apache2 und MySQL zu einem Ziel kombiniert. Auf diese Weise konnten Sie beide Dienste mit einem Team ausführen. Und ich habe mein mysqld-tmpfs-Skript in den Augen von systemd als Dienst deklariert. Da es sich um einen Dienst handelt, bin ich sicher, dass systemd diesen ordnungsgemäß stoppt, wenn das System neu gestartet wird oder in einer anderen Notsituation, und meine Datenbank ohne Verlust auf der Festplatte gespeichert wird.

    Was ist eine Dienstleistung?


    Dies ist eine Art Programm, das im Hintergrund ausgeführt wird und nützliche Funktionen bietet. Zum Beispiel Apache-Webserver. Dienste können gestartet und gestoppt werden. Einige Dienste können bei bestimmten Ereignissen (Laden des Betriebssystems, Entladen des Betriebssystems usw.) automatisch gestartet und beendet werden. Sie können auch manuell gestartet / gestoppt werden. Der Dienst wird in den Dateien /etc/systemd/system/my-name.service (mit dem Suffix „.service“) deklariert.

    Was ist das Ziel?


    Target in systemd ist Runlevel in openRC sehr ähnlich, aber dies sind immer noch verschiedene Dinge. Erstens können Sie mit target 1 oder mehrere Dienste zu einer einzigen Einheit zusammenfassen. Durch die Gruppierung von Diensten zu Zielen wird die Verwaltung vereinfacht. Zweitens schaltet systemd Ziele automatisch nach Ereignissen ein / aus. "Einbeziehung" von Ziel bedeutet die Einbeziehung aller Dienste, die es kombiniert. Wenn beispielsweise systemd standardmäßig auf target my-favorite.target festgelegt ist, aktiviert systemd beim Systemstart alle Dienste, die in my-favorite.target deklariert sind. Irgendwann in der Konsole können Sie Folgendes eingeben:
    systemctl isolate my-another.target
    

    Alle Dienste von my-another.target werden aktiviert, und alle eingeschlossenen Dienste, die nicht von my-another.target stammen, werden deaktiviert. Dies ist dem Umschalten von Runlevel auf openRC sehr ähnlich. Systemd unterstützt jedoch die Einbeziehung von mehr als einem Ziel. Hier ist ein Beispiel:
    # Эксклюзивно включаем my-favorite.target и выключаем все остальные сервисы
    systemctl isolate my-favorite.target
    # К уже запущенным сервисам и targets добавляем еще 1 target
    systemctl start my-another.target
    

    Nach Ausführung dieser Befehle kombiniert das System die Dienste aus my-favorite.target und my-another.target.

    Wie habe ich das gemacht?


    Als Ergebnis habe ich eine solche mysqld-tmpfs.service-Datei erhalten:
    Description=Mount a MySQL database into tmpfs.
    # Мой /root/scripts/tmpfs скрипт может работать как при включенном, так и при выключенном mysql сервисе. Но если бы mysql сервис нужен был включенным, к примеру, то я бы добавил эти строки:
    #Requires=mysqld.service
    #After=mysqld.service
    [Service]
    # Даем знать systemd, что этот сервис представляет из себя лишь 1 процесс. Man page хорошо описывает доступные опции.
    Type=oneshot
    # Выполнить эту команду при запуске сервиса.
    ExecStart=/root/scripts/mysqld-tmpfs start
    # Выполнить эту команду при остановке сервиса.
    ExecStop=/root/scripts/mysqld-tmpfs stop
    # Даем знать systemd, что сервис нужно считать запущенным, даже если основной процесс прекратил свою работу. Как раз то, что мне нужно: мой процесс выполнит монтировку и после этого прекратит свою работу, но должен считаться активным, т.к. монтировка осталась в системе.
    RemainAfterExit=yes
    

    Und hier ist so eine programming.target-Datei:
    [Unit]
    Description=Working/Programming target
    Requires=mysqld.service
    Requires=apache2.service
    # Сюда я могу дописывать новые сервисы “Requires=another.service”, если они мне понадобятся в повседневной работе.
    


    Was waren die Probleme?


    Als programming.target aus irgendeinem Grund gestoppt wurde, wurden die zugrunde liegenden Programme apache2.service und mysqld.service nicht gestoppt. Nachdem ich die Manpage richtig gelesen hatte, fand ich ein Problem: systemd stoppt die Dienste "träge" - wenn niemand den Dienst starten möchte und er nicht explizit gestartet wurde, sondern als Abhängigkeit für einen anderen Dienst, stoppt systemd ihn nur mit einem von 3 Umstände:
    1. Es wird ein anderer Dienst gestartet, der in seiner Erklärung angibt, dass er mit unserem Dienst in Konflikt steht.
    2. Systemctl isoliere ein anderes Ziel oder systemctl stop this.service wird ausgeführt.
    3. Unser Dienst fordert in seiner Deklaration möglicherweise auf, sich nicht faul, sondern aktiv zu stoppen, indem er diese Zeile in den Abschnitt [Unit] einfügt: StopWhenUnneeded = true


    Deklarationen von "fremden" Diensten können geändert werden, indem die Dateien /etc/systemd/system/name-i-alter.service.d/*.conf erstellt werden. Ich habe gerade /etc/systemd/system/apache2.service/auto-stop.conf und /etc/systemd/system/mysqld.service.d/auto-stop.conf erstellt und diese Zeile dort eingefügt.

    Ein weiteres Problem, auf das ich gestoßen bin, war, dass systemd Symlinks nicht wirklich mag. Ich bin kein großer Fan davon, Systemverzeichnisse wie / etc, / bin, / usr mit meinen wichtigen lokalen Produkten zu „verwechseln“. Deshalb habe ich zunächst versucht, mit meinem Dienst /etc/systemd/system/mysqld-tmpfs.service einen Symlink zu / root / scripts / mysqld- zu erstellen. tmpfs.service-Datei, d.h. Speichern Sie die Datei selbst im Stammverzeichnis des Benutzers. Das Systemteam lehnte es jedoch ab, mit einem solchen Dienst zu arbeiten, der unklare Fehler verursachte. Es stellte sich heraus, dass systemd einen bestimmten Teil seiner internen Küche genau über Symlinks ausführt, und es dann „schwierig“ ist, die interne Küche (ihre Symlinks) von * .service-Dateien von Drittanbietern zu unterscheiden (sofern es sich auch um Symlinks handelt). Durch Entfernen von symlink aus /etc/systemd/system/mysqld-tmpfs.service und Kopieren des Inhalts dieser Datei dort habe ich dieses Problem gelöst.bugzilla.redhat.com/show_bug.cgi?id=955379

    Ergebnis


    Ich habe mein Ziel erreicht. Einen Arbeitstag beginnen:
    systemctl start programming.target
    

    Wenn Sie Tests für Ihr Projekt ausführen müssen:
    systemctl start mysqld-tmpfs.service
    

    Wenn ich die Datenbank von tmpfs auf die Festplatte demontieren möchte (obwohl ich das in der Praxis fast nicht mache, lasse ich die Datenbank einfach den ganzen Tag in tmpfs und wenn ich systemd ausschalte, beginnt es für die Festplatte, die Bereitstellung von tmpfs aufzuheben):
    systemctl stop mysqld-tmpfs.service
    

    Wenn ich mit der Arbeit fertig bin und nicht mehr arbeiten möchte:
    systemctl stop programming.target
    


    Spickzettel


    Nützlichkeit beim Arbeiten mit systemd:
    • Rufen Sie systemctl daemon-reload auf, wenn Sie die Deklaration von etwas ändern (systemd liest die Deklarationsdateien erneut).
    • systemctl start my-name. (service | target) - Startet einen Dienst oder ein Ziel
    • systemctl stop my-name. (service | target) - Stoppt den Service oder das Target
    • systemctl enable my-name.service - Dienste können angeben, auf welchen aktivierten Zielen sie enthalten sein sollen. Verwenden Sie dazu den Abschnitt [Install] in der Service-Deklarationsdatei. Als Systemadministrator haben Sie die Berechtigung, diesen Wunschdienst zu installieren. Häufig werden Dienste standardmäßig in multi-user.target oder in einem ähnlichen Zielsystem „installiert“.
    • systemctl disable my-name.service ist die Umkehrung von enable: um die Verbindung zwischen my-name.service und Zielen zu lösen, die er im Abschnitt [Install] seiner Deklaration angefordert hat.
    • systemctl my.target isolieren - Aktiviert alle Dienste von my.target und deaktiviert alle anderen enthaltenen Dienste.
    • systemctl status my-name. (service | target) - Ermittelt den Status (gestartet / gestoppt) eines Service oder Ziels.


    Ich hoffe dieser Artikel hilft jemandem beim Mastering von systemd. Ich habe versucht, es kompakt zu machen, und wenn ich zusätzliche Fragen übersehen habe, fragen Sie in den Kommentaren!

    Jetzt auch beliebt: