Linux – Systemd Service Type

Loading

透過自己寫 Systemd Unit Files 方式來取代傳統的 (crontab) cron table 啟動程式.

測試環境 CentOS 8 x86_64 (虛擬機)

寫了一支會定期 60 秒寫入時間資料到檔案的 c++ 程式.

[root@localhost ~]# vi test.cpp 
#include <fstream>
#include <iostream>
#include <chrono>
#include <ctime> 
#include <unistd.h>

using namespace std;

int main() {
while(true)
{
    ofstream myFile_Handler;
    // File Open
    myFile_Handler.open("/tmp/1.txt", std::ios_base::app);

    auto timenow = chrono::system_clock::to_time_t(chrono::system_clock::now());
  
    // Write to the file
    myFile_Handler << ctime(&timenow) << endl;

    // File Close
    myFile_Handler.close();
   
    // Sleep
    sleep(60);
}
}

編譯成可執行檔.

[root@localhost ~]# g++ test.cpp -o test
bash: g++: command not found...
Install package 'gcc-c++' to provide command 'g++'? [N/y] y

程式放到 /sbin/ 路徑.

[root@localhost ~]# cp test /sbin/

開始編輯 Systemd Unit Files (一般使用者寫的 service 檔案放在 /etc/systemd/system/ ,系統的放在 /usr/lib/systemd/system).

[root@localhost ~]# vi /etc/systemd/system/test.service 
[Unit]
Description=Test Job
 
[Service]
Type=simple
ExecStart=/sbin/test

[Install]
WantedBy=multi-user.target

只簡單設定3個區塊

  1. [unit]
    Description=Test Job
    

    Description 敘述該 Systemd Unit Files 目的.

  2. [Service]
    Type=simple
    ExecStart=/sbin/test
    

    Type=simple – A long-running process that does not background its self and stays attached to the shell.
    ExecStart – 指定執行程式.

  3. [Install]
    WantedBy=multi-user.target
    

    指定哪一個 runlevel 執行.

啟動服務

[root@localhost ~]# systemctl enable test.service
Created symlink /etc/systemd/system/multi-user.target.wants/test.service → /etc/systemd/system/test.service.
[root@localhost ~]# systemctl start test.service
[root@localhost ~]# systemctl status test.service
● test.service - Test Job
   Loaded: loaded (/etc/systemd/system/test.service; enabled; vendor preset: disabled)
   Active: active (running) since Fri 2022-11-25 11:02:40 CST; 7s ago
 Main PID: 89850 (test)
    Tasks: 1 (limit: 49322)
   Memory: 292.0K
   CGroup: /system.slice/test.service
           └─89850 /sbin/test

Nov 25 11:02:40 localhost.localdomain systemd[1]: Started Test Job.

檢視 /sbin/test (定期 60 秒寫入時間資料到檔案 /tmp/1.txt) 是否有正常執行.

[root@localhost ~]# cat /tmp/1.txt
Fri Nov 25 11:02:40 2022

Fri Nov 25 11:03:40 2022

Fri Nov 25 11:04:40 2022

結束測試.

[root@localhost ~]# systemctl stop test.service
[root@localhost ~]# systemctl disable test.service
Removed /etc/systemd/system/multi-user.target.wants/test.service.

Note:

其中的 type 是最困惱的地方,要選哪一種?

  • simple – A long-running process that does not background its self and stays attached to the shell.
  • forking – A typical daemon that forks itself detaching it from the process that ran it, effectively backgrounding itself.
  • oneshot – A short-lived process that is expected to exit.
  • dbus – Like simple, but notification of processes startup finishing is sent over dbus.
  • notify – Like simple, but notification of processes startup finishing is sent over inotify.
  • idle – Like simple, but the binary is started after the job has been dispatched.

以上的程式是無法使用 type=forking

[root@localhost ~]# vi /etc/systemd/system/test.service 
[Unit]
Description=Test Job
 
[Service]
Type=forking
ExecStart=/sbin/test
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart test.service
Job for test.service failed because a timeout was exceeded.
See "systemctl status test.service" and "journalctl -xe" for details.
[root@localhost ~]# systemctl status test.service
● test.service - Test Job
   Loaded: loaded (/usr/lib/systemd/system/test.service; static; vendor preset: disabled)
   Active: failed (Result: timeout) since Wed 2022-09-14 17:59:09 CST; 12s ago
  Process: 2682 ExecStart=/sbin/test (code=killed, signal=TERM)
 Main PID: 2654 (code=killed, signal=TERM)

 9月 14 17:57:39 localhost.localdomain systemd[1]: Stopping Test Job...
 9月 14 17:57:39 localhost.localdomain systemd[1]: test.service: Succeeded.
 9月 14 17:57:39 localhost.localdomain systemd[1]: Stopped Test Job.
 9月 14 17:57:39 localhost.localdomain systemd[1]: Starting Test Job...
 9月 14 17:59:09 localhost.localdomain systemd[1]: test.service: start operation timed out. Terminating.
 9月 14 17:59:09 localhost.localdomain systemd[1]: test.service: Failed with result 'timeout'.
 9月 14 17:59:09 localhost.localdomain systemd[1]: Failed to start Test Job.
[root@localhost ~]# journalctl -xe
-- 
-- 單位 test.service 已開始啟動。
 9月 14 17:59:09 localhost.localdomain systemd[1]: test.service: start operation timed out. Terminating.
 9月 14 17:59:09 localhost.localdomain systemd[1]: test.service: Failed with result 'timeout'.
-- Subject: Unit failed
-- Defined-By: systemd
-- Support: https://access.redhat.com/support
-- 
-- The unit test.service has entered the 'failed' state with result 'timeout'.
 9月 14 17:59:09 localhost.localdomain systemd[1]: Failed to start Test Job.
-- Subject: 單位 test.service 已失敗
-- Defined-By: systemd
-- Support: https://access.redhat.com/support
-- 
-- 單位 test.service 已失敗。
-- 
-- 結果為 failed。

關於 simple 與 forking 使用時機請參考說明 – https://superuser.com/questions/1274901/systemd-forking-vs-simple

  • simple
    If the service starts and keeps running, and the prompt does not return until you press Control-C or stop the service in some other way.
  • forking
    If the prompt returns but the service keeps running in the background (i.e. the service daemonizes itself on its own).
沒有解決問題,試試搜尋本站其他內容

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料