coldwa.st
Tutte le guideProgrammazioneWebDatiStrumentiDatabaseHaskellConcettiCabal e buildToolchainCompilatorePrestazioniEditor e HLS

Coldwast

Generatore di file di servizio systemd

Inserisci il comando che avvia la tua applicazione e ottieni un'unità .service da mettere in /etc/systemd/system/, con i relativi comandi di installazione. Il generatore rilegge anche ciò che hai scritto e segnala gli errori che fanno fallire un'unità al primo avvio. Tutto gira nel tuo browser.

Frontale di un server tower con griglia metallica forata e piccoli pulsanti di accensione, illuminato di blu su sfondo scuro
Il pannello frontale di un server tower, illuminato di blu. Una volta abilitata l'unità, systemd avvia la tua applicazione su una macchina come questa a ogni avvio, senza che nessuno effettui l'accesso.
Parti da

Il tuo file di unità

 

Cosa ha notato il generatore

    Installarlo

     

    Le cinque righe che decidono se funziona

    ExecStart non è una shell. systemd divide da solo la riga in argomenti ed esegue direttamente il programma. Una pipe, una redirezione > o un && arriva al tuo programma come argomento letterale. systemd espande anche $VAR per conto suo, quindi un dollaro letterale si scrive $$. Quando il generatore rileva sintassi di shell, avvolge il comando in /bin/sh -c e fa questo escape al posto tuo.

    Usa un percorso assoluto. Un percorso come ./server viene rifiutato subito. Un nome senza percorso come node è accettato, ma systemd cerca solo nelle proprie directory fisse, non nel PATH della tua shell: un Node installato con nvm o uno strumento in ~/.local/bin non viene trovato.

    Type=simple o exec per quasi tutto. Un server web, un worker o un bot che resta in primo piano è simple. exec differisce in un punto utile: l'avvio viene considerato riuscito solo quando il binario è stato davvero eseguito, quindi un percorso sbagliato fa fallire systemctl start invece di fallire in silenzio un attimo dopo. forking serve ai vecchi demoni che vanno da soli in background, e notify funziona solo se il programma chiama sd_notify.

    Restart=on-failure, con un limite. on-failure riavvia dopo un crash o un'uscita diversa da zero, ma non dopo un arresto pulito; always riavvia anche in quel caso. Per impostazione predefinita systemd consente 5 avvii in 10 secondi, e con un'attesa di 5 secondi un'app che va in crash non raggiunge mai quel limite: gira in tondo all'infinito. StartLimitIntervalSec=300 con StartLimitBurst=5 la fa arrendere e lascia uno stato di errore chiaro.

    Wants= e After= insieme. After=network-online.target da solo fissa soltanto un ordine; non attiva il target. Senza Wants=network-online.target il servizio può comunque partire prima che la rete sia pronta: il classico «funziona dopo un riavvio manuale, fallisce al boot».

    L'isolamento, e ciò che è stato escluso di proposito

    Con ProtectSystem=strict l'intero filesystem è in sola lettura per il servizio, tranne i percorsi elencati in ReadWritePaths=. PrivateTmp gli dà un proprio /tmp, NoNewPrivileges gli impedisce di ottenere privilegi tramite binari setuid, e le impostazioni del kernel e dei cgroup gli impediscono di modificare lo stato del sistema. Esegui systemd-analyze security tuaapp.service prima e dopo: mostra un punteggio di esposizione ed elenca ogni impostazione ancora aperta.

    Due raccomandazioni comuni mancano di proposito. MemoryDenyWriteExecute=true rompe i compilatori just-in-time, cioè Node.js, la JVM e PyPy. PrivateDevices=true va bene per un'app web ma rompe tutto ciò che comunica con una GPU o una porta seriale. Aggiungile tu se sai che il tuo programma non ne ha bisogno.

    Un paio di occhiali su una scrivania davanti a un monitor sfocato che mostra codice sorgente colorato in un editor
    Occhiali appoggiati davanti a uno schermo pieno di codice. Quando un'unità fallisce, la risposta è anche sullo schermo: systemctl status fornisce il codice di uscita, journalctl l'output del tuo programma.

    Quando non parte: i codici di uscita

    systemctl status tuaapp mostra uno stato come status=203/EXEC. Il numero indica quale passaggio è fallito prima ancora che il programma partisse:

    StatoSignificatoSoluzione abituale
    203/EXECImpossibile eseguire il programmaPercorso errato, permesso di esecuzione mancante o script senza riga shebang
    200/CHDIRWorkingDirectory mancante o non accessibileCrearla, o verificare che ProtectHome non la nasconda
    217/USERL'account di User= non esisteEseguire la riga useradd qui sopra
    226/NAMESPACEImpossibile predisporre l'isolamentoUn percorso in ReadWritePaths non esiste: crearlo o anteporgli -

    Qualsiasi altro errore è il tuo programma che termina, e il suo output è in journalctl -u tuaapp -b.

    Modificarlo in seguito

    Dopo aver modificato il file in /etc/systemd/system/, esegui sudo systemctl daemon-reload prima di riavviare, altrimenti systemd continua a usare la vecchia versione. Per un'unità installata da un pacchetto, non modificarla sul posto: sudo systemctl edit tuaapp crea un file di override che sopravvive agli aggiornamenti e ricarica systemd per te.

    Da leggere anche: che cos'è un VPS, mettere un reverse proxy davanti all'app, le basi di SSH e, per i processi pianificati, il decodificatore di espressioni cron.

    Le direttive seguono le pagine di manuale systemd.service(5) e systemd.exec(5). Type=exec richiede systemd 240 o successivo; tutte le versioni attuali di Debian, Ubuntu, Fedora e RHEL lo soddisfano.