systemd即為system daemon,是linux下的一種init軟件,由Lennart Poettering帶頭開(kāi)發(fā),并在LGPL 2.1及其后續(xù)版本許可證下開(kāi)源發(fā)布,開(kāi)發(fā)目標(biāo)是提供更優(yōu)秀的框架以表示系統(tǒng)服務(wù)間的依賴(lài)關(guān)系,并依此實(shí)現(xiàn)系統(tǒng)初始化時(shí)服務(wù)的并行啟動(dòng),同時(shí)達(dá)到降低Shell的系統(tǒng)開(kāi)銷(xiāo)的效果,最終代替現(xiàn)在常用的System V與BSD風(fēng)格init程序。
?與多數(shù)發(fā)行版使用的System V風(fēng)格init相比,systemd采用了以下新技術(shù):
?(1) 采用Socket激活式與總線(xiàn)激活式服務(wù),以提高相互依賴(lài)的各服務(wù)的并行運(yùn)行性能;
?(2) 用Cgroups代替PID來(lái)追蹤進(jìn)程,以此即使是兩次fork之后生成的守護(hù)進(jìn)程也不會(huì)脫離systemd的控制
例 1. 簡(jiǎn)單服務(wù)
下面的單元文件創(chuàng)建了一個(gè)運(yùn)行 /usr/sbin/foo-daemon 守護(hù)進(jìn)程的服務(wù)。 未設(shè)置 Type= 等價(jià)于 Type=simple 默認(rèn)設(shè)置。 systemd 執(zhí)行守護(hù)進(jìn)程之后, 即認(rèn)為該單元已經(jīng)啟動(dòng)成功。
#################################
[Unit]
Description=簡(jiǎn)單的Foo服務(wù)
[Service]
ExecStart=/usr/sbin/foo-daemon
[Install]
WantedBy=multi-user.target
##################################
注意,本例中的 /usr/sbin/foo-daemon 必須在啟動(dòng)后持續(xù)運(yùn)行到服務(wù)被停止。 如果該進(jìn)程只是為了派生守護(hù)進(jìn)程,那么應(yīng)該使用 Type=forking
因?yàn)闆](méi)有設(shè)置 ExecStop= 選項(xiàng), 所以在停止服務(wù)時(shí),systemd 將會(huì)直接向該服務(wù)啟動(dòng)的所有進(jìn)程發(fā)送 SIGTERM 信號(hào)。 若超過(guò)指定時(shí)間依然存在未被殺死的進(jìn)程,那么將會(huì)繼續(xù)發(fā)送 SIGKILL 信號(hào)。 詳見(jiàn) systemd.kill(5) 手冊(cè)。
默認(rèn)的 Type=simple 并不包含任何通知機(jī)制(例如通知"服務(wù)啟動(dòng)成功")。 要想使用通知機(jī)制,應(yīng)該將 Type= 設(shè)為其他非默認(rèn)值: Type=notify 可用于能夠理解 systemd 通知協(xié)議的服務(wù); Type=forking 可用于能將自身切換到后臺(tái)的服務(wù); Type=dbus 可用于能夠在完成初始化之后獲得一個(gè) D-Bus 名稱(chēng)的單元。
例 2. 一次性服務(wù)
Type=oneshot 用于那些只需要執(zhí)行一次性動(dòng)作而不需要持久運(yùn)行的單元, 例如文件系統(tǒng)檢查或者清理臨時(shí)文件。 此類(lèi)單元, 將會(huì)在啟動(dòng)后一直等待指定的動(dòng)作完成, 然后再回到停止?fàn)顟B(tài)。 下面是一個(gè)執(zhí)行清理動(dòng)作的單元:
#################################
[Unit]
Description=清理老舊的 Foo 數(shù)據(jù)
[Service]
Type=oneshot
ExecStart=/usr/sbin/foo-cleanup
[Install]
WantedBy=multi-user.target
##################################
注意,在 /usr/sbin/foo-cleanup 執(zhí)行結(jié)束前, 該服務(wù)一直處于"啟動(dòng)中"(activating)狀態(tài),而一旦執(zhí)行結(jié)束,該服務(wù)又立即變?yōu)?停止"(inactive)狀態(tài)。 也就是說(shuō),對(duì)于 Type=oneshot 類(lèi)型的服務(wù),不存在"活動(dòng)"(active)狀態(tài)。 這意味著,如果再一次啟動(dòng)該服務(wù),將會(huì)再一次執(zhí)行該服務(wù)定義的動(dòng)作。 注意,在先后順序上晚于該服務(wù)的單元, 將會(huì)一直等到該服務(wù)變成"停止"(inactive)狀態(tài)后, 才會(huì)開(kāi)始啟動(dòng)。
Type=oneshot 是唯一可以設(shè)置多個(gè) ExecStart= 指令的服務(wù)類(lèi)型。 多個(gè) ExecStart= 指令將按照它們出現(xiàn)的順序依次執(zhí)行, 一旦遇到錯(cuò)誤,就會(huì)立即停止,不再繼續(xù)執(zhí)行, 同時(shí)該服務(wù)也將進(jìn)入"失敗"(failed)狀態(tài)。
例 3. 可停止的一次性服務(wù)
有時(shí)候,單元需要執(zhí)行一個(gè)程序以完成某個(gè)設(shè)置(啟動(dòng)), 然后又需要再執(zhí)行另一個(gè)程序以撤消先前的設(shè)置(停止), 而在設(shè)置持續(xù)有效的時(shí)段中,該單元應(yīng)該視為處于"活動(dòng)"(active)狀態(tài), 但實(shí)際上并無(wú)任何程序在持續(xù)運(yùn)行。 網(wǎng)絡(luò)配置服務(wù)就是一個(gè)典型的例子。 此外,只能啟動(dòng)一次(不可多次啟動(dòng))的一次性服務(wù),也是一個(gè)例子。
可以通過(guò)設(shè)置 RemainAfterExit=yes 來(lái)滿(mǎn)足這種需求。 在這種情況下,systemd 將會(huì)在啟動(dòng)成功后將該單元視為處于"活動(dòng)"(active)狀態(tài)(而不是"停止"(inactive)狀態(tài))。 RemainAfterExit=yes 雖然可以用于所有 Type= 類(lèi)型, 但是在實(shí)踐中主要用于 Type=oneshot 和 Type=simple 類(lèi)型。 對(duì)于 Type=oneshot 類(lèi)型, systemd 一直等到服務(wù)啟動(dòng)成功之后,才會(huì)將該服務(wù)置于"活動(dòng)"(active)狀態(tài)。 所以,依賴(lài)于該服務(wù)的其他單元必須等待該服務(wù)啟動(dòng)成功之后,才能啟動(dòng)。 但是對(duì)于 Type=simple 類(lèi)型, 依賴(lài)于該服務(wù)的其他單元無(wú)需等待,將會(huì)和該服務(wù)同時(shí)并行啟動(dòng)。 下面的類(lèi)似展示了一個(gè)簡(jiǎn)單的靜態(tài)防火墻服務(wù):
####################################
[Unit]
Description=簡(jiǎn)單的靜態(tài)防火墻
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/simple-firewall-start
ExecStop=/usr/local/sbin/simple-firewall-stop
[Install]
WantedBy=multi-user.target
####################################
因?yàn)榉?wù)啟動(dòng)成功后一直處于"活動(dòng)"(active)狀態(tài), 所以再次執(zhí)行 systemctl start 命令不會(huì)有任何效果。
例 4. 傳統(tǒng)的服務(wù)
多數(shù)傳統(tǒng)的守護(hù)進(jìn)程(服務(wù))在啟動(dòng)時(shí)會(huì)轉(zhuǎn)入后臺(tái)運(yùn)行。 systemd 通過(guò) Type=forking 來(lái)支持這種工作方式。 對(duì)于這種類(lèi)型的服務(wù),如果最初啟動(dòng)的進(jìn)程尚未退出, 那么該單元將依然處于"啟動(dòng)中"(activating)狀態(tài)。 當(dāng)最初的進(jìn)程成功退出, 并且至少有一個(gè)進(jìn)程仍然在運(yùn)行(并且 RemainAfterExit=no), 該服務(wù)才會(huì)被視為處于"活動(dòng)"(active)狀態(tài)。
對(duì)于單進(jìn)程的傳統(tǒng)服務(wù),當(dāng)最初的進(jìn)程成功退出后, 將會(huì)只剩單獨(dú)一個(gè)進(jìn)程仍然在持續(xù)運(yùn)行, systemd 將會(huì)把這個(gè)唯一剩余的進(jìn)程視為該服務(wù)的主進(jìn)程。 僅在這種情況下,才將可以在 ExecReload=, ExecStop= … 之類(lèi)的選項(xiàng)中使用 $MAINPID 變量。
對(duì)于多進(jìn)程的傳統(tǒng)服務(wù),當(dāng)最初的進(jìn)程成功退出后,將會(huì)剩余多個(gè)進(jìn)程在持續(xù)運(yùn)行, 因此,systemd 無(wú)法確定哪一個(gè)進(jìn)程才是該服務(wù)的主進(jìn)程。 在這種情況下,不可以使用 $MAINPID 變量。 然而,如果主進(jìn)程會(huì)創(chuàng)建傳統(tǒng)的PID文件, 那么應(yīng)該將 PIDFile= 設(shè)為此PID文件的絕對(duì)路徑, 以幫助 systemd 從該P(yáng)ID文件中讀取主進(jìn)程的PID,從而幫助確定該服務(wù)的主進(jìn)程。 注意,守護(hù)進(jìn)程必須在完成初始化之前寫(xiě)入PID文件, 否則可能會(huì)導(dǎo)致 systemd 讀取失敗(讀取時(shí)文件不存在)。
下面是一個(gè)單進(jìn)程傳統(tǒng)服務(wù)的示例:
#################################
[Unit]
Description=一個(gè)單進(jìn)程傳統(tǒng)服務(wù)
[Service]
Type=forking
ExecStart=/usr/sbin/my-simple-daemon -d
[Install]
WantedBy=multi-user.target
##################################?
參見(jiàn) systemd.kill(5) 以了解如何結(jié)束服務(wù)進(jìn)程。
下面是一個(gè)多進(jìn)程傳統(tǒng)服務(wù)的示例:

