Rhel 7:如果給予後台選項,systemd 無法啟動程序

Rhel 7:如果給予後台選項,systemd 無法啟動程序

我有一個 systemd 單元檔案(serv_unit.service):

[Unit]
Description=My service

[Service]
Type=simple
Restart=always
RestartSec=60
StartLimitInterval=400
StartLimitBurst=3
ExecStart=/etc/init.d/myscript start

[Install]
WantedBy=multi-user.target

/etc/init.d/myscript

source /etc/myfile.sh # JAVA_home & other vars are resolved through this file
mode=$1
case "$mode" in
  'start')
    # Start daemon
    daemon --user=abc $JAVA_HOME/bin/java -cp $appClassPath $MAIN_CLASS $args &

我面臨的問題是當我執行以下命令時:

systemctl start serv_unit.service

我沒有看到java進程。但是當我刪除尾隨&IE:

daemon --user=abc $JAVA_HOME/bin/java -cp $appClassPath $MAIN_CLASS $args

可以看到java進程(並且java進程沒有崩潰,因此排除了它在後台崩潰的可能性)

原因是什麼?

答案1

除了主要問題之外,從 systemd 呼叫 init.d 腳本有點多餘,而且通常從一開始就是一個壞主意。這就是您所需要的:

User=abc
EnvironmentFile=/etc/myfile.conf
ExecStart=/usr/bin/env $JAVA_HOME/bin/java -cp $appClassPath $MAIN_CLASS $args

EnvironmentFile 只能是普通的 KEY=value 分配,但如果設定必須採用 shell 腳本語法,您也可以使用:

User=abc
ExecStart=/bin/sh -c ". /etc/myfile.sh && exec $$JAVA_HOME/bin/java -cp $$appClassPath $$MAIN_CLASS $$args"

SyslogIdentifier=(如果服務產生標準輸出訊息,您還應該在這兩種情況下進行設定。)

服務類型

Systemd 服務預計遵循特定規則。一個.service單元只能有一個「主」守護程序,該Type=選項告訴 systemd 該進程如何運作。

Type=simple表示初始進程(即從 ExecStart= 啟動的進程)本身就是服務的主進程。一旦主進程退出,服務就被認為已經停止了,因此所有剩餘物都會被清理乾淨。

這意味著如果您使用 Type=simple,您就是在告訴 systemd 該守護進程將不會進入“背景”。事實上,你還告訴 systemdinit.d 腳本– 不是daemon– 是服務的主要流程...

exec因此,如果 init.d 腳本不僅不嘗試將實際的守護程序置於後台,而且還通過如下方式啟動它,那就最好了:

case "$mode" in
    'start-foreground')
        # Start daemon in foreground
        exec daemon --user=abc $JAVA_HOME/bin/java -cp $appClassPath $MAIN_CLASS $args

另一方面,Type=forking表示初始過程將要在啟動過程中 fork 並退出,並且應該從 PIDFile= 或啟發式發現主程序。

使用哪一個

使用具有以下功能的守護進程內建「守護程式」模式Type=forking具有顯著的優勢:systemd 服務保持在「正在啟動」狀態,直到守護程式最終嘗試進入後台,此時它最終會移動到「已啟動/活動」狀態。這有助於配置依賴項,例如服務 A 可以聲明「After=B.service」。

但是,如果後台是透過外部方式完成的,例如 shell&功能 – 沒有任何可以報告守護程序是否準備就緒的東西 – 那麼它就完全結束了無用你可能應該Type=simple在沒有任何背景選項的情況下使用。

相關內容