轉載: https://blog.51cto.com/littledevil/1912570
System.service:
服務單元,你可以理解為系統服務和原來的init.d下面的服務一樣,只是比它更加豐富。每一個服務都是以.service進行標識的,如下圖:
systemctl list-unit-files --type=service
STATE 說明
disabled 表示開機不啟動
enabled 表示開機啟動
static 對應Unit文件中沒有定義[install]區域,因此無法設置為開機啟動
我們看看一個服務包含哪些內容:
systemctl cat sshd.service
通過這個圖是不是可以看出一些聯系呢?和之前說的單元概念中包括的[Unit]段和[Install]段,這里還多了一個[Service]段,這個段就是用來定義服務的。我們先說一下常用的配置項有哪些:
配置項 說明
Type=
可以包含的值為simple、forking、oneshot、dbus、notify、idel其中之一。
**simple**:表示ExecStar=進程是該服務的主進程。如果它需要為其他進程提供服務,那么必須在該服務啟動之前先建立好通信渠道,比如套接字,以加快后續單元的啟動速度。
**forking**:表示ExecStar=進程將會在啟動時使用fork()函數,這是傳統Unix系統的做法,也就是這個進程將由systemd進程fork出來,然后當該進程都准備就緒時,systemd進程退出,而fork出來的進程作為服務的主進程繼續運行,對於此類型的進程,建議設置PIDFile=選項,以幫助systemd准確定位該服務的主進程。
**oneshot**:該進程會在systemd啟動后續單元之前退出,適用於僅需要執行一次的程序。比如清理磁盤,你只需要執行一次,不需要一直在后台運行這個程序。
**dbus**:該進程需要在D-Bus上獲得一個由BusName=指定的名稱,systemd將會在啟動后續單元之前,首先確保該進程已經成功的獲取了指定D-Bus名稱。
**notify**:與simple類似,不同之處在於該進程會在啟動完成之后通過sd_notify之類的接口發送一個通知消息。systemd在啟動后續單元之前,必須確保該進程已經成功地發送了一個消息。
**idel**:與simple類似,不同之處在於該進程將會被延遲到所有操作都完成之后在執行。這樣可以避免控制台上的狀態信息與shell腳本的輸出混在在一起。
ReaminAfterExit= 當該服務的所有進程都退出之后,是否依然將此無視為活動的,默認為no。
GuessMainPID= 在沒有設置PIDFile=值的時候,systemd是否要猜測主進程的PID。默認是yes。
PIDFile= 守護進程的PID文件,必須是絕對路徑,強烈建議在Type=forking的情況下明確設置此選項。這個路徑也不是隨便寫的,而是你的進程實際的PID文件路徑。這樣systemd才能正確的讀取該文件,但是它不會寫入,只是會在服務停止后刪除該文件,如果存在的話。
BusName= 設置與此服務通訊所使用的D-Bus名稱,如果Type=dbus,則必須設置此項。
ExecStart=
設置啟動服務是要執行的命令(命令+參數)。命令行必須是一個絕對路徑表示可執行文件的位置,后面可以跟多個該命令支持的參數。如果在命令前面加上下面的標志,將會有不同含義:
@:表示后面的參數一次傳遞給被執行的程序
-:表示即使該進程以失敗狀態退出,也會被視為成功退出
+:表示該進程擁有超級用戶特權
如果設置多個ExecStart=那么將依次運行,如果某個沒有“-”前綴的命令執行失敗,那么后續的ExecStart=將不會執行,同時該單元變為失敗(failed)狀態。
如果沒有設置Type=forking時,這里的命令所啟動的進程,將被視為該服務的主守護進程。
ExecStartPre=
ExecStartPost=
在執行ExecStart之前或之后運行的命令。規則與ExecStart=相同。
對於ExecStartPost= 命令僅在服務已經啟動成功之后才會運行,判斷的標准基於 Type= 選項。 具體說來,對於 Type=simple 或 Type=idle 就是主進程已經成功啟動; 對於 Type=oneshot 來說就是主進程已經成功退出; 對於 Type=forking 來說就是初始進程已經成功退出; 對於 Type=notify 來說就是已經發送了 "READY=1" ; 對於 Type=dbus 來說就是已經取得了 BusName= 中設置的總線名稱。注意一下2點:
不可將 ExecStartPre= 用於需要長時間執行的進程。 因為所有由 ExecStartPre= 派生的子進程 都會在啟動 ExecStart= 服務進程之前被殺死。
如果在服務啟動完成之前,任意一個 ExecStartPre=, ExecStart=, ExecStartPost= 中無 "-" 前綴的命令執行失敗或超時, 那么,ExecStopPost= 將會被繼續執行,而 ExecStop= 則會被跳過。
ExecReload=
這是一個可選的指令, 用於設置當該服務被要求重新載入配置時所執行的命令行。 語法規則與 ExecStart= 完全相同。
另外,還有一個特殊的環境變量 $MAINPID 可用於表示主進程的PID, 例如可以這樣使用:/bin/kill -HUP $MAINPID
注意,像上例那樣,通過向守護進程發送復位信號, 強制其重新加載配置文件,並不是一個好習慣。 因為這是一個異步操作, 所以不適用於需要按照特定順序重新加載配置文件的服務。 我們強烈建議將 ExecReload= 設為一個 能夠確保重新加載配置文件的操作同步完成的命令行
ExecStop=
這是一個可選的指令, 用於設置當該服務被要求停止時所執行的命令行。 語法規則與 ExecStart= 完全相同。 執行完此處設置的命令行之后, 該服務所有剩余的進程將會根據 KillMode= 的設置被殺死(參見 systemd.kill(5))。 如果未設置此選項,那么當此服務被停止時, 該服務的所有進程都將會根據 KillSignal= 的設置被立即全部殺死。 與 ExecReload= 一樣, 也有一個特殊的環境變量 $MAINPID 可用於表示主進程的PID
一般來說, 僅僅設置一個結束服務的命令而不等待其完成, 是不夠的。 因為當此處設置的命令執行完之后, 剩余的進程會被 SIGKILL 信號立即殺死, 這可能會導致數據丟失。 因此,這里設置的命令必須是同步操作, 而不能是異步操作。
注意,僅在服務確實啟動成功的前提下,才會執行 ExecStop= 中設置的命令。 如果服務從未啟動或啟動失敗(例如,任意一個 ExecStart=, ExecStartPre=, ExecStartPost= 中無 "-" 前綴的命令執行失敗或超時), 那么 ExecStop= 將會被跳過。 如果想要無條件的在服務停止后執行特定的動作,那么應該使用 ExecStopPost= 選項。
應該將此選項用於那些必須在服務干凈的退出之前執行的命令。 當此選項設置的命令被執行的時候,應該假定服務正處於完全正常的運行狀態,可以正常的與其通信。 如果想要無條件的在服務停止后"清理屍體",那么應該使用 ExecStopPost= 選項。
KillMode=的值有如下幾種:
control-group:表示殺死該單元的cgroup內的所有進程
process:表示僅殺死主進程
mixed:表示先向主進程發送SIGTERM信號,然后在向該單元的cgroup內的其他進程發送SIGKILL信號。
none:表示僅執行ExecStop=動作,而不殺死任何進程,這會導致進程單元停止了,但是該單元的cgroup還依然存在,直到其余進程全部死亡。
默認是control-group。
ExecStopPost=
這是一個可選的指令, 用於設置在該服務停止之后所執行的命令行。 語法規則與 ExecStart= 完全相同。 注意,與 ExecStop= 不同,無論服務是否啟動成功, 此選項中設置的命令都會在服務停止后被無條件的執行。
應該將此選項用於設置那些無論服務是否啟動成功都必須在服務停止后無條件執行的清理操作。 此選項設置的命令必須能夠正確處理由於服務啟動失敗而造成的各種殘缺不全以及數據不一致的場景。 由於此選項設置的命令在執行時,整個服務的所有進程都已經全部結束,所以無法與服務進行任何通信。
RestartSec= 設置在重啟服務(Restart=)前暫停多長時間。 默認值是100毫秒(100ms)。 如果未指定時間單位,那么將視為以秒為單位。 例如設為"20"等價於設為"20s"
TimeoutStartSec= 設置該服務允許的最大啟動時長。 如果守護進程未能在限定的時長內發出"啟動完畢"的信號,那么該服務將被視為啟動失敗,並會被關閉。 如果未指定時間單位,那么將視為以秒為單位。
TimeoutStopSec= 設置該服務允許的最大停止時長。 如果該服務未能在限定的時長內成功停止, 那么將會被強制使用 SIGTERM 信號關閉, 如果依然未能在相同的時長內成功停止, 那么將會被強制使用 SIGKILL 信號關閉。如果未指定時間單位,那么將視為以秒為單位。 例如設為"20"等價於設為"20s"。 設為 "infinity" 則表示永不超時。
RuntimeMaxSec= 允許服務持續運行的最大時長。 如果服務持續運行超過了此處限制的時長,那么該服務將會被強制終止,同時將該服務變為失敗(failed)狀態。 注意,此選項對 Type=oneshot 類型的服務無效,因為它們會在啟動完成后立即終止。 默認值為 "infinity" (不限時長)。
WatchdogSec= 設置該服務的看門狗(watchdog)的超時時長。 看門狗將在服務成功啟動之后被啟動。 該服務在運行過程中必須周期性的以 "WATCHDOG=1" ("keep-alive ping")調用 sd_notify(3) 函數。 如果在兩次調用之間的時間間隔大於這里設定的值, 那么該服務將被視為失敗(failed)狀態, 並會被強制使用 SIGABRT 信號關閉。 通過將 Restart= 設為 on-failure, on-watchdog, on-abnormal, always 之一, 可以實現在失敗狀態下的自動重啟該服務。 這里設置的值將會通過 WATCHDOG_USEC= 環境變量傳遞給守護進程, 這樣就允許那些支持看門狗的服務自動啟用"keep-alive ping"。 如果設置了此選項, 那么必須將 NotifyAccess= 設為 main(此種情況下的隱含默認值) 或 all 。 如果未指定時間單位,那么將視為以秒為單位。 例如設為"20"等價於設為"20s"。 默認值"0"表示禁用看門狗功能。 詳見 sd_watchdog_enabled(3) 與 sd_event_set_watchdog(3) 手冊。
Restart=
當服務進程正常退出、異常退出、被殺死、超時的時候,是否重啟系統該服務。進程通過正常操作被停止則不會被執行重啟。可選值為:
no:默認值,表示任何時候都不會被重啟
always:表示會被無條件重啟
no-success:表示僅在服務進程正常退出時重啟
on-failure:表示僅在服務進程異常退出時重啟
所謂正常退出是指,退出碼為“0”,或者到IGHUP, SIGINT, SIGTERM, SIGPIPE 信號之一,並且退出碼符合 SuccessExitStatus= 的設置。
所謂異常退出時指,退出碼不為“0”,或者被強殺或者因為超時被殺死。
SuccessExitStatus=
額外定義附加的進程"正常退出"狀態。 可以設為一系列以空格分隔的數字退出碼或者信號名稱
說明:如果在ExecStart=中設置多個命令,那么每個命令必須用“;”隔開,且只有Type=oneshot時才可用。
另外在[Service]段中還可以使用:
配置項 說明
WorkingDirectory= 設置進程的工作目錄。 既可以設為特殊值 "~" 表示 User= 用戶的家目錄,
也可以設為一個以 RootDirectory= 為基准的絕對路徑。 例如當 RootDirectory=/sysroot 並且 WorkingDirectory=/work/dir 時, 實際的工作目錄將是 /sysroot/work/dir 。 當 systemd 作為系統實例運行時,此選項的默認值是 / ; 當 systemd 作為用戶實例運行時,此選項的默認值是對應用戶的家目錄。 如果給目錄加上 "-" 前綴, 那么表示即使此目錄不存在,也不算致命錯誤。 如果未設置 RootDirectory= 選項, 那么為 WorkingDirectory= 設置的絕對路徑 將以主機(或容器)的根目錄(也就是運行 systemd 的系統根目錄)為基准。 注意,設置此選項將會導致自動添加額外的依賴關系(見上文)。
RootDirectory= 設置以 chroot(2) 方式執行進程時的根目錄。 必須設為一個以主機(或容器)的根目錄(也就是運行 systemd 的系統根目錄)為基准的絕對路徑。 如果設置了此選項, 必須確保進程及其輔助文件在 chroot() 監獄中確實可用。 注意,設置此選項將會導致自動添加額外的依賴關系(見上文)。
User=
Group=
設置進程在執行時使用的用戶與組。 既可以設為數字形式的ID也可以設為字符串形式的名稱。 如果沒有明確設置 Group= 選項,則使用 User= 所屬的默認組。 此選項不影響帶有 "+" 前綴的命令。
Nice= 設置進程的默認謙讓值。 可以設為 -20(最高優先級) 到 19(最低優先級) 之間的整數值。
Environment=
設置進程的環境變量, 值是一個空格分隔的 VAR=VALUE 列表。 可以多次使用此選項以增加新的變量或者修改已有的變量 (同一個變量以最后一次的設置為准)。 若設為空, 則表示清空先前所有已設置的變量。 注意: (1)不會在字符串內部進行變量展開(也就是"$"沒有特殊含義); (2)如果值中包含空格, 那么必須在字符串兩邊使用雙引號(")界定
Environment="VAR1=word1 word2"。
EnvironmentFile=
與 Environment= 類似, 不同之處在於此選項是從文本文件中讀取環境變量的設置。 文件中的空行以及以分號(;)或井號(#)開頭的行會被忽略, 其他行的格式必須符合 VAR=VALUE 的shell變量賦值語法。 行尾的反斜杠()將被視為續行符, 這與shell語法類似。 若想在變量值中包含空格, 則必須在值的兩端加上雙引號(")界定。
文件必須用絕對路徑表示(可以包含通配符)。 但可在路徑前加上"-"前綴表示忽略不存在的文件。 可以多次使用此選項, 以從多個不同的文件中讀取設置。 若設為空, 則表示清空所有先前已經從文件中讀取的環境變量。
這里列出的文件將在進程啟動前的瞬間被讀取, 因此可以由前一個單元生成配置文件, 再由后一個單元去讀取它。
從文件中讀取的環境變量會覆蓋 Environment= 中設置的同名變量。 文件的讀取順序就是它們出現在單元文件中的順序, 並且對於同一個變量,以最后讀取的文件中的設置為准。
我們再回來看之前的sshd的服務定義:
現在你就知道如何定義一個服務了。尤其是編譯安裝軟件的時候,較新版本的軟件可能提供了.service的文件,如果沒有你就需要自己寫。
常用命令
#啟動一個服務
systemctl start postfix.service
#關閉一個服務
systemctl stop postfix.service
#重啟一個服務
systemctl restart postfix.service
#顯示一個服務的狀態
systemctl status postfix.service
#在開機時啟用一個服務
systemctl enable postfix.service
#在開機時禁用一個服務
systemctl disable postfix.service
#查看服務是否開機啟動
systemctl is-enabled postfix.service
#查看已啟動的服務列表
systemctl list-unit-files|grep enabled
#查看啟動失敗的服務列表
systemctl --failed
#重新加載service文件
systemctl daemon-reload
# 通過service啟動|停止|重啟|狀態服務
service xxx start | restart | stop | status