##########################################################
[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 服務(wù)
對(duì)于需要在 D-Bus 系統(tǒng)總線(xiàn)上注冊(cè)一個(gè)名字的服務(wù), 應(yīng)該使用 Type=dbus 并且設(shè)置相應(yīng)的 BusName= 值。?
該服務(wù)不可以派生任何子進(jìn)程。 一旦從 D-Bus 系統(tǒng)總線(xiàn)成功獲取所需的名字,該服務(wù)即被視為初始化成功。?
下面是一個(gè)典型的 D-Bus 服務(wù):
#################################
[Unit]
Description=一個(gè)簡(jiǎn)單的 DBus 服務(wù)
[Service]
Type=dbus
BusName=org.example.simple-dbus-service
ExecStart=/usr/sbin/simple-dbus-service
[Install]
WantedBy=multi-user.target
###################################
對(duì)于基于 D-Bus 啟動(dòng)的服務(wù)來(lái)說(shuō), 不可以包含 "[Install]" 小節(jié), 而是應(yīng)該在對(duì)應(yīng)的 D-Bus service 文件中設(shè)置 SystemdService= 選項(xiàng), 例如(/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
###################################
參見(jiàn) systemd.kill(5) 手冊(cè)以了解如何結(jié)束服務(wù)進(jìn)程。
例 6. 能夠通知初始化已完成的服務(wù)
Type=simple 類(lèi)型的服務(wù)非常容易編寫(xiě), 但是無(wú)法將"啟動(dòng)成功"的消息及時(shí)通知給 systemd 是一個(gè)重大缺陷。 Type=notify 可以彌補(bǔ)該缺陷, 它支持將"啟動(dòng)成功"的消息及時(shí)通知給 systemd 。 下面是一個(gè)典型的例子:
####################################
[Unit]
Description=Simple notifying service
[Service]
Type=notify
ExecStart=/usr/sbin/simple-notifying-service
[Install]
WantedBy=multi-user.target
####################################
注意,該守護(hù)進(jìn)程必須支持 systemd 通知協(xié)議, 否則 systemd 將會(huì)認(rèn)為該服務(wù)一直處于"啟動(dòng)中"(activating)狀態(tài),并在超時(shí)后將其殺死。 關(guān)于如何支持該通知協(xié)議,參見(jiàn) sd_notify(3) 手冊(cè)。
參見(jiàn) systemd.kill(5) 手冊(cè)以了解如何結(jié)束服務(wù)進(jìn)程。
參考
systemd詳解
https://blog.linuxeye.cn/400.html
Systemd 入門(mén)教程:命令篇
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
Systemd 入門(mén)教程:實(shí)戰(zhàn)篇
http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html
CentOS 7之Systemd詳解之服務(wù)單元設(shè)置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系統(tǒng)詳細(xì)開(kāi)機(jī)啟動(dòng)流程和關(guān)機(jī)流程
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 創(chuàng)建服務(wù)
http://blog.csdn.net/zhangxtn/article/details/50462008
編寫(xiě)systemd service文件
https://zh.opensuse.org/openSUSE:How_to_write_a_systemd_service
認(rèn)識(shí)系統(tǒng)服務(wù)
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 中文手冊(cè)
http://www.jinbuguo.com/systemd/systemd.service.html
systemd 使用簡(jiǎn)介
https://jin-yang.github.io/post/linux-systemd.html