Viết một tệp đơn vị systemd với một đường dẫn thực thi được thiết lập theo môi trường


17

Tôi đang viết một tệp đơn vị systemd cho một ứng dụng Java và tôi muốn kiểm soát phiên bản Java được sử dụng để khởi động nó. Tệp dịch vụ (đơn giản hóa) của tôi là

[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

Khi cố gắng khởi động tôi gặp lỗi

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.

Tôi biết rằng nó JAVA_HOMEđược đặt chính xác; nếu tôi thay đổi ExecStartdòng để bắt đầu /usr/bin/javavà sau đó thêm một cái gì đó như -DsomeOption=${JAVA_HOME}tôi có thể thấy nó tốt.

Cách giải quyết rõ ràng là tạo ra một tập lệnh bao bọc nhưng tôi cảm thấy rằng nó đánh bại điểm sử dụng tệp dịch vụ.

Làm cách nào tôi có thể đặt JAVA_HOME cho ứng dụng Java của mình bằng tệp đơn vị?


Tại sao chính xác kịch bản trình bao bọc lại đánh bại mục đích sử dụng tệp dịch vụ? Bạn vẫn nhận được theo dõi, giám sát tuần tự và phụ thuộc của systemd, v.v. Về cơ bản, systemd giao dịch với khả năng lập trình dạng tự do mà chúng tôi có với SysVinit để ủng hộ logic DTRT . Khi "điều đúng" là một cái gì đó systemd không làm, bạn cần đặt nó bên ngoài systemd, như trong một kịch bản shell.
Warren Young

@WarrenYoung - bởi vì tôi đột nhiên bắt đầu quản lý các kịch bản shell một lần nữa. Trong trường hợp của tôi, việc không quản lý tập lệnh shell sẽ hữu ích hơn các bit khác.
Robert Munteanu

Tôi thực sự không thấy vấn đề. Bạn có dành cả ngày để lo lắng về tất cả các thực thi bạn phải quản lý không? :)
Warren Young

3
Từ systemd.service (5): "Lưu ý rằng đối số đầu tiên (tức là chương trình thực thi) có thể không phải là một biến." Điều đó giải thích tại sao $ {JAVA_HOME} không được mở rộng ở đầu đường dẫn ứng dụng, mà là khi được sử dụng tại một số điểm sau đó.
Wieland

@WarrenYoung - Tôi thích một trình bao bọc hơn nhị phân. Tôi hiểu rằng đó không phải là vấn đề với tất cả mọi người, nhưng nó là dành cho tôi :-)
Robert Munteanu

Câu trả lời:


12

Từ phần "Dòng lệnh" trong systemd.service (5):

Lưu ý rằng đối số đầu tiên (tức là chương trình thực thi) có thể không phải là biến.

Tôi sẽ đề nghị sử dụng trình xác định cá thể %i(bạn có thể đọc thêm về nó trong systemd.unit (5)), nhưng (bây giờ chúng tôi quay lại systemd.service (5)):

đối số đầu tiên của dòng lệnh (tức là chương trình thực thi) có thể không bao gồm các chỉ định.

Tôi nghĩ rằng tùy chọn tốt nhất vào thời điểm này thực sự là tạo một tập lệnh shell bao bọc việc thực thi nhị phân java như được đề xuất bởi Warren Young hoặc bạn có thể ExecStart một shell như trong ví dụ cho các dòng lệnh shell trong phần "Dòng lệnh" của systemd.service (5) có ví dụ sau:

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

vì vậy bạn có thể làm (chưa được kiểm tra):

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

2

Một tùy chọn tương tự khác là sử dụng /usr/bin/env:

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

Bằng cách này, bạn có thể bỏ qua các 'trích dẫn xung quanh toàn bộ lệnh rất hữu ích nếu bạn cần lồng các công cụ được trích dẫn.

Tái bút Là một lưu ý phụ, điều quan trọng là phải đặt các tên biến trong {dấu ngoặc nhọn }trong các tệp Systemd nếu không chúng sẽ không được nhận dạng chính xác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.