Systemd

生成 systemd 服務文件後,init 服務無法啟用

  • January 19, 2022

我一直在解決 sysVinit 服務在 systemd 環境中啟動時無法正常聯機的問題。我發現,當所述服務的 /etc/systemd/system/ 中沒有服務文件或覆蓋時,它會正確自動啟動。在這種情況下,據我了解,systemd 應該通過讀取系統上存在的“舊版”sysvinit 腳本來動態載入啟動腳本,儘管我對此並不是 100% 清楚。

我感到困惑的是,一旦我將 edit –full 選項傳遞給 systemctl 以獲得所述服務,就會在 /etc/systemd/system/ 生成一個平面文件,並且所述服務現在無法在啟動時自動啟動。使用編輯選項並嘗試添加任何覆蓋似乎也會導致服務無法啟動。

如果需要,下面提供範例…

系統工作時的範例:

該服務(在此範例中稱為“ProgramExample”)有一個 init 腳本放置在 /etc/init.d/programexample 和 /etc/rc.d/init.d/programexample 中:

[root@centos7-box ~]# ls -l /etc/rc.d/init.d/programexample
-rwxr-xr-x. 1 root root 2264 Mar 29 14:11 /etc/rc.d/init.d/programexample

/etc/systemd/system/ 中沒有服務文件:

[root@centos7-box ~]# ls -lh /etc/systemd/system/programexample.service
ls: cannot access /etc/systemd/system/programexample.service: No such file or directory

此配置中的 Systemctl 狀態輸出:

[root@centos7-box ~]# systemctl status programexample.service
● programexample.service - LSB: Start Program Example at boot time
  Loaded: loaded (/etc/rc.d/init.d/programexample; bad; vendor preset: disabled)
  Active: active (exited) since Wed 2017-03-29 15:53:06 CDT; 14min ago
    Docs: man:systemd-sysv-generator(8)
 Process: 1297 ExecStart=/etc/rc.d/init.d/programexample start (code=exited, status=0/SUCCESS)

Mar 29 15:53:05 centos7-box systemd[1]: Starting LSB: Start ProgramExample at boot time...
Mar 29 15:53:05 centos7-box su[1307]: (to programexample) root on none
Mar 29 15:53:06 centos7-box programexample[1297]: ProgramExample (user programexample): instance name set to centos7-box
Mar 29 15:53:06 centos7-box programexample[1297]: instance public base uri set to https://192.168.0.148.programexample.net/programexample/
Mar 29 15:53:06 centos7-box programexample[1297]: instance timezone set to US/Central
Mar 29 15:53:06 centos7-box programexample[1297]: starting java services
Mar 29 15:53:06 centos7-box programexample[1297]: ProgEx server started.
Mar 29 15:53:06 centos7-box systemd[1]: Started LSB: Start ProgramExample at boot time.

使用上述配置,沒有在 /etc/systemd/system/ 中創建/放置任何文件,ProgramExample 服務會正確自動啟動。

一旦使用 systemctl edit –full (或只是編輯):

將任何編輯傳遞給 systemctl 後,我觀察到以下內容:

  • 一個平面文件或覆蓋目錄將放置在 /etc/systemd/system/
  • 所述服務(在本例中為 ProgramExample)無法在啟動時啟動。
  • 我將無法使用 systemctl“啟用”所述服務

此配置中的 Systemctl 狀態輸出(編輯後):

[root@centos7-box ~]# systemctl status programexample.service
● programexample.service - LSB: Start ProgramExample at boot time
  Loaded: loaded (/etc/rc.d/init.d/programexample; static; vendor preset: disabled)
  Active: inactive (dead)
    Docs: man:systemd-sysv-generator(8)

這是使用 -edit –full 選項時正在生成並放置在 /etc/systemd/system/ 中的服務文件:

# Automatically generated by systemd-sysv-generator

[Unit]
Documentation=man:systemd-sysv-generator(8)
SourcePath=/etc/rc.d/init.d/programexample
Description=LSB: Start ProgramExample at boot time
Before=runlevel2.target
Before=runlevel3.target
Before=runlevel4.target
Before=runlevel5.target
Before=shutdown.target
Before=adsm.service
After=all.target
After=network-online.target
After=postgresql-9.4.service
Conflicts=shutdown.target

[Service]
Type=forking
Restart=no
TimeoutSec=5min
IgnoreSIGPIPE=no
KillMode=process
GuessMainPID=no
RemainAfterExit=yes
ExecStart=/etc/rc.d/init.d/programexample start
ExecStop=/etc/rc.d/init.d/programexample stop
ExecReload=/etc/rc.d/init.d/programexample reload

這裡發生了什麼?如果沒有 /etc/systemd/system/ 中的平面服務文件和/或服務覆蓋目錄,systemd 從所述服務的初始化腳本中動態讀取此資訊,我是否更正?我已經嘗試過多次迭代編輯 /etc/systemd/system/ 中的服務文件並將預設文件保留在原處,並且無法自動啟動工作或服務進入“啟用”狀態。

我相信最好有一個用於 systemd 配置的 systemd .service 文件,而不是依賴 systemd 從 init 腳本 LSB 頭中讀取兼容性和並發原因,但是 systemd 創建的預設文件無法啟動或啟用以及許多其他我嘗試過的 .service 文件的更簡單的迭代。

我現在發現問題在於 systemd-sysv-generator 自動生成的服務文件缺少帶有 WantedBy 選項的安裝部分。我在 /etc/systemd/system/programexample.service 生成的文件中添加了以下內容,這使我能夠正確啟用該服務:

[Install]
WantedBy = multi-user.target

之後我跑了

systemctl daemon-reload

以確保我的服務文件被 systemd 讀取。

現在我收到了一個適當的通知,說我的服務實際上在某個地方被符號連結以“啟用”:

[root@centos7-box ~]# systemctl enable programexample.service
Created symlink from /etc/systemd/system/multi-user.target.wants/programexample.service to /etc/systemd/system/programexample.service.

這個連結幫助我更好地理解了服務文件。

我不喜歡 systemd-sysv-generator 預設不包含帶有 WantedBy 選項的安裝部分的方式。如果 systemd 可以動態讀取 LSB 標頭並在啟動時正確啟動服務,為什麼它不相應地生成服務文件?我想一些系統性的成長痛苦是可以預料的。

2020 年 7 月 7 日更新

與 Debian Buster 合作並嘗試啟用 SysVInit 遺留服務時,我收到了這條精彩的消息,我相信這會為我在 2017 年處理此問題時節省一些時間:

Synchronizing state of programexample.service with SysV
service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable
programexample
The unit files have no installation config (WantedBy=,
RequiredBy=, Also=, Alias= settings in the [Install] section,
and DefaultInstance= for template units). This means they are
not meant to be enabled using systemctl. 
Possible reasons for having this kind of units are:

• A unit may be statically enabled by being symlinked from
 another unit's .wants/ or .requires/ directory.
• A unit's purpose may be to act as a helper for some other
 unit which has a requirement dependency on it.
• A unit may be started when needed via activation (socket,
 path, timer, D-Bus, udev, scripted systemctl call, ...).
• In case of template units, the unit is meant to be enabled
 with some instance name specified.

引用自:https://unix.stackexchange.com/questions/354681