systemd即為system daemon,是linux下的一種init軟件,由Lennart Poettering帶頭開發,并在LGPL 2.1及其后續版本許可證下開源發布,開發目標是提供更優秀的框架以表示系統服務間的依賴關系,并依此實現系統初始化時服務的并行啟動,同時達到降低Shell的系統開銷的效果,最終代替現在常用的System V與BSD風格init程序。
?與多數發行版使用的System V風格init相比,systemd采用了以下新技術:
?(1) 采用Socket激活式與總線激活式服務,以提高相互依賴的各服務的并行運行性能;
?(2) 用Cgroups代替PID來追蹤進程,以此即使是兩次fork之后生成的守護進程也不會脫離systemd的控制
例 1. 簡單服務
下面的單元文件創建了一個運行 /usr/sbin/foo-daemon 守護進程的服務。 未設置 Type= 等價于 Type=simple 默認設置。 systemd 執行守護進程之后, 即認為該單元已經啟動成功。
#################################
[Unit]
Description=簡單的Foo服務
[Service]
ExecStart=/usr/sbin/foo-daemon
[Install]
WantedBy=multi-user.target
##################################
注意,本例中的 /usr/sbin/foo-daemon 必須在啟動后持續運行到服務被停止。 如果該進程只是為了派生守護進程,那么應該使用 Type=forking
因為沒有設置 ExecStop= 選項, 所以在停止服務時,systemd 將會直接向該服務啟動的所有進程發送 SIGTERM 信號。 若超過指定時間依然存在未被殺死的進程,那么將會繼續發送 SIGKILL 信號。 詳見 systemd.kill(5) 手冊。
默認的 Type=simple 并不包含任何通知機制(例如通知"服務啟動成功")。 要想使用通知機制,應該將 Type= 設為其他非默認值: Type=notify 可用于能夠理解 systemd 通知協議的服務; Type=forking 可用于能將自身切換到后臺的服務; Type=dbus 可用于能夠在完成初始化之后獲得一個 D-Bus 名稱的單元。
例 2. 一次性服務
Type=oneshot 用于那些只需要執行一次性動作而不需要持久運行的單元, 例如文件系統檢查或者清理臨時文件。 此類單元, 將會在啟動后一直等待指定的動作完成, 然后再回到停止狀態。 下面是一個執行清理動作的單元:
#################################
[Unit]
Description=清理老舊的 Foo 數據
[Service]
Type=oneshot
ExecStart=/usr/sbin/foo-cleanup
[Install]
WantedBy=multi-user.target
##################################
注意,在 /usr/sbin/foo-cleanup 執行結束前, 該服務一直處于"啟動中"(activating)狀態,而一旦執行結束,該服務又立即變為"停止"(inactive)狀態。 也就是說,對于 Type=oneshot 類型的服務,不存在"活動"(active)狀態。 這意味著,如果再一次啟動該服務,將會再一次執行該服務定義的動作。 注意,在先后順序上晚于該服務的單元, 將會一直等到該服務變成"停止"(inactive)狀態后, 才會開始啟動。
Type=oneshot 是唯一可以設置多個 ExecStart= 指令的服務類型。 多個 ExecStart= 指令將按照它們出現的順序依次執行, 一旦遇到錯誤,就會立即停止,不再繼續執行, 同時該服務也將進入"失敗"(failed)狀態。
例 3. 可停止的一次性服務
有時候,單元需要執行一個程序以完成某個設置(啟動), 然后又需要再執行另一個程序以撤消先前的設置(停止), 而在設置持續有效的時段中,該單元應該視為處于"活動"(active)狀態, 但實際上并無任何程序在持續運行。 網絡配置服務就是一個典型的例子。 此外,只能啟動一次(不可多次啟動)的一次性服務,也是一個例子。
可以通過設置 RemainAfterExit=yes 來滿足這種需求。 在這種情況下,systemd 將會在啟動成功后將該單元視為處于"活動"(active)狀態(而不是"停止"(inactive)狀態)。 RemainAfterExit=yes 雖然可以用于所有 Type= 類型, 但是在實踐中主要用于 Type=oneshot 和 Type=simple 類型。 對于 Type=oneshot 類型, systemd 一直等到服務啟動成功之后,才會將該服務置于"活動"(active)狀態。 所以,依賴于該服務的其他單元必須等待該服務啟動成功之后,才能啟動。 但是對于 Type=simple 類型, 依賴于該服務的其他單元無需等待,將會和該服務同時并行啟動。 下面的類似展示了一個簡單的靜態防火墻服務:
####################################
[Unit]
Description=簡單的靜態防火墻
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/simple-firewall-start
ExecStop=/usr/local/sbin/simple-firewall-stop
[Install]
WantedBy=multi-user.target
####################################
因為服務啟動成功后一直處于"活動"(active)狀態, 所以再次執行 systemctl start 命令不會有任何效果。
例 4. 傳統的服務
多數傳統的守護進程(服務)在啟動時會轉入后臺運行。 systemd 通過 Type=forking 來支持這種工作方式。 對于這種類型的服務,如果最初啟動的進程尚未退出, 那么該單元將依然處于"啟動中"(activating)狀態。 當最初的進程成功退出, 并且至少有一個進程仍然在運行(并且 RemainAfterExit=no), 該服務才會被視為處于"活動"(active)狀態。
對于單進程的傳統服務,當最初的進程成功退出后, 將會只剩單獨一個進程仍然在持續運行, systemd 將會把這個唯一剩余的進程視為該服務的主進程。 僅在這種情況下,才將可以在 ExecReload=, ExecStop= … 之類的選項中使用 $MAINPID 變量。
對于多進程的傳統服務,當最初的進程成功退出后,將會剩余多個進程在持續運行, 因此,systemd 無法確定哪一個進程才是該服務的主進程。 在這種情況下,不可以使用 $MAINPID 變量。 然而,如果主進程會創建傳統的PID文件, 那么應該將 PIDFile= 設為此PID文件的絕對路徑, 以幫助 systemd 從該PID文件中讀取主進程的PID,從而幫助確定該服務的主進程。 注意,守護進程必須在完成初始化之前寫入PID文件, 否則可能會導致 systemd 讀取失敗(讀取時文件不存在)。
下面是一個單進程傳統服務的示例:
#################################
[Unit]
Description=一個單進程傳統服務
[Service]
Type=forking
ExecStart=/usr/sbin/my-simple-daemon -d
[Install]
WantedBy=multi-user.target
##################################?
參見 systemd.kill(5) 以了解如何結束服務進程。
下面是一個多進程傳統服務的示例:
##########################################################
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
###########################################################?
例 5. DBus 服務
對于需要在 D-Bus 系統總線上注冊一個名字的服務, 應該使用 Type=dbus 并且設置相應的 BusName= 值。?
該服務不可以派生任何子進程。 一旦從 D-Bus 系統總線成功獲取所需的名字,該服務即被視為初始化成功。?
下面是一個典型的 D-Bus 服務:
#################################
[Unit]
Description=一個簡單的 DBus 服務
[Service]
Type=dbus
BusName=org.example.simple-dbus-service
ExecStart=/usr/sbin/simple-dbus-service
[Install]
WantedBy=multi-user.target
###################################
對于基于 D-Bus 啟動的服務來說, 不可以包含 "[Install]" 小節, 而是應該在對應的 D-Bus service 文件中設置 SystemdService= 選項, 例如(/usr/share/dbus-1/system-services/org.example.simple-dbus-service.service):
##################################
[D-BUS Service]
Name=org.example.simple-dbus-service
Exec=/usr/sbin/simple-dbus-service
User=root
SystemdService=simple-dbus-service.service
###################################
參見 systemd.kill(5) 手冊以了解如何結束服務進程。
例 6. 能夠通知初始化已完成的服務
Type=simple 類型的服務非常容易編寫, 但是無法將"啟動成功"的消息及時通知給 systemd 是一個重大缺陷。 Type=notify 可以彌補該缺陷, 它支持將"啟動成功"的消息及時通知給 systemd 。 下面是一個典型的例子:
####################################
[Unit]
Description=Simple notifying service
[Service]
Type=notify
ExecStart=/usr/sbin/simple-notifying-service
[Install]
WantedBy=multi-user.target
####################################
注意,該守護進程必須支持 systemd 通知協議, 否則 systemd 將會認為該服務一直處于"啟動中"(activating)狀態,并在超時后將其殺死。 關于如何支持該通知協議,參見 sd_notify(3) 手冊。
參見 systemd.kill(5) 手冊以了解如何結束服務進程。
參考
systemd詳解
https://blog.linuxeye.cn/400.html
Systemd 入門教程:命令篇
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
Systemd 入門教程:實戰篇
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html
CentOS 7之Systemd詳解之服務單元設置system.service
http://blog.csdn.net/yuesichiu/article/details/51485147
https://www.freedesktop.org/software/systemd/man/systemd.service.html
CentOS 7之Systemd詳解之單元配置systemd.unit
http://blog.csdn.net/yuesichiu/article/details/51331136
CentOS 7系統詳細開機啟動流程和關機流程
http://blog.csdn.net/yuesichiu/article/details/51350654
NGINX systemd service file
https://www.nginx.com/resources/wiki/start/topics/examples/systemd
http://images.linoxide.com/systemd-vs-sysVinit-cheatsheet.pdf
Centos7 創建服務
http://blog.csdn.net/zhangxtn/article/details/50462008
編寫systemd service文件
https://zh.opensuse.org/openSUSE:How_to_write_a_systemd_service
認識系統服務
http://linux.vbird.org/linux_basic/0560daemons.php
systemd System and Service Manager
https://www.freedesktop.org/wiki/Software/systemd/
https://wiki.archlinux.org/index.php/systemd_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=?
systemd.service 中文手冊
http://www.jinbuguo.com/systemd/systemd.service.html
systemd 使用簡介
https://jin-yang.github.io/post/linux-systemd.html