it-swarm.com.de

Der Systemd-Dienst wird ohne Beenden ausgeführt

Ich habe meinen eigenen Dienst für jekyll erstellt, und wenn ich den Dienst starte, scheint er nicht als Hintergrundprozess ausgeführt zu werden, da ich dazu gezwungen bin ctrl+c heraus. Es bleibt nur wegen der --watch im Vordergrund. Ich bin mir 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
32
madmanali93

Systemd kann verschiedene Diensttypen verarbeiten, insbesondere einen der folgenden

  • simple - Ein lang laufender Prozess, der sich nicht selbst in den Hintergrund stellt und mit der Shell verbunden bleibt.
  • forking - Ein typischer Daemon, der sich selbst von dem Prozess trennt, der ihn ausgeführt hat, und sich selbst effektiv in den Hintergrund stellt.
  • oneshot - Ein kurzlebiger Prozess, der voraussichtlich beendet wird.
  • dbus - Wie einfach, aber die Benachrichtigung über den Abschluss des Prozessstarts wird über dbus gesendet.
  • notify - Wie einfach, aber die Benachrichtigung über den Abschluss des Prozessstarts wird über inotify gesendet.
  • idle - Wie einfach, aber die Binärdatei wird gestartet, nachdem der Job gesendet wurde.

In Ihrem Fall haben Sie Type=forking Ausgewählt, was bedeutet, dass systemd darauf wartet, dass sich der Prozess selbst verzweigt und der übergeordnete Prozess beendet wird. Dies ist ein Hinweis darauf, dass der Prozess erfolgreich gestartet wurde. Ihr Prozess tut dies jedoch nicht - er bleibt im Vordergrund und so bleibt systemctl start Auf unbestimmte Zeit hängen oder bis der Prozess abstürzt.

Stattdessen möchten Sie Type=simple, Dies ist die Standardeinstellung, damit Sie die Zeile vollständig entfernen können, um den gleichen Effekt zu erzielen. In diesem Modus wartet systemd nicht darauf, dass die Prozesse gestartet werden (da nicht bekannt ist, wann dies geschehen ist), und führt daher die Ausführung und abhängige Dienste sofort weiter aus. In Ihrem Fall gibt es keine, daher spielt dies keine Rolle.

Ein kleiner Hinweis zur Sicherheit:

Wenn Sie den Dienst als Root ausführen, wird davon abgeraten, da er weniger sicher ist als die Ausführung als nicht privilegierter Benutzer. Der Grund dafür ist, dass if es eine Sicherheitslücke in jekyll gibt, die irgendwie die Ausführung von Befehlen ermöglicht (möglicherweise über den Code, den es analysiert), dann muss der Angreifer nichts anderes tun, um Ihr System vollständig zu besitzen. 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-Berechtigungen zu erlangen, um Ihr System vollständig zu besitzen. Es fügt einfach eine zusätzliche Ebene hinzu, auf die Angreifer gehen müssen.

Sie können es einfach als denselben Benutzer ausführen, der Ihren Webserver ausführt. Dadurch sind Sie jedoch offen für einen weiteren potenziellen Angriff. Wenn auf Ihrem Webserver eine Sicherheitsanfälligkeit vorliegt, die es dem Benutzer ermöglicht, Dateien auf Ihrem System zu bearbeiten, kann er die generierten HTML-Dateien oder im schlimmsten Fall die Quelldateien ändern und Ihren Server veranlassen, alle gewünschten Dienste bereitzustellen. 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 sie nicht so einfach ändern, indem sie den Webserver angreifen.

Wenn Sie jedoch einfach 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 gegen den Aufwand für die Einrichtung abzuwägen, basierend darauf, wie kritisch Ihr System ist. Beide Tipps sind jedoch sehr einfach einzurichten und verursachen keinen Wartungsaufwand.

57
Michael Daffin

Zusätzlich zur Lösung von @ Michael Daffin können Sie auch das Tool daemonize verwenden, um die Verwendung von forking zu erreichen, wie im folgenden Beispiel gezeigt.

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

#!/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 erstellte Dienst muss systemd angekündigt werden:

systemctl daemon-reload

Jetzt können Sie den Dienst und die Skriptgabeln starten. Wie erwartet kehrt der Servicestart sofort zur Shell zurück. Das Ergebnis ist offensichtlich:

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

0
Michael