為什麼 systemd 不知道服務是否失敗?

為什麼 systemd 不知道服務是否失敗?

我正在嘗試在 Ubuntu 18.04 上配置 spring-boot 應用程式(由其他人開發 - 我不是 java 程式設計師)。開發人員之前添加了符號連結來/etc/init.d啟用該服務 - 它在啟動時啟動良好。但是,如果該服務隨後失敗,systemd 仍會報告它正在運行:

[email protected]:/var/log/apps# systemctl status crm-service
● crm-service.service - LSB: crm-service
   Loaded: loaded (/etc/init.d/crm-service; generated)
   Active: active (exited) since Wed 2020-04-15 12:27:15 BST; 3h 56min ago
     Docs: man:systemd-sysv-generator(8)
  Process: 8656 ExecStop=/etc/init.d/crm-service stop (code=exited, status=0/SUCCESS)
  Process: 8703 ExecStart=/etc/init.d/crm-service start (code=exited, status=0/SUCCESS)

Apr 15 12:27:15 example.com systemd[1]: Starting LSB: crm-service...
Apr 15 12:27:15 example.com crm-service[8703]: /var/services/crm-service.conf: line 1: -Xms96M: command not found
Apr 15 12:27:15 example.com crm-service[8703]: Started [8747]
Apr 15 12:27:15 example.com systemd[1]: Started LSB: crm-service.

當我看到相同的 systemd 單元文件對於互聯網上發布的 springboot,我沒有看到任何可能解決此問題的內容。

  1. 如何讓 systemd 查看服務的真實狀態? (它將打開一個偵聽套接字,但在隨機的高連接埠上)
  2. 有沒有辦法讓 systemd 試試看輕輕地重新啟動它知道失敗的服務?

答案1

Systemd 有很多批評者,其中很多都還不錯,但事實並非如此。Systemd 可以追蹤從啟動腳本分叉(或克隆)的所有進程和線程,如果沒有留下任何進程和線程,則認為服務已死亡。

我看到的第一個問題是:systemd 不使用啟動/停止腳本/etc/init.d,它只是一個相容性插件。相反,systemd 使用單元文件,即其所有服務的設定檔。

systemd sysv init compat 模組有效地為/etc/init.d.這並不總是可以的,因為初始化腳本缺少所需的資訊(或不可能從它們中提取資訊)。

該 compat 模組的工作方式是,如果退出程式碼非零,則 systemd 認為 init 腳本失敗,因此服務無法運作。零退出代碼意味著成功執行。如果 init 腳本有錯誤並且即使失敗也給出零退出代碼,它會欺騙 systemd。

初始化腳本錯誤最可能的原因是它在背景啟動進程,然後總是以零退出。我對大多數由自訂提供者編寫的初始化腳本的共同經驗是……也許它們中的大多數都有很大的改進空間。不要相信他們,看看他們做了什麼並修復它們。對於你的情況,最好是檢查一下,

  • 它如何啟動你的java應用程式
  • 從哪裡開始
  • 由哪個使用者啟動

並使用單元文件重現相同的功能。

無法從 systemd 自動重新啟動 initscripts,但可以從單元檔案自動重新啟動。

請注意,如果 Java 程式隨機崩潰,這也是一個嚴重的問題。所有健全的 java 框架都會正確處理自己的致命錯誤(它們捕獲所有異常,記錄並繼續)。

init 腳本中另一個很可能的錯誤是它找不到您的 JVM(最有可能是:/usr/bin/java),因此它用空字串取代它,導致它嘗試將 JVM 標誌作為 shell 命令啟動。顯然-Xms96M您的系統中沒有命令,但/usr/bin/java -Xms96M ...可以使用。

Spring Boot 應用程式的範例單元檔案:

[Unit]
Description=Crm Spring Boot App Example
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/java -Xms96M ...other flags... your.spring.boot.jar
User=exampleuser
Group=examplegroup
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=exampleapp
WorkingDirectory=/path/to/app/home

[Install]
WantedBy=multi-user.target
Alias=exampleapp.service

該單元檔案也將 Java 進程的標準輸出和錯誤重定向到系統日誌中。

若要自動重新啟動應用程序,請插入

RestartSec=5s
Restart=on-failure

進入該[Service]部分。

有一個 systemd 教程GoLinuxCloud.com

相關內容