systemd - gestore di sistema e servizi

Introduzione

systemd è un gestore di sistema e servizi per Linux. È il sistema init predefinito per Debian a partire da Debian 8 ("jessie"). systemd è compatibile con script init per SysV e LSB. Può funzionare come rimpiazzo perfetto per sysvinit. Systemd

systemd viene eseguito come demone con PID 1.

Le attività di systemd sono organizzate in unità. Le unità più comuni sono servizi (.service), punti di montaggio (.mount), device (.device), socket (.socket) o temporizzatori (.timer). Per esempio l'avvio del demone Secure SHell viene fatto dall'unità ssh.service.

systemd mette ogni servizio in un gruppo di controllo (cgroup) dedicato che prende il nome dal servizio. I kernel moderni gestiscono l'isolazione dei processi e l'allocazione delle risorse sulla base dei cgroup.

I target sono gruppi di unità. I target richiamano unità per mettere insieme il sistema. graphical.target, per esempio, chiama tutte le unità necessarie per avviare una postazione di laoro con un'interfaccia utente grafica. I target possono costruire uno sopra l'altro oppure dipendere da altri target. All'avvio systemd attiva il target default.target che è un alias per un altro target, come graphical.target.

systemd crea e gestisce i socket usati per la comunicazione tra i componenti del sistema. Per esempio prima crea il socket /dev/log e poi avvia il demone syslog. Questo approccio ha due vantaggi: in primo luogo i processi che comunicano con syslog attraverso /dev/log possono essere avviati in parallelo. Poi i servizi che vanno crash possono essere riavviati senza che i processi che comunicano con essi attraverso socket perdano la loro connessione. Il kernel tiene un buffer della comunicazione mentre il processo si riavvia.

Per maggiori informazioni vedere la pagina originale di systemd.

Uso di base

systemctl è lo strumento principale utilizzato per l'introspezione e il controllo dello stato del gestore di sistema e servizi "systemd". Si può, ad esempio, usare systemctl per abilitare o disabilitare servizi in modo permanente o solo per la sessione corrente. Per maggiori dettagli fare riferimento alla pagina di manuale systemctl(1).

Ottenere informazioni sullo stato del sistema

Visualizzare lo stato del sistema:

$ systemctl status

Elencare le unità che hanno fallito:

$ systemctl --failed

Elencare i file di unità installati:

$ systemctl list-unit-files

Gestire servizi

Elencare tuti i servizi in esecuzione:

$ systemctl

Attivare il servizio "esempio1" immediatamente:

# systemctl start esempio1

Deattivare il servizio "esempio1" immediatamente:

# systemctl stop esempio1

Riavviare il servizio "esempio1" immediatamente:

# systemctl restart esempio1

Visualizzare lo stato del servizio "esempio1":

# systemctl status esempio1

Abilitare l'avvio di "esempio1" all'avvio di sistema:

# systemctl enable esempio1

Disabilitare l'avvio di "esempio1" all'avvio di sistema:

# systemctl disable esempio1

Visualizzare la configurazione per "esempio1":

# systemctl cat esempio1

Creare o alterare servizi

Le unità sono definite da singoli file di configurazione chiamati file di unità. Il tipo di unità è riconosciuto dal suffisso del nome del file, .mount nel caso di un punto di mount. I file di unità forniti da Debian sono posizionati nella directory /lib/systemd/system directory. Se esiste un file di unità locale con un nome identico nella directory /etc/systemd/system, questo avrà la precedenza e systemd ignorerà il file nella directory /lib/systemd/system. Alcune unità vengono create da systemd senza che esista un file di unità nel file system.

Gli amministratori di sistema dovrebbero mettere i file di unità nuovi o quelli altamente personalizzati in /etc/systemd/system.

Piccoli aggiustamenti

Per piccoli aggiustamenti ad un file di unità gli amministratori di sistema dovrebbero usare la funzionalità "drop-in directory" (documentata in systemd.unit(5)).

Ecco un esempio:

# cat /etc/systemd/system/name.service.d/local.conf
[Service]
ExecStart=
ExecStart=/usr/sbin/name-service --my-options

Per informazioni su come scrivere servizi propri, vedere systemd/Services.

Installazione e test

