Der Systemd-Dienst wird ohne Beenden ausgeführt

30

Ich habe meine eigenen Dienst für Jekyll und wenn ich den Dienst starten scheint es , wie es nicht als Hintergrundprozess läuft , weil ich gezwungen bin , ctrl+ caus ihm heraus. Es bleibt nur wegen der --watch im Vordergrund. Ich bin nicht sicher, wie ich es umgehen soll, damit es im Hintergrund läuft. Irgendwelche Gedanken?

# /etc/systemd/system/jekyll-blog.service

[Unit]
Description=Start blog jekyll

[Service]
Type=forking
WorkingDirectory=/home/blog
ExecStart=/usr/local/bin/jekyll build --watch --incremental -s /home/blog -d /var/www/html/blog &
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
User=root
Group=root

[Install]
WantedBy=multi-user.target
madmanali93
quelle
systemd startet Ihren Prozess und erwartet, dass er einen anderen Prozess auslöst, wenn Sie ihn verwenden Type=forking. Darüber hinaus wird es nicht execStartals Shell-Erweiterung ausgeführt, so dass es &am Ende nie als Hintergrund-Flag verstanden wird.
Grochmal
Ich habe es getestet. So sollte Typ einfach sein?
madmanali93
2
Wenn ich mich nicht irre, ist jekyll ein Rails-Typ, dh ein kleiner Web-Server in Ruby. Also ja, Type=simplewäre angemessen. Dies ist auch nicht die Art von Anwendung, die ich als Root ausführen würde, zumindest nicht auf einem internetfähigen Computer (was möglicherweise nicht Ihr Fall ist).
voraussichtlich
Danke ja einfach geklappt. Außerdem generiert dieser Befehl den statischen HTML-Code für Apache, sodass Jekyll nicht auf dem Server ausgeführt wird. Ich denke, es sollte in Ordnung sein, wenn es als root läuft. Ich bin mir nicht sicher, ob ich darüber debattiert habe.
Madmanali93
Oh ok, das ist es, was --incrementalmacht :). Ja, ich sehe keine Sicherheitslücke bei der Wiederherstellung von Dateien als root. Vorausgesetzt natürlich, dass diese Dateien nicht vom Benutzer bereitgestellt werden.
voraussichtlich

Antworten:

54

Systemd ist in der Lage, verschiedene Diensttypen zu verarbeiten, insbesondere einen der folgenden

  • simple - Ein lang laufender Prozess, der sich nicht selbst im Hintergrund darstellt und an die Shell gebunden bleibt.
  • forking - Ein typischer Daemon, der sich selbst davon trennt, dass er ausgeführt wird, und sich selbst effektiv im Hintergrund darstellt.
  • oneshot - Ein kurzlebiger Prozess, der voraussichtlich beendet wird.
  • dbus - Wie einfach, aber die Benachrichtigung über die Beendigung des Startvorgangs wird über dbus gesendet.
  • notify - Wie einfach, aber die Benachrichtigung über das Beenden des Startvorgangs wird über inotify gesendet.
  • idle - Wie einfach, aber die Binärdatei wird nach dem Absenden des Jobs gestartet.

In deinem Fall hast du gewählt Type=forking was bedeutet, dass systemd darauf wartet, dass der Prozess sich selbst aufteilt und der übergeordnete Prozess beendet wird. an, dass der Prozess erfolgreich gestartet wurde. Ihr Prozess tut dies jedoch nicht - er bleibt im Vordergrund und bleibt daher systemctl startauf unbestimmte Zeit hängen oder bis der Prozess abstürzt.

Stattdessen möchten Sie Type=simple , was die Standardeinstellung ist, damit Sie die Linie vollständig entfernen können, um den gleichen Effekt zu erzielen. In diesem Modus wartet systemd nicht auf den Abschluss des Startvorgangs der Prozesse (da nicht bekannt ist, wann dies geschehen ist) und setzt die Ausführung und abhängige Dienste sofort fort. In deinem Fall gibt es keine, also spielt das keine Rolle.

Ein kleiner Hinweis zur Sicherheit:

Wenn Sie den Dienst als Root ausführen, wird davon abgeraten, da er weniger sicher ist als der Betrieb als nicht privilegierter Benutzer. Der Grund dafür ist, dass wenn der Angreifer nichts weiter tun muss, um Ihr System vollständig zu besitzen es in jekyll eine Sicherheitslücke gibt, die die Ausführung von Befehlen ermöglicht (möglicherweise über den Code, den es analysiert). Wenn es andererseits als nicht privilegierter Benutzer ausgeführt wird, kann der Angreifer nur so viel Schaden anrichten wie dieser Benutzer und muss nun versuchen, Root-Rechte zu erlangen, um Ihr System vollständig zu besitzen. Es wird lediglich eine zusätzliche Ebene hinzugefügt, auf die Angreifer zugreifen müssen.

