환경에 의해 설정된 실행 경로를 사용하여 시스템 단위 파일을 작성합니다.

환경에 의해 설정된 실행 경로를 사용하여 시스템 단위 파일을 작성합니다.

저는 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 ...

이렇게 하면 '전체 명령 주위의 따옴표를 생략할 수 있으며, 이는 인용된 내용을 중첩해야 할 때 유용합니다.

추신. 참고로 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 지시문을 탐색하는 데 시간을 할애할 수 있다면 투박한 래퍼 스크립트를 고수하지 않고도 원하는 것을 달성할 수 있는 더 깔끔한 방법을 찾을 수 있습니다.

관련 정보