systemd è stato incluso in Debian wheezy come anteprima tecnologica. Assicurarsi di stare usando Debian jessie o una successiva per ottenere una versione recente di systemd.

Installazione

Per installare systemd eseguire:

# apt-get update
# apt-get install systemd

Questo installa i pacchetti di systemd ma non configura systemd come sistema init.

Configurazione a fini di test

Per testare systemd prima di passare ad usarlo in modo predefinito si può aggiungere il seguente parametro d'avvio al kernel:

init=/lib/systemd/systemd

Ciò può essere fatto nel menu di grub per un solo avvio: premere "e" nel menu di grub e aggiungere quanto detto nella riga del kernel. Per esempio, a seconda delle opzioni richieste dal proprio particolare sistema, potrebbe essere una cosa simile a:

linux   /vmlinuz-3.13-1-amd64 root=/dev/mapper/root-root init=/lib/systemd/systemd ro quiet

Se il PID 1 è systemd allora il sistema è in esecuzione con systemd.

Configurazione come sistema predefinito

Per utilizzare systemd si deve installare anche systemd-sysv che fornisce i collegamenti simbolici per /sbin/init. È raccomandato di eseguirlo quando il sistema è già in esecuzione con systemd, come descritto nella sezione precedente.

# apt-get install systemd-sysv

Per avviare il sistema con il systemd appena installato basta riavviare.

# reboot

Se si esegue un kernel compilato personalmente assicurarsi di avere 2.6.39 o successivo e abilitare le seguenti opzioni:

 * CONFIG_DEVTMPFS=y
 * CONFIG_CGROUPS=y
 * CONFIG_AUTOFS4_FS=[y|m]
 * CONFIG_IPV6=[y|m], opzionale, ma altamente raccomandato
 * CONFIG_FANOTIFY=y, opzionale, necessario per il readahead di systemd, disponibile nel kernel Linux >= 2.6.37.

Per un elenco aggiornato vedere la sezione "REQUIREMENTS" nel file README degli autori originali a monte.

Sicurezza dei demoni

Panoramica

Una funzionalità importante di systemd è la capacità di gestire in modo coerente l'accesso al sistema che viene consentito ai demoni. Prima dell'adozione di systemd, ci si attendeva che ogni demone chiamasse setgid(2), setuid(2) e daemon(3) per limitare l'ambito del danno se il demone fosse compromesso. Ma prima che il demone lasciasse i privilegi qualsiasi bug, errore di configurazione o attacco poteva causare danni illimitati. Se un demone era sotto il controllo di una parte ostile a partire dalla fase di inizializzazione e veniva avviato manualmente dall'amministratore di sistema, poteva usare il TIOCSTI ioctl per mettere caratteri nel buffer della tastiera per prendere controllo del sistema; questo era un problema difficile da risolvere dato che i demoni richiedevano all'amministratore di inserire la password all'avvio (un server web con chiavi SSL cifrate era un esempio comune).

Per risolvere il problema systemd gestisce il processo di avvio dei demoni, ha systemd-ask-password(1) e programmi associati per ottenere le password all'avvio dei demoni e, oltre a ciò, non gli dà l'accesso diretto al terminale dell'amministratore di sistema. Il demone può essere avviato con UID/GID specifici, uno specifico contesto di sicurezza SELinux e con l'intera gamma dei meccanismi di controllo degli accessi di Linux (punti di mount privati, punti di mount in sola lettura, limiti alle chiamate di sistema, ecc.). Vedere la documentazione di systemd-exec per tutte le opzioni.

Controllare la sicurezza dei demoni

Il comando seguente mostra una lista di tutte le unità e il numero di esposizione da 0 a 10 (alto è male):

systemd-analyze security

Il comando seguente mostra i dettagli dell'esposizione del servizio rsyslog:

systemd-analyze security rsyslog.service

Generalmente si vuole abbassare i numeri il più possibile nei limiti di ciò che fanno. Ma un programma di login (sshd, getty, xdm, ecc.) che permette un login root diretto o l'accesso in esecuzione a su/sudo non può essere ristretto molto in modo significativo.

Aumentare la sicurezza dei demoni

