Articles

Creazione di un servizio Linux con systemd

Posted on
Creare propri servizi – Foto di Jeff Sheldon su Unsplash

Mentre scrivo applicazioni web, Ho spesso bisogno di scaricare compiti pesanti di calcolo su uno script lavoratore asincrono, pianificare compiti per dopo, o anche scrivere un demone che ascolta un socket per comunicare direttamente con i clienti.

Anche se a volte ci possono essere strumenti migliori per questo lavoro – considerate sempre di usare prima il software esistente, come ad esempio un server di code di attività – scrivere il proprio servizio può darvi un livello di flessibilità che non avrete mai quando siete legati ai vincoli di software di terze parti.

La cosa bella è che è abbastanza facile creare un servizio Linux: usate il vostro linguaggio di programmazione preferito per scrivere un programma a lunga esecuzione, e trasformatelo in un servizio usando systemd.

Creiamo un piccolo server usando PHP. Vedo le vostre sopracciglia alzarsi, ma funziona sorprendentemente bene. Ascolteremo la porta UDP 10000, e restituiremo qualsiasi messaggio ricevuto con una trasformazione ROT13:

Avviamo:

$ php server.php

E testiamolo in un altro terminale:

$ nc -u 127.0.0.1 10000
Hello, world!
Uryyb, jbeyq!

Fico, funziona. Ora vogliamo che questo script venga eseguito in ogni momento, sia riavviato in caso di fallimento (uscita inaspettata), e sopravviva anche al riavvio del server. È qui che entra in gioco systemd.

Trasformarlo in un servizio

Creiamo un file chiamato /etc/systemd/system/rot13.service:


Description=ROT13 demo service
After=network.target
StartLimitIntervalSec=0
Type=simple
Restart=always
RestartSec=1
User=centos
ExecStart=/usr/bin/env php /path/to/server.php

WantedBy=multi-user.target

Avrete bisogno di:

  • impostare il vostro vero nome utente dopo User=
  • impostare il percorso corretto del vostro script in ExecStart=

Ecco fatto. Ora possiamo avviare il servizio:

$ systemctl start rot13

E farlo partire automaticamente all’avvio:

$ systemctl enable rot13

Andare oltre

Ora che il servizio (si spera) funziona, può essere importante immergersi un po’ più a fondo nelle opzioni di configurazione, e assicurarsi che funzioni sempre come ci si aspetta.

Iniziare nel giusto ordine

Ti sarai chiesto cosa fa la direttiva After=. Significa semplicemente che il tuo servizio deve essere avviato dopo che la rete è pronta. Se il tuo programma si aspetta che il server MySQL sia attivo e funzionante, dovresti aggiungere:

After=mysqld.service

Riavvio all’uscita

Per default, systemd non riavvia il tuo servizio se il programma esce per qualsiasi motivo. Questo di solito non è quello che si vuole per un servizio che deve essere sempre disponibile, quindi gli stiamo ordinando di riavviare sempre all’uscita:

Restart=always

Si potrebbe anche usare on-failure per riavviare solo se lo stato di uscita non è 0.

Di default, systemd tenta un riavvio dopo 100ms. È possibile specificare il numero di secondi da attendere prima di tentare un riavvio, utilizzando:

RestartSec=1

Evitare la trappola: il limite di avvio

Io personalmente ci sono caduto più di una volta. Per impostazione predefinita, quando si configura Restart=always come abbiamo fatto noi, systemd rinuncia a riavviare il servizio se non riesce a partire più di 5 volte in un intervallo di 10 secondi. Per sempre.

Ci sono due opzioni di configurazione responsabili di questo:

StartLimitBurst=5
StartLimitIntervalSec=10

La direttiva RestartSec ha anche un impatto sul risultato: se si imposta il riavvio dopo 3 secondi, allora non si può mai raggiungere 5 tentativi falliti entro 10 secondi.

La semplice soluzione che funziona sempre è impostare StartLimitIntervalSec=0. In questo modo, systemd tenterà di riavviare il servizio per sempre.

È una buona idea impostare RestartSec ad almeno 1 secondo però, per evitare di mettere troppo stress sul vostro server quando le cose iniziano ad andare male.

In alternativa, è possibile lasciare le impostazioni predefinite e chiedere a systemd di riavviare il server se il limite di avvio viene raggiunto, utilizzando StartLimitAction=reboot.

E’ davvero così?

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *