Scrittura di un file di unità systemd con un percorso eseguibile impostato dall'ambiente


17

Sto scrivendo un file di unità systemd per un'applicazione Java e vorrei controllare la versione di Java utilizzata per avviarlo. Il mio file di servizio (semplificato) è

[Service]
Type=simple
EnvironmentFile=%h/Documents/apps/app/app-%i/app.cfg
ExecStart=${JAVA_HOME}/bin/java ${JAVA_OPTS} -jar %h/Documents/apps/app/app-%i/myapp.jar
SuccessExitStatus=143

Quando provo ad avviarlo, ricevo un errore

Apr 28 12:43:37 rombert systemd[1613]: [/home/robert/.config/systemd/user/app@.service:7] Executable path is not absolute, ignoring: ${JAVA_HOME}/bin/java ${JAVA_OPT
Apr 28 12:43:37 rombert systemd[1613]: app@1.0.0.service lacks both ExecStart= and ExecStop= setting. Refusing.

So che JAVA_HOMEè impostato correttamente; se cambio la ExecStartlinea per cominciare /usr/bin/javae poi aggiungo qualcosa come -DsomeOption=${JAVA_HOME}posso vederlo bene.

La soluzione ovvia è quella di creare uno script wrapper ma ritengo che sconfigga il punto di usare un file di servizio.

Come posso impostare JAVA_HOME per la mia applicazione Java usando un file di unità?


Perché lo script wrapper vanifica esattamente lo scopo di utilizzare un file di servizio? Ottieni ancora il sequenziamento e il monitoraggio delle dipendenze di Systemd, il monitoraggio, ecc. Fondamentalmente, systemd scambia la programmabilità in formato libero che avevamo con SysVinit a favore della logica DTRT integrata . Quando "la cosa giusta" è qualcosa che systemd non fa, devi metterlo al di fuori di systemd, come in uno script di shell.
Warren Young,

@WarrenYoung - perché improvvisamente ricomincio a gestire nuovamente gli script della shell. Nel mio caso non gestire uno script di shell è più utile degli altri bit.
Robert Munteanu,

Davvero non vedo il problema. Trascorri le tue giornate preoccupandoti anche di tutti gli eseguibili che devi gestire? :)
Warren Young,

3
Da systemd.service (5): "Notare che il primo argomento (ovvero il programma da eseguire) potrebbe non essere una variabile." Ciò spiega perché $ {JAVA_HOME} non viene espanso all'inizio del percorso delle applicazioni, ma viene utilizzato in un secondo momento.
Wieland,

@WarrenYoung - Preferisco un singolo wrapper rispetto al binario. Capisco che non è un problema per tutti, ma è per me :-)
Robert Munteanu,

Risposte:


12

Dalla sezione "Righe di comando" in systemd.service (5):

Si noti che il primo argomento (ovvero il programma da eseguire) potrebbe non essere una variabile.

Stavo per suggerire di usare l' %iidentificatore di istanza (puoi leggere di più su di esso in systemd.unit (5)), ma (ora siamo di nuovo in systemd.service (5)):

il primo argomento della riga di comando (ovvero il programma da eseguire) potrebbe non includere specificatori.

Penso che l'opzione migliore a questo punto sia davvero quella di creare uno script shell che avvolga l'esecuzione del binario java come suggerito da Warren Young o potresti avviare una shell direttamente come nell'esempio per le righe di comando della shell nella sezione "Linee di comando" di systemd.service (5) che ha il seguente esempio:

ExecStart=/bin/sh -c 'dmesg | tac'

quindi potresti fare (non testato):

ExecStart=/bin/sh -c '${JAVA_HOME}....'

2

Un'altra opzione simile è usare /usr/bin/env:

ExecStart=/usr/bin/env "${JAVA_HOME}/bin/java" -jar ...

In questo modo è possibile omettere le 'virgolette attorno all'intero comando, utile se è necessario nidificare elementi citati.

PS. Come nota a margine , è importante racchiudere i nomi delle variabili tra {parentesi graffe }nei file Systemd, altrimenti non verranno riconosciuti correttamente.

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.