Vedere la sezione Piccoli aggiustamenti di questo documento per informazioni su come regolare la configurazione dei demoni, per ragioni di sicurezza o altri motivi.

Una delle cose più importanti da impostare è l'elenco della capacità permesse per il demone. CapabilityBoundingSet è l'elenco delle capacità che sono permesse (separate da spazi su una singola riga) o l'elenco delle capacità da bloccare precedute da un carattere ~. Ecco un esmpio su come permettere ad un demone di avere DAC_OVERRIDE (leggere file che non sarebbero permessi dai permessi Unix quando in esecuzione come UID 0), SETUID e SETGID (per lasciare i privilegi, non necessario se si usa systemd per l'esecuzione con UID/GID richiesti), PTRACE e lock della memoria. Tutte le altre capacità verranno negate:

CapabilityBoundingSet=CAP_DAC_OVERRIDE CAP_SETGID CAP_SETUID CAP_SYS_PTRACE CAP_IPC_LOCK

Un elenco completo delle capacità con la loro descrizione è nel file /usr/include/linux/capability.h dal pacchetto linux-libc-dev o fare riferimento a capabilities(7). Solitamente è meglio elencare semplicemente le capacità da permettere, dato che è un insieme più piccolo.

Capire quali capacità sono necessarie per un demone è difficile, solitamente i log non indicano ciò che manca.

Un'altra buona opzione per limitare sono le chiamate di sistema. L'esempio seguente elenca alcune chiamate di sistema che sono note come rischiose (come il gruppo @clock e il gruppo @mount, oltre ad alcune che non sono solitamente usate e che possono essere ristrette in modo sicuro per ridurre la superficie di attacco come @cpu-emulation e @raw-io. Filtrare le chiamate di sistema si sovrappone in parte con il limitare le capacità, ma è bene restringere le cose in due modi. Solitamente non è difficile mappare i messaggi di errore creati nei log da un demone ai gruppi di chiamate di sistema che sono stati filtrati e poi fare una ricerca binaria per le opzioni più restrittive.

SystemCallFilter=~@mount @cpu-emulation @debug @raw-io @reboot @resources @swap @module @obsolete @clock

Quello che segue è raccomandato per ogni demone che non interagisce direttamente con i file utente. I demoni come i server di database quasi mai hanno necessità di accedere alle directory home degli utenti e dovrebbe essere in modo predefinito impedito a loro di accedere a /home.

ProtectHome=true

Le impostazioni seguenti vanno bene per proteggere l'installazione globale del sistema. Possono essere usate per la maggior parte dei demoni con basso rischio di rendere cose difettose:

ProtectKernelLogs=true
ProtectControlGroups=true
ProtectKernelModules=true
MemoryDenyWriteExecute=true
ProtectHostname=true
LockPersonality=true
RestrictRealtime=true
DevicePolicy=closed
ProtectClock=true
RestrictSUIDSGID=true
ProtectKernelTunables=true
PrivateDevices=true

Quanto segue va bene per prevenire che un demone venga attaccato da un utente o un altro demone usando condizioni di race su /tmp. È improbabile che causi problemi.

PrivateTmp=true

Ciò che segue va bene per demoni che non hanno bisogno della rete. Ciò permette i socket di dominio Unix col file system (es. /run/$DAEMON/whatever.sock), ma non lo spazio dei nomi socket astratto. Il rischio è per i servizi PAM che usano la rete o un altro accesso indiretto alla rete. Questa è una buona opzione per l'amministratore di sistema che blocca il proprio sistema, ma è rischioso per il manutentore di pacchetti.

PrivateNetwork=true

L'opzione NoNewPrivileges previene che un demone esegua un programma SETUID per ottenere privilegi non desiderati. Ci sono però alcuni casi d'uso limite per questo, come l'esecuzione di un programma che ha la transizione automatica di dominio SE Linux ad privilegi MINORI che può essere negata.

NoNewPrivileges=true

Debug

Unità fallite

In alcuni casi le unità entrano in uno stato detto di fallimento. Il comando status può essere utilizzato per scoprire alcuni dettagli:

$ systemctl status <NOMEUNITA>

Le unità fallite possono essere manualmente ripulite:

# systemctl reset-failed

Verificare le unità

Per verificare di non aver fatto errori di battitura o di aver usato qualche opzione sconosciuta quando vengono scritte unità usare systemd-analyze

$ systemd-analyze verify <NOMEUNITA-o-PERCORSOUNITA>

L'assenza di output significa che tutto torna.

systemd si blocca all'avvio o allo spegnimento

A volte è necessario investigare sul perché systemd si blocca all'avvio o durante un riavvio o uno spegnimento.

Soluzione n.0: rimuovere "quiet" dalla riga di comando del kernel (a volte chiamata "cmdline" o "grub line")

Soluzione n.1: aumentare la prolissità utilizzando la riga di comando (cmdline): aggiungere "systemd.log_target=kmsg systemd.log_level=debug"

Naturalmente si può avere una soluzione "temporanea" persistente:

[ /etc/default/grub ]
GRUB_CMDLINE_LINUX="systemd.log_target=kmsg systemd.log_level=debug" <--- aggiungere qui (decommentando si può facilmente passare al debug)

# update-grub

Soluzione n.2: aumentare la prolissità usando /etc/systemd/system.conf

LogLevel=debug           <--- decommentare questa riga e usare  "debug" (predefinito: commentato e con "info")
LogTarget=syslog-or-kmsg <--- decommentare questa riga (predefinito: commentato)

Soluzione n.3: avviare una shell di emergenza: aggiungere systemd.unit=rescue.target o semplicemente 1 (il numero uno) alla riga di comando del kernel.

Soluzione n.4: abilitare la shell di debug: eseguire systemctl enable debug-shell.service. (Lo si può fare in un ambiente chroot dopo aver avviato un sistema di ripristino.) Questo avvia una shell root su TTY 9.

SUGGERIMENTO: "man systemd" e "man systemd-system.conf"

SUGGERIMENTO: informazioni esaustive di debug su systemd sono disponibili in questa pagina di FreeDesktop.

SUGGERIMENTO: HCome controllare i parametri/opzioni della riga di comando del kernel?

# cat /proc/cmdline

NOTA: per LogLevel (vedere systemd(1) e systemd-system.conf(5)):

"Impostare il livello di log. Come argomentio accetta un livello di log numerico o anche i noti nomi simbolici di syslog(3) (in minuscolo): emerg, alert, crit, err, warning, notice, info, debug."

SUGGERIMENTO: tenere una copia di /sbin/init dal pacchetto sysvinit in caso di ripristino (così si può usare init=/sbin/init.sysvinit nella riga di comando del kernel)!

# cp -av /sbin/init /sbin/init.sysvinit <--- Prima di installare il pacchetto systemd-sysv

Vedere anche https://fedoraproject.org/wiki/How_to_debug_Systemd_problems

Debug del kernel senza debug di systemd in Jessie

Usare il vecchio parametro "debug" del kernel in Jessie attiva il log di debug di systemd oltre al log di debug del kernel. Per ottenere il vecchio comportamento, non usare "debug", ma usare invece il parametro "loglevel=7" del kernel.

Bug and sistemi di tracciamento dei bug

Problemi conosciuti e soluzioni

Montaggi bind condivisi

Il comportamento predefinito dei montaggi bind cambia in systemd. Il kernel Linux rende i montaggi bind di tutto ciò che è sotto / PRIVATI. Systemd cambia tutto ciò in CONDIVISO.

Perciò quando si esegue:

    mount --bind / $CHROOT
    mount --bind /dev/ $CHROOT/dev
    umount $CHROOT/dev

allora /dev viene smontata anche nel sistema base/genitore!

Ciò che si può fare ora invece è:

    mount --bind --make-rslave / $CHROOT
    mount --bind --make-rslave /dev/ $CHROOT/dev

ciò propaga i cambiamenti di montaggio (anche le opzioni di montaggio) nel sistema base/genitore nella $CHROOT ma non dalla $CHROOT indietro al genitore.

La ragione della modifica al comportamento predefinito può essere trovata nel bug 739593, in particolar modo nel commento di Lenart che contiene.

La sessione SSH non termina in modo pulito al riavvio o allo spegnimento

Se si riavvia o si spegne la macchina via ssh può succedere che la propria sessione non termini correttamente lasciando con un terminale non reattivo fino a che non è passato un lungo tempo di timeout. C'era il bug 751636 a questo proposito. Il problema era aggirabile installando:

    apt-get install libpam-systemd

che terminerà la sessione ssh prima della disattivazione della rete. Notare che ciò richiede l'abilitazione di PAM in sshd.

Messaggi di avvio mancanti in console(tty1) dopo l'avvio

Con systemd console(tty1) è gestita diversamente e se si era abituati a controllarla per vedere come era andato l'avvio ora si vedranno un paio di righe poco informative.

Per ottenere l'intera trascrizione dell'avvio di sistema sulla console è necessario effettuare due passaggi:

1. Aggiungere alle opzioni del kernel systemd.show_status=1, per esempio attraverso /etc/default/grub:

    GRUB_CMDLINE_LINUX_DEFAULT="quiet systemd.show_status=1"

ed eseguire update-grub2.

2. Creare il file /etc/systemd/system/getty@tty1.service.d/noclear.conf con il seguente contenuto:

[Service]
TTYVTDisallocate=no

per disabilitare la pulizia del terminale all'invocazione di getty.

Cambio di console virtuali e seriali

Chi era abituato a modificare inittab per abilitare o disabilitare console virtuali o seriali avrà notato che tale file non esiste più sulle installazioni pulite. Tutto ciò viene gestito ora direttamente attraverso systemd. Per esempio, si può abilitare una console seriale su COM1 con:

systemctl enable serial-getty@ttyS0.service
systemctl start serial-getty@ttyS0.service

Tuttavia è generalmente preferibile aggiungere console=ttyS0 alla riga di comando del kernel dato che ciò abilita anche l'output del kernel ai riavvii. Per esempio, per GRUB, ciò viene fatto aggiungendo quando segue a /etc/default/grub:

GRUB_CMDLINE_LINUX="console=ttyS0"

... ed eseguendo update-grub. Ciò avrà però effetto solamente al prossimo riavvio.

Notare anche che Linux gestisce più console per l'output, ma solo una per l'input; l'ultima indicata (o quella predefinita se nessuna viene indicata) dalla riga di comando del kernel specifica quale viene usata per l'input e tutte sono usate per l'output. Ad esempio per GRUB:

GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0"

Ciò farà sì che, dopo l'esecuzione di update-grub e il riavvio, si abbia l'input da console da /dev/ttyS0 e l'output sia in quel device sia in /dev/tty0. Notare anche che possono essere specificare anche parametri seriali, es.:

GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,9600n8"

Processi orfani

Dato che gestisce le sessioni utente (prendendo il ruolo di X o altri componenti) systemd può cambiare leggermente il modo in cui i processi sopravvivono ad un logoff. In modo predefinito, quando X viene chiuso, tutti i processi dovrebbero terminare e systemd ripulisce la sessione, ma ci sono alcuni casi particolari in cui certi processi non fanno correttamente pulizia.

Si può configurare il modo in cui systemd gestisce i processi residui con il parametro KillUserProcesses= in logind.conf. Impostandolo a yes, i processi verranno uccisi in modo forzato quando termina la sessione. Notare che ciò rende difettosi strumenti come screen o tmux, a meno che non siano configurati per essere eseguiti sotto una separata unità user@.service e se enable-linger è impostato a yes in loginctl. Un semplice modo per farlo al volo è di eseguire il programma in un "ambito transitorio" usando systemd-run:

systemd-run --scope --user screen

Ora le sessioni normali dovrebbero fare pulizia e i problemi relativi dovrebbero essere risolti senza dover ricorrere al metodo violento KillUserProcesses=yes. Un buon modo per elencare i processi che sono interessati da ciò è di raggrupparli per "control group", con il comando systemd-cgls:

systemd-cgls

Alcune applicazioni per le quali è noto che si comportano male:

Dove ottenere aiuto?

Systemd è un progetto giovane con una forte attenzione alla risoluzione dei problemi in modo indipendente dalla distribuzione.

I canali specifici di Debian includono:

Svariate altre distribuzioni usano systemd:

Installazione senza systemd

Vedere Init alla sezione "Cambiare il sistema init - al momento dell'installazione"

Risorse Debian

Altre risorse


CategoryPermalink