使用 systemd 設定 java 守護程式

使用 systemd 設定 java 守護程式

我在工作中使用這個定義systemd

 [Unit]
 Description=Some job

 [Service]
 ExecStart=/usr/local/sbin/somejob
 User=dlt
 Type=forking

 [Install]
 WantedBy=multi-user.target

該腳本的呼叫方式如下(呼叫一個偵聽 tcpip 套接字並將輸入附加到檔案的簡單例程):

 #!/bin/sh

 cd /home/user/tmp/testout
 nohup java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar </dev/null >/dev/null &

systemctl start somejob進程顯示為正在運行後,init作為其父進程:

 user@CANTANDO ~$ ps -u dlt eo pid,ppid,command
   PID  PPID COMMAND
  8718     1 java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar

執行systemctl stop somejob該程序後不再顯示(且連接埠已關閉)。

所以一切看起來都很好而且花花公子

我的問題是:這是一個可接受的解決方案運行 java 守護進程systemd,或者是否有警告,以及其他更穩定或安全的方法來實現這一目標?

答案1

以下是一些小的修改:

  1. 由於它偵聽網路套接字,因此使其成為network.target.
  2. nohup不需要,因為systemd將為您守護可執行檔。
  3. 我認為單獨的 shell 腳本太過分了,所以只需將其合併到服務文件中即可。
  4. < /dev/null由於 systemd 設定了適當的標準 I/O 上下文,因此不需要重定向(等等)。事實上,如果你採取重定向出去systemd 將在其日誌中記錄 Java 程式傳送至標準輸出的任何內容,無需特殊的日誌記錄機制。
  5. &不需要也不適合從呼叫 shell () 非同步運行。
  6. 需要一個特定的行為模式Type=forking,如果守護程式不遵循它,就會出錯。所以嘗試Type=simple(或Type=notify)。

所以服務文件如下圖所示:

[Unit]
Description=Some job
After=network.target

[Service]
WorkingDirectory=/home/user/tmp/testout
SyslogIdentifier=SocketTest
ExecStart=/bin/sh -c "exec java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar"
User=dlt
Type=simple

[Install]
WantedBy=multi-user.target

筆記:

  1. 您不能僅用作java要執行的程式的名稱。 systemd 不搜尋PATH可執行文件,且給出的可執行文件的名稱ExecStart必須是絕對的。因此,如果您想要路徑搜索,則必須透過 shell 或/usr/bin/env.我們選擇/bin/sh這裡。
  2. 因為這是Type=simple必須Java的shell exec,不能將其作為子進程運行。 systemd 透過主程序控制服務,並且需要是 Java,而不是父 shell 程序。
  3. 因為這不是直接呼叫 Java 可執行文件,所以 systemd 會將名稱sh作為服務名稱放入其日誌中。看如何避免 /usr/bin/env 在 systemd 日誌中被標記為執行檔了解更多相關資訊。

據我所知,使用 Systemd 運行 Java 應用程式沒有特別的警告。

相關內容