การเขียนไฟล์ systemd unit ด้วยพา ธ ที่ปฏิบัติการได้ที่ตั้งค่าสภาพแวดล้อม


17

ฉันกำลังเขียนไฟล์ systemd unit สำหรับแอปพลิเคชัน 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/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.

ฉันรู้ว่าJAVA_HOMEตั้งไว้ถูกต้อง; ถ้าฉันเปลี่ยนExecStartบรรทัดเพื่อเริ่มต้นด้วย/usr/bin/javaจากนั้นเพิ่มสิ่งที่-DsomeOption=${JAVA_HOME}ฉันเห็นมันก็โอเค

วิธีแก้ปัญหาที่ชัดเจนคือการสร้างสคริปต์ตัวตัด แต่ฉันรู้สึกว่ามันเอาชนะจุดที่ใช้ไฟล์บริการ

ฉันจะตั้ง JAVA_HOME สำหรับแอปพลิเคชัน Java ของฉันโดยใช้ไฟล์หน่วยได้อย่างไร


ทำไมสคริปต์แรปเปอร์เสียจุดประสงค์ในการใช้เซอร์วิสไฟล์ใช่หรือไม่ คุณยังคงได้รับการจัดลำดับและการติดตามการพึ่งพาของ systemd การตรวจสอบและอื่น ๆ โดยทั่วไป systemd ทำการแลกเปลี่ยนความสามารถในการเขียนโปรแกรมในรูปแบบอิสระที่เรามีกับ SysVinit เพื่อให้เข้ากับตรรกะของDTRT เมื่อ "สิ่งที่ถูกต้อง" เป็นสิ่งที่ systemd ไม่ได้ทำคุณจะต้องวางระบบนั้นไว้ข้างนอกเช่นในเชลล์สคริปต์
Warren Young

@WarrenYoung - เพราะฉันเริ่มจัดการเชลล์สคริปต์อีกครั้ง ในกรณีของฉันไม่ได้จัดการเชลล์สคริปต์มีประโยชน์มากกว่าบิตอื่น ๆ
Robert Munteanu

ฉันไม่เห็นปัญหาจริงๆ คุณใช้เวลาทั้งวันกังวลกับสิ่งที่คุณต้องจัดการทั้งหมดหรือไม่? :)
Warren Young

3
จาก systemd.service (5): "โปรดทราบว่าอาร์กิวเมนต์แรก (เช่นโปรแกรมที่จะดำเนินการ) อาจไม่ใช่ตัวแปร" นั่นอธิบายว่าทำไม $ {JAVA_HOME} ไม่ได้ถูกขยายที่จุดเริ่มต้นของเส้นทางแอปพลิเคชัน แต่จะใช้เมื่อใช้ในภายหลัง
Wieland

@WarrenYoung - ฉันชอบ wrapper เดียวมากกว่าไบนารี ฉันเข้าใจว่ามันไม่ใช่ปัญหาสำหรับทุกคน แต่สำหรับฉัน :-)
Robert Munteanu

คำตอบ:


12

จากส่วน "บรรทัดคำสั่ง" ใน systemd.service (5):

โปรดทราบว่าอาร์กิวเมนต์แรก (เช่นโปรแกรมที่จะดำเนินการ) อาจไม่ใช่ตัวแปร

ฉันจะแนะนำให้ใช้ตัวระบุอินสแตนซ์%i(คุณสามารถอ่านเพิ่มเติมเกี่ยวกับมันใน systemd.unit (5)) แต่ (ตอนนี้เรากลับมาที่ systemd.service (5)):

อาร์กิวเมนต์แรกของบรรทัดคำสั่ง (เช่นโปรแกรมที่จะดำเนินการ) อาจไม่มีตัวระบุ

ฉันคิดว่าตัวเลือกที่ดีที่สุด ณ จุดนี้คือการสร้างเชลล์สคริปต์ที่ล้อมรอบการดำเนินการของไบนารี java ตามที่แนะนำโดย Warren Young หรือคุณสามารถ ExecStart เชลล์โดยตรงเช่นในตัวอย่างสำหรับบรรทัดคำสั่งเชลล์ในส่วน "Command Lines" ของ 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 มิฉะนั้นจะไม่สามารถจดจำชื่อได้อย่างถูกต้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.