Il servizio Systemd viene eseguito senza uscire


30

Ho creato il mio servizio per jekyll e quando avvio il servizio sembra che non venga eseguito come processo in background perché sono costretto a ctrl+ cuscire da esso. Rimane solo in primo piano a causa del --watch. Non sono sicuro di come aggirarlo e farlo in modo che funzioni in background. qualche idea?

# /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

systemd avvierà il tuo processo e si aspetta che biforchi un altro processo se lo stai utilizzando Type=forking. Inoltre, non funzionerà execStartcome un'espansione della shell, quindi &alla fine non verrà mai inteso come flag di sfondo.
grochmal

mio male il & ero io testarlo. Quindi il tipo dovrebbe essere semplice?
madmanali93,

2
Se non sbaglio jekyll è un tipo di binario simile a un binario, ovvero un piccolo server weby in ruby. Quindi sì, Type=simplesarebbe appropriato. Inoltre, questo non è il tipo di applicazione che vorrei eseguire come root, almeno non su una macchina che si affaccia su Internet (che potrebbe non essere il tuo caso).
grochmal

Grazie sì semplice lavorato. Anche questo comando genera l'html statico per Apache in modo che jekyll non venga pubblicato sul server. Penso che dovrebbe andare bene se funziona come root. Non sono sicuro però se ne stesse discutendo.
madmanali93,

Oh OK, questo è quello che --incrementalfa :). Sì, non vedo alcun problema di sicurezza nel rigenerare i file come root. Naturalmente, dato che quei file non sono forniti dall'utente.
grochmal

Risposte:


54

Systemd è in grado di gestire vari tipi di servizi in particolare uno dei seguenti

  • simple - Un processo di lunga durata che non fa da sfondo a se stesso e rimane attaccato alla shell.
  • forking - Un tipico demone che si biforca, distaccandolo dal processo che lo ha eseguito, creando un background efficace.
  • oneshot - Un processo di breve durata che dovrebbe uscire.
  • dbus - Come semplice, ma la notifica della fine dell'avvio dei processi viene inviata tramite dbus.
  • notify - Come semplice, ma la notifica della fine dell'avvio dei processi viene inviata su inotify.
  • idle - Come semplice, ma il file binario viene avviato dopo l'invio del lavoro.

Nel tuo caso hai scelto il Type=forkingche significa che systemd sta aspettando che il processo si biforchi da solo e che il processo genitore termini, il che serve come indicazione che il processo è stato avviato correttamente. Tuttavia, il processo non sta eseguendo questa operazione: rimane in primo piano e quindi si systemctl startbloccherà indefinitamente o fino a quando i processi si arrestano in modo anomalo.

Invece, vuoi Type=simple, che è l'impostazione predefinita in modo da poter rimuovere completamente la linea per ottenere lo stesso effetto. In questa modalità systemd non attende che i processi finiscano l'avvio (poiché non ha modo di sapere quando ciò è accaduto) e quindi continua immediatamente l'esecuzione e i servizi dipendenti. Nel tuo caso non ce ne sono, quindi non importa.

Una piccola nota sulla sicurezza:

Stai eseguendo il servizio come root, questo è sconsigliato in quanto è meno sicuro di eseguirlo come utente non privilegiato. La ragione di ciò è che se c'è una vulnerabilità in jekyll che in qualche modo consente l'esecuzione di comandi (possibilmente tramite il codice che sta analizzando), l'attaccante non deve fare nient'altro per possedere completamente il proprio sistema. Se, d'altra parte, viene eseguito come utente non privilegiato, l'attaccante è in grado di fare solo il danno di quell'utente e deve ora tentare di ottenere i privilegi di root per possedere completamente il sistema. Aggiunge semplicemente un livello aggiuntivo che gli attaccanti devono comunque seguire.

Puoi semplicemente eseguirlo come lo stesso utente che esegue il tuo server web, ma questo ti lascia aperto a un altro potenziale attacco. Se esiste una vulnerabilità nel tuo server web che consente all'utente di manipolare i file sul tuo sistema, può modificare i file html generati o, peggio, i file di origine e far sì che il tuo server serva tutto ciò che desidera. Tuttavia, se i file generati e i file sorgente sono leggibili solo dal server web e sono scrivibili come un altro utente non privilegiato, non saranno in grado di modificarli con la stessa facilità attaccando il web server.

Tuttavia, se stai semplicemente servendo file statici da questo server e mantieni aggiornato il server, questi attacchi sono molto improbabili, ma ancora possibili. È tua responsabilità valutare i rischi rispetto alle spese generali di configurazione in base a quanto sia critico il tuo sistema, ma entrambi questi suggerimenti sono molto semplici da configurare e quasi senza spese generali di manutenzione.


0

Oltre alla soluzione di @ Michael Daffin , è anche possibile utilizzare lo strumento daemonize per ottenere l'utilizzo di forkingcome mostrato nel seguente esempio.

Dato un piccolo script di shell che voglio demonizzare e che voglio controllare su systemd, l'ho salvato come /home/pi/testscript.sh:

#!/bin/bash

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

Se non lo hai ancora, installa daemonize, in questo modo:

sudo apt install daemonize

Ora crea il file di definizione del servizio file:

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

Il servizio appena creato deve essere annunciato a systemd:

systemctl daemon-reload

Ora puoi avviare il servizio e le forcelle di script. Come previsto, l'avvio del servizio ritorna immediatamente alla shell. Il risultato è ovvio:

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


Qual è il vantaggio di utilizzare daemonize+ Type=forkinganziché Type=simpleconsentire a systemd di occuparsi dell'avvio del servizio? Type=forkingè una specie di impostazione di compatibilità in systemd per supportare i programmi legacy scritti su fork.
Johan Myréen,

Penso che sia una soluzione equivalente; Volevo solo fornire all'OP una soluzione alternativa e renderlo consapevole di questo strumento che ho già usato in /etc/init.d volte poiché la domanda è anche un po 'su come demonizzare un processo.
Michael,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.