systemd是RH7系列操作系統開始啟用新的系統和服務管理器。它被設計為與sysv init腳本向后兼容,並提供了一些功能,例如在引導時並行啟動系統服務,按需激活守護程序或基於依賴關系的服務控制邏輯。
systemd中引入了system units的概念,在units其中封裝有關系統服務(service),偵聽套接字(socket),以及與init系統啟動相關信息
systemd unit 類型
unit類型 | 文件后綴名 | 描述 Service unit | .service | 服務類 Target unit | .target | 一個unit服務組,用於模擬實現運行級別 Automount unit | .automount | 文件系統自動掛載點 Device unit | .device | 內核識別的設備文件 Mount unit | .mount | 文件系統掛載點 Path unit | .path | 文件或目錄 Scope unit | .scope | 外部創建的進程 Slice unit | .slice | A group of hierarchically organized units that manage system processes. Snapshot unit | .snapshot | 系統快照 Socket unit | .socket | 套接字 Swap unit | .swap | 標識swap設備 Timer unit | .timer | systemd的計時器
unit文件保存位置
/usr/lib/systemd/system/ | RPM包安裝時分發的unit文件 /run/systemd/system/ | systemd運行時創建的文件 /etc/systemd/system/ | systemctl enable創建的unit文件
主要特性
-
基於socket的激活機制: 在程序不可用時,socket會保持可訪問狀態,並且所有消息都排隊等待.實現了socket與服務程序分離,可以為服務啟動一個socket而不需要立即啟動程序,通過socket連接激活程序.並以此實現了服務的並行啟動.
-
基於bus的激活機制: 使用d-bus進行進程間通信的系統服務可以在客戶端應用程序第一次嘗試與它們進行通信時按需啟動
-
基於device的激活機制: 使用d-bus進行進程間通信的系統服務可以在客戶端應用程序第一次嘗試與它們進行通信時按需啟動.利用USB,CD等設備掛載時激活服務
-
基於path的激活機制: 支持基於路徑的激活的系統服務可以在特定文件或目錄更改其狀態時按需啟動.
-
基於mount的激活機制: systemd監視和管理掛載點或自動掛載點激活服務
-
並行啟動系統服務: 根據socket激活機制,只要服務所需要的偵聽套接字就位,systemd就可以並行啟動系統服務.減少系統啟動時間
-
系統快照: 保存unit的當前狀態於持久設備中,必要時載入.例如重啟前保存unit狀態,重啟后不重新初始化服務直接使用保存的狀態.
-
激活邏輯: 在激活或關閉單元之前,systemd會計算它的依賴關系,創建一個臨時事務,並驗證這個事務是否一致.
如果事務不一致,systemd將自動嘗試糾正錯誤,並在報告錯誤之前從中刪除不重要的作業. -
兼容sysv init: 支持sysv init風格的啟動腳本
兼容性
systemd系統和服務管理器的設計主要是兼容sysv init和upstart.主要的兼容性變化包括:
-
systemd對運行級別的支持有限.對早期的0-6的運行級別概念,systemd是模擬實現的,並不能一一對應的實現,但並不是所有的systemd目標都可以直接映射到運行級別,因此,runlevel這個命令可能會返回n來指示未知的運行級別.同時避免使用init3,5來切換運行級別.
-
systemctl子命令是預定義好的,不支持自定義命令.對於centos7以前編寫sysv init啟動腳本除了定義start,stop,status等命令以外,我們還可以在腳本中自定義其它的子命令.在systemd中不能實現
-
不能控制使用systemctl管理工具以外啟動的服務,因為使用systemctl啟動服務.systemctl會存儲服務的元信息來查詢和管理服務.所以通過命令行啟動的守護進程,systemd是無法確定服務狀態.
-
systemd會檢查服務運行狀態,所以在關機時只會停止正在運行的服務進程
-
systemd不會讀取任何標准輸入數據流
-
systemd不會從調用用戶及其會話繼承任何上下文(如主目錄和環境變量),所以編寫服務時都使用絕對路徑
-
5分鍾超時時間,任何服務如果沒有被正常執行都會有5分鍾超時時間限制.
管理系統服務
在以前版本使用sysv init或upstart管理位於/etc/rc.d/init.d/目錄中的腳本.在centos7中被service unit取代.是用systemctl命令管理
1, 服務基本命令對比
service和systemctl
service | systemctl |
service name start | systemctl start name.service | 啟動服務 service name stop | systemctl stop name.service | 停止服務 service name restart | systemctl restart name.service | 重啟服務(沒啟動的服務會啟動) service name condrestart | systemctl try-restart name.service | 只重啟正在運行的服務 service name reload | systemctl reload name.service | 重載配置文件 service name status | systemctl status name.service | 檢查服務狀態 service name status | systemctl is-active name.service | 檢查服務是否啟動 service --status-all | systemctl list-units --type service --all | 顯示所有的服務狀態
chkconfig和systemctl
chkconfig | systemctl |
chkconfig name on | systemctl enable name.service | 啟用開機自啟服務 chkconfig name off | systemctl disable name.service | 停用自啟服務 chkconfig --list name | systemctl status name.service | 檢查服務狀態 chkconfig --list name | systemctl is-enabled name.service | 查看服務是否自啟 chkconfig --list | systemctl list-unit-files --type service | 查看所有服務 chkconfig --list | systemctl list-dependencies --after | 列出在指定服務之前啟動的服務.(依賴) chkconfig --list | systemctl list-dependencies --before | 列出在指定服務之后啟動的服務.(被依賴)
2, 服務狀態信息
Loaded | 關於服務是否已經加載的信息,文件的絕對路徑以及是否被啟用的注釋。
Active | 服務是否正在運行,然后是啟動時間信息
Main PID | 服務主進程pid
Docs | 服務的幫助文檔(man)
Status | 系統服務的額外信息 Process | 進程額外信息 CGroup | Control Groups額外信息
3, 常用命令(start,stop,這些常用命令就不說明了)
列出所有當前激活服務
systemctl list-units --type service
列出所有服務,不管是否激活(LOAD為notfound應該是還沒有安裝)
systemctl list-units --type service --all
列出可開機自啟的服務
systemctl list-unit-files --type service
重新加載服務: 一個服務設置為開機啟動使用enable會將/usr/lib/systemd/system/name.service軟鏈接到/etc/systemd/system/.但是enable命令不會重寫已經存在的鏈接,所以當我們修改了服務文件就需要重新加載
systemctl reenable name.service
禁用服務 mask會將 /etc/systemd/system/name.service軟鏈接到/dev/null.從而禁止服務啟用.反操作unmask
systemctl mask name.service
顯示服務屬性信息
systemctl show auditd
服務的依賴關系
systemctl list-dependencies chronyd.service
結束服務
systemctl kill name.service
Target
在Centos7之前版本中,擁有0-6編號的一組運行級別代表特定的操作模式.在Centos7中由systemd的target取代,通過一系列依賴關系將其他systemd units組合在一起,來模擬一個運行級別的概念.在運行級別的基礎上target有更豐富更靈活的運行模式.
1,sysv和systemd 區別
Runlevel| Target Units | 0 | runlevel0.target, poweroff.target | 關機 1 | runlevel1.target, rescue.target | 單用戶,救援模式 2 | runlevel2.target, multi-user.target | 多用戶,非完全啟動的命令行(比如網絡) 3 | runlevel3.target, multi-user.target | 建立了一個非圖形化多用戶系統 4 | runlevel4.target, multi-user.target | 預留,未啟用 5 | runlevel5.target, graphical.target | 圖形界面 6 | runlevel6.target, reboot.target | 重啟
sysv | systemd |
runlevel | systemctl list-units --type target | 查看運行級別. init N | systemctl isolate name.target | 改變運行級別
2, 常用命令
獲取默認target
systemctl get-default
查看激活的target
systemctl list-units --type target
查看所有target
systemctl list-units --type target --all
修改默認target
systemctl set-default name.target
切換級別
systemctl isolate graphical.target
救援模式
systemctl rescue #會加載驅動
systemctl emergency #emergency模式不會加載驅動和系統服務
關機,重啟相關
關機
systemctl halt systemctl poweroff
重啟
systemctl reboot
掛起
將系統狀態保存在內存中,並關閉大部分設備.(不推薦,容易斷電導致內存中數據丟失)
systemctl suspend
休眠
將系統狀態保存在硬盤中並關閉.下次啟動直接充保存的文件中讀取系統信息
systemctl hibenate
休眠並掛起
systemctl hybrid-sleep
遠程管理
除了在本地控制systemd系統和服務管理器之外,systemctl實用程序還允許您通過ssh協議與在遠程服務器上運行的systemd進行交互.需要使用openssh協議,並且遠程服務器上openssh server開啟
systemctl -H root@192.168.10.200 list-units --type service root@192.168.10.200's password: UNIT LOAD ACTIVE SUB DESCRIPTION auditd.service loaded active running Security Auditing Service chronyd.service loaded active running NTP client/server crond.service loaded active running Command Scheduler ...
Systemd unit 配置文件指南
通常我們需要做一些自定義服務或者是許多編譯軟件並沒有提供systemd的服務文件,就需要自己在/etc/systemd/system/目錄中創建,編寫unit文件.文件命名格式
unit_name.type_extension
unit_name:為服務名稱
type_extension: 為unit類型包括,service,target,socket,device等等
同時unit文件允許為服務補充一個目錄用於存放配置文件的符號鏈接,比如redis.service就可以在/etc/systemd/system下創建redis.service.d/limit.conf.類似的目錄redis.service.wants和redis.service.requires
1, unit 文件結構
由三部分組成:
- [Unit]-unit的基本信息和參數,包括:服務說明,unit依賴於那些服務(man 5 systemd.unit)
Description | 簡要說明 Documentation | 參考文檔列表 After | 當前服務啟動之前必須要滿足的條件(通常是target,service,socket),Before相反,定義當前服務之后的動作 Requires | 其它依賴關系,要求列出的服務與當前服務一起激活,如果requires沒啟動成功,當前服務也失敗 Wants | 比Requires更弱的依賴關系,wants不會影響當前服務的激活. Conflicts | 互斥依賴和requires相反.
- [unit type]-根據unit類型特定的選項指令,比如service,target,socket,device(更多選項man 5 systemd.service, man 5 systemd.socket...)
Type | 啟動模式,配置影響execstart和服務進程相關選項 ExecStart | 服務啟動所需要執行的命令或者腳本,還有ExecStartPre和ExecStartPost來指定ExecStar之前和之后的命令執行.Type=oneshot時可以指定多個,按順序執行. ExecStop | 服務停止執行的命令或腳本 ExecReload | 重新加載執行的命令或腳本 Restart | 重啟服務執行的命令或腳本 RemainAfterExit | 默認值是false.如果設置為true即使所有進程退出,服務也被視為活動.Type=oneshot時特別有用
Type的模式 simple | 默認值,以execstart開始的進程是服務的主要進程 forking | 從execstart開始的進程產生一個子進程,成為服務的主進程.父進程在啟動完成時退出 oneshot | 和simple類似,但是在啟動后續服務后退出進程 dbus | 與simple類似,但在之前要獲取一個d-bus name notify | 與simple類似,但是在之前要獲取 sd_notify() 函數發送一個通知消息 idle | 服務二進制的實際執行被延遲直到所有作業完成,這避免了狀態輸出與服務的shell輸出的混淆
- [Install]-服務在enable和disable命令時所用的安裝信息(man 5 systemd.unit)
Alias | 為服務設置除systemctl enable外可使用的別名
RequiredBy | 依賴列表,當服務被設為開機自啟所需要的依賴列表
WantedBy | 同上,弱依賴(通常設為WantedBy=multi-user.target) Also | 指定一起安裝或卸載的設備列表 DefaultInstance | 啟用默認實例
修改unit文件
大多數系統服務和rpm包的默認unit文件都存儲在/usr/lib/systemd/system/,通過符號鏈接到/etc/systemd/system/目錄,在需要對啟動過程進程自定義修改是不建議直接修改源文件,官方建議是通過下面兩種方法進行自定義
1, 創建配置文件目錄/etc/systemd/system/unit.d/,在這個目錄里做擴展配置和附加功能,具體步驟為:
創建目錄
mkdir /etc/systemd/system/name.service.d/
創建擴展文件,必須為.conf
touch /etc/systemd/system/name.service.d/config_name.conf
修改功能,建議只創建專注於一個任務的小配置文件。
[Service] ExecStartPost=/usr/local/bin/custom.sh
重新加載
systemctl daemon-reload
systemctl restart name.service
2, 在/etc/systemd/system/目錄下創建單獨的unit文件,而不是使用unit源文件的符號鏈接,具體步驟:
創建unit文件
cp /usr/lib/systemd/system/name.service /etc/systemd/system/name.service
修改
vi /etc/systemd/system/name.service
重新加載
systemctl daemon-reload
systemctl restart name.service
3, 觀察unit文件的重寫或修改的差異信息
systemd-delta
[EXTENDED] /usr/lib/systemd/system/redis.service → /etc/systemd/system/redis.service.d/limit.conf [REDIRECTED] /etc/systemd/system/default.target → /usr/lib/systemd/system/default.target [EXTENDED] /run/systemd/system/user-0.slice → /run/systemd/system/user-0.slice.d/50-Description.conf ...
關於差異的類型
[MASKED] | 被mask的 [EQUIVALENT] | 內容上沒有區別的文件 [REDIRECTED] | 重定向的文件(指向了其它文件) [OVERRIDEN] | 重寫覆蓋的文件 [EXTENDED] | 使用/etc/systemd/system/unit.d/config_name.conf增加功能的文件 [UNCHANGED] | 沒有修改的文件
My-test
1,啟動一個redis的master-slave
復制.service文件
cd /etc/systemd/system/multi-user.target.wants cp redis.service redis-m.service cp redis.service redis-s1.service cp redis.service redis-s2.service
master
[Unit] Description=Redis persistent key-value database After=network.target [Service] ExecStart=/usr/bin/redis-server /opt/rs/7001/redis.conf --daemonize no ExecStop=/usr/libexec/redis-shutdown User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target
slave
[Unit] Description=Redis persistent key-value database After=network.target redis-m.service [Service] ExecStart=/usr/bin/redis-server /opt/rs/7002/redis.conf --daemonize no ExecStop=/usr/libexec/redis-shutdown User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 [Install] WantedBy=multi-user.target
開啟開機自啟
#因為是放在默認的target目錄下所以會自動啟動,如果不是 systemctl enable redis-xx
2, 啟動sentinel集群
復制.service文件
cd /etc/systemd/system cp /usr/lib/systemd/system/redis-sentinel.service sentinel-1.service
配置文件
cat sentinel-1.service
[Unit]
Description=Redis Sentinel
After=network.target redis-m.service
[Service]
ExecStart=/usr/bin/redis-sentinel /opt/sentinel/8001/redis-sentinel.conf --daemonize no
ExecStop=/usr/libexec/redis-shutdown redis-sentinel
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
cat sentinel-2.service
[Unit]
Description=Redis Sentinel
After=network.target sentinel-1.service
[Service]
ExecStart=/usr/bin/redis-sentinel /opt/sentinel/8002/redis-sentinel.conf --daemonize no
ExecStop=/usr/libexec/redis-shutdown redis-sentinel
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
cat sentinel-3.service
[Unit]
Description=Redis Sentinel
After=network.target sentinel-2.service
[Service]
ExecStart=/usr/bin/redis-sentinel /opt/sentinel/8003/redis-sentinel.conf --daemonize no
ExecStop=/usr/libexec/redis-shutdown redis-sentinel
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
設置開機自啟動
systemctl enable sentinel-1.service
需要注意的是因為systemd負責管理和創建服務進程.所以redis需要加上啟動--daemonize no.