Sie können es einfach als derselbe Benutzer ausführen, auf dem Ihr Webserver ausgeführt wird. Dadurch sind Sie jedoch einem weiteren potenziellen Angriff ausgesetzt. Wenn Ihr Webserver eine Sicherheitsanfälligkeit aufweist, die es dem Benutzer ermöglicht, Dateien auf Ihrem System zu manipulieren, kann er die generierten HTML-Dateien oder schlimmstenfalls die Quelldateien ändern und Ihren Server dazu veranlassen, alles zu bedienen, was er will. Wenn die generierten Dateien und Quelldateien jedoch nur vom Webserver gelesen und von einem anderen nicht privilegierten Benutzer beschrieben werden können, können sie nicht so einfach durch einen Angriff auf den Webserver geändert werden.

Wenn Sie jedoch nur statische Dateien von diesem Server bereitstellen und den Server auf dem neuesten Stand halten, sind diese Angriffe sehr, sehr unwahrscheinlich - aber dennoch möglich. Es liegt in Ihrer Verantwortung, die Risiken im Vergleich zum Aufwand für die Einrichtung zu bewerten, basierend darauf, wie kritisch Ihr System ist. Diese beiden Tipps sind jedoch sehr einfach einzurichten und verursachen kaum Wartungsaufwand.

Michael Daffin
quelle
0

Zusätzlich zur Lösung von @ Michael Daffin können Sie auch das Dämonisierungstool verwenden, um die Verwendung von zu erzielen, forkingwie im folgenden Beispiel gezeigt.

Angesichts eines kleinen Shell-Skripts, das ich dämonisieren und über systemd steuern möchte, habe ich es gespeichert als /home/pi/testscript.sh:

#!/bin/bash

while true;
do
    sleep 1
    echo -n "."
done

Wenn Sie es noch nicht haben, installieren Sie daemonize wie folgt:

sudo apt install daemonize

Erstellen Sie nun die Dateidienstdefinitionsdatei:

sudo vi /etc/systemd/system/testomat.service
# It is not recommended to modify this file in-place, because it will
# be overwritten during package upgrades. If you want to add further
# options or overwrite existing ones then use
# $ systemctl edit testomat.service
# See "man systemd.service" for details.

# copied from https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service and modified by Michael 

[Unit]
Description=Test service
After=network.target

[Service]
ExecStart=daemonize -p /run/testomat/testomat.pid -o /home/pi/testscript.log /home/pi/testscript.sh
TimeoutSec=1200

# Make sure the config directory is readable by the service user
PermissionsStartOnly=true

# Process management
####################
Type=forking
PIDFile=/run/testomat/testomat.pid
Restart=on-failure
GuessMainPID = true

# Directory creation and permissions
####################################

# Run as pi:pi
User=pi
Group=pi

# /run/testomat
RuntimeDirectory=testomat
RuntimeDirectoryMode=0710

# /var/lib/testomat
StateDirectory=testomat
StateDirectoryMode=0710

# Hardening measures
####################

# Provide a private /tmp and /var/tmp.
PrivateTmp=true

# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full

# Allow access to /home, /root and /run/user
# Chosing "false" is actually no hardening, this is just to demonstrate the usage of a service. Well, I could have omitted it. True. :)
ProtectHome=false

# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true

# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true

# Deny the creation of writable and executable memory mappings.
MemoryDenyWriteExecute=true

[Install]
WantedBy=multi-user.target

Der neu angelegte Service muss an systemd gemeldet werden:

systemctl daemon-reload

Jetzt können Sie den Dienst und die Skriptgabeln starten. Wie erwartet wird der Dienststart sofort wieder in der Shell ausgeführt. Das Ergebnis ist offensichtlich:

$ tail -f testscript.log 
.....................

Michael
quelle
Was ist der Vorteil, wenn Sie daemonize+ Type=forkinganstelle von verwenden Type=simpleund systemd den Start des Dienstes übernehmen lassen? Type=forkingist eine Art Kompatibilitätseinstellung in systemd, um ältere Programme zu unterstützen, die in fork geschrieben wurden.
Johan Myréen
Ich denke, es ist eine gleichwertige Lösung. Ich wollte dem OP nur eine alternative Lösung bieten und ihn auf dieses Tool aufmerksam machen, das ich bereits in /etc/init.d verwendet habe, da die Frage auch ein wenig darüber ist, wie man einen Prozess dämonisiert.
Michael