環境によって設定された実行パスを使用してシステム単位ファイルを作成します。

環境によって設定された実行パスを使用してシステム単位ファイルを作成します。

私はJavaアプリケーション用のシステム単位ファイルを作成しており、それを実行するために使用されるJavaのバージョンを制御したいと思います。私の(単純化された)サービスファイルは次のとおりです。

[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

起動しようとすると、エラーメッセージが表示されます。

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

私はJAVA_HOMEそれが正しく設定されていることを知っています。行ExecStartの始まりを変更してこのような/usr/bin/javaものを追加すると、-DsomeOption=${JAVA_HOME}それを見ることができます。

確かな解決策はラッパースクリプトを作成することですが、サービスファイルを使用する目的に反しているようです。

ユニットファイルを使用してJavaアプリケーションのJAVA_HOMEをどのように設定しますか?

答え1

systemd.service(5) の「コマンドライン」セクションで:

最初の引数(つまり実行されるプログラム)は変数にすることはできません。

インスタンス指定子を使用することをお勧めします%i(これについての詳細はsystemd.unit(5)で読むことができます)。しかし(今はsystemd.service(5)に戻ります):

コマンドラインの最初の引数(つまり、実行されるプログラム)に指定子を含めることはできません。

この時点で最良のオプションは、Warren Youngが提案したようにJavaバイナリの実行をラップするシェルスクリプトを生成することです。または、「コマンドライン」のシェルコマンドラインの例のように、シェルをExecStartすることもできます。部分。 systemd.service(5) には次の例があります。

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

したがって、次のことができます(テストされていません)。

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

答え2

別の同様のオプションは、次のものを使用することです/usr/bin/env

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

これにより、'コマンド全体の引用符を省略できます。これは、引用符を入れ子にする必要がある場合に便利です。

PS。参考までに、Systemdファイルでは{変数名を中かっこで囲むことが非常に重要です。}それ以外の場合、正しく認識されません。

答え3

もう少し異なるオプションは別のシステムツールを使用していると仮定しますalternatives。 Java SDKがシステムパッケージで提供されている場合は、すでに準備ができている可能性が高くなります。手動でインストールした場合は、次の方法でシステムに追加する必要があります。

alternatives --install /usr/bin/java java /path/to/your/sdk/bin/java 3

最後の数字が優先順位です(高いほど重要です)。alternatives --display java新しいSDKに対して選択する優先順位を決定するコマンドを実行して、既存の優先順位を確認できます。

インストールしたら、/usr/bin/javaサービスファイルで使用し、alternatives --config javaサービスを開始する前に実行して選択するバージョンを決定できます。まだ実際に試していませんが、次のようにすることができるようです。

alternatives --set java /path/to/your/sdk/bin/java

...スクリプトでSDKを選択します。インタラクティブなインターフェイスがalternatives --configそのシナリオに適していない場合、これはオプションです。ディレクティブを使用してサービスファイルに設定することもできますExecStartPre

私はラッパースクリプトが本当に好きではありません。ほとんどは恐らく恐ろしいSysV initスクリプト(少なくとも始め)と同じです。おそらくラッパースクリプトで始まるサービスファイルは、実行中のコマンドが実行中のプロセスではないため、少し複雑になります。多くのsystemdディレクティブをナビゲートするのに時間を費やすことができれば、あなたはあなたが欲しいものを達成するためのよりきちんとした方法を見つけることができます。

関連情報