Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Eseguire un comando all'avvio

Sfruttando systemd, è possibile installare un servizio su Ubuntu Server (così come su altre distruzioni Linux), eseguendo un comando all'avvio.
Sfruttando systemd, è possibile installare un servizio su Ubuntu Server (così come su altre distruzioni Linux), eseguendo un comando all'avvio.
Link copiato negli appunti

Come già affermato nelle lezioni precedenti, un server Linux è essenzialmente un computer che esegue uno o più software progettati per offrire un servizio specifico. Nei sistemi Unix e Unix-like (come ad esempio GNU/Linux), l'esecuzione dei servizi è affidata ad un sottosistema dedicato: init. In particolare, init è il primo processo avviato in un sistema Unix o Unix-like, ed ha appunto lo scopo di inizializzare il sistema avviando (mediante forking) i servizi installati.

Nel mondo GNU/Linux si sono succedute diverse implementazioni di init, con lo scopo di superare le inevitabili limitazioni dovute ad uno standard vecchio di decenni. Ubuntu, dopo aver implementato la propria soluzione, upstart, ha adottato systemd a partire dalla versione 15.04, uniformandosi alle scelte effettuate dai maintainer delle maggiori distribuzioni. Sebbene questa scelta abbia originariamente scatenato delle polemiche, il vantaggio nell'adozione di un framework comune è innegabile.

Systemd

Systemd nasce in casa Red-Hat nel 2010. A differenza di upstart, launchd ed altri, non si tratta soltanto di un gestore di servizi. Systemd infatti integra un servizio centralizzato di logging (journald), un gestore di login (logind), un demone per la configurazione di rete (networkd) ed altro ancora.

Per configurare un servizio affinché esso venga gestito da systemd, è sufficiente creare un opportuno file di configurazione. Le configurazioni di systemd vengono dette "Unit" ed hanno struttura diversa in base alla risorsa che si vuole descrivere. Nel caso dei servizi, le unit sono contenute in file di testo con estensione .service. I file .service descrivono il servizio, il comando da eseguire e le modalità con cui esso debba essere eseguito, le eventuali dipendenze.

La sintassi delle unit di systemd è molto semplice e ricorda quella dei file .ini utilizzati in ambiente Windows.

I file .service possono fare riferimento ai file .target. I file .target sono usati per raggruppare le dipendenze tra più unità di systemd. Ad esempio, il file network.target è usato come dipendenza da tutti i servizi che devono essere avviati solo dopo che lo stack di rete è stato inizializzato.

Esistono poi file target per i vari runlevel del sistema. Ci sono infatti varie modalità con cui è possibile avviare un sistema Unix: in modalità rescue, in avvio normale, con console grafica, ecc. Queste modalità, che tradizionalmente corrispondono ai runlevel da 0 a 6, sono descritte da una serie di file .target. La corrispondenza tra runlevel e file target è mostrata nella tabella sottostante.

Runlevel Target Descrizione
0 runlevel0.target, poweroff.target Sistema spento.
1 runlevel1.target, rescue.target Sistema avviato in modalità di ripristino.
2 runlevel2.target, multi-user.target Runlevel non usato normalmente.
3 runlevel3.target, multi-user.target Sistema avviato senza interfaccia grafica.
4 runlevel4.target, multi-user.target Runlevel non usato normalmente..
5 runlevel5.target, graphical.target Sistema avviato con interfaccia grafica.
6 runlevel6.target, reboot.target Sistema in fase di riavvio.

Struttura di un file service

Supponiamo adesso di voler creare un file .service per il nostro software "MioServizio", in modo che il sistema avvii automaticamente il servizio e ne monitori lo stato di esecuzione. Un possibile file .service potrebbe essere il seguente:

[Unit]
Description=Servizio di esempio
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/mioservizio
ExecStart=/opt/mioservizio/MioServizio
Restart=always
[Install]
WantedBy=multi-user.target

La clausola After permette di indicare una dipendenza per il nostro servizio. In particolare, specificando "network.target" il nostro servizio verrà avviato solo dopo che lo stack di rete sarà inizializzato. In questa clausola è possibile specificare più di una unit, separandole da uno spazio. Ad esempio, se il nostro servizio dipende sia dalla rete sia da un altro servizio è possibile specificarli entrambi.

La sezione Service descrive il comando da eseguire. La clausola ExecStart specifica il comando, mentre la WorkingDirectory indica la directory di lavoro del processo.

Tipicamente, i processi eseguiti da systemd vengono avviati da root. In alcuni casi è necessario invece che il comando venga eseguito da un utente specifico. In questo caso, è possibile specificare il nome dell'utente con cui eseguire il comando con la clausola User nella sezione Service (ad esempio, User=mioutente).

La clausola Restart permette di richiedere a systemd di monitorare l'esecuzione del servizio e di intervenire automaticamente. In particolare, specificando "always" come nell'esempio, systemd provvederà a riavviare automaticamente il nostro servizio qualora il processo vada in crash. Altri possibili valori per questa clausola sono:

  • no - il servizio non verrà mai riavviato automaticamente;
  • on-success - il servizio verrà riavviato solo se termina correttamente (exit code 0);
  • on-failure - il servizio verrà riavviato solo se termina con un exit code diverso da 0;
  • on-abnormal - il servizio verrà riavviato solo se termina a causa di un segnale di terminazione;
  • on-watchdog - il servizio verrà riavviato solo se non risponde entro un tempo predefinito (specificato nella clausola WatchdogSec);
  • on-abort - il servizio verrà riavviato solo se termina a causa di un segnale di terminazione;

Infine, la clausola WantedBy permette di aggiungerlo alla lista di dipendenze del target multi-user. In questo modo, il nostro servizio verrà eseguito se il sistema sarà avviato con un run level compreso tra 2 e 4.

Analogamente, se volessimo lanciare il comando durante la fase di riavvio (supponendo ad esempio che il nostro servizio effettui qualche operazione di cleanup), dovremmo specificare nella clausola WantedBy il valore "reboot.target".

Esistono molte altre clausole che possono esssere specificate in un file .service. Per un elenco completo, si rimanda alla documentazione disponibile qui.

Attivazione e avvio del servizio

Il file .service così creato andrà salvato nella directory /etc/systemd/system. Nel caso dell'esempio di cui sopra il percorso completo potrebbe essere /etc/systemd/system/mioservizio.service.

Tuttavia ciò non basta, in quanto il servizio va attivato per rendere effettive le modifiche. Questa caratteristica permette di disabilitare temporaneamente un servizio senza dover rimuovere i relativi file di configurazione. Per abilitare il servizio è sufficiente digitare il comando:

# systemctl enable mioservizio.service

Il sistema provvederà a verificare la correttezza del file di configurazione e ad abilitarlo. A questo punto, all'avvio del sistema il nostro servizio verrà avviato automaticamente.

Inoltre è possibile gestire il servizio senza la necessità di riavviare, sia con i comandi "service start" e "service stop" (vedi lezione precedente), sia con il comando systemctl. Ad esempio, per riavviare il servizio basterà digitare:

# systemctl restart mioservizio.service

Ti consigliamo anche