linux | 自動化之systemd
linux 中的自動化之systemd
學習總是循序漸進的。
linux 中程序的自動化,包括早期手動啟動,查看啟動后的日志、分析啟動情況,再到后面封裝腳本(大致要求啟動后檢查是否掛了,掛了拉起,沒掛跳過)然后加入到定時器任務,再到加入service
關鍵詞:自動化、注冊服務、定時器、GUI、CLI
系統管理
systemd 并不是一個命令,而是一組命令,涉及到系統管理的方方面面
- systemctl
1.1 systemctl 是 systemd 的主命令,用于管理系統
# 重啟
systemctl reboot# 啟動進入救援模式
systemctl rescue
1.2 systemd-analyze 用于查看啟動耗時
# 查看啟動耗時
systemd-analyze# 查看每個服務啟動耗時
systemd-analyze blame# 顯示制定服務的啟動流
systemd-analyze critical-chain atd.service
1.3 hostnamectl
# 查看主機信息
hostnamectl# 設置主機名
sudo hostnamectl set-hostname zhangbuda7788
1.4 timedatectl
# 查看當前時區設置
timedatectl# 顯示所有可用的時區
timedatectl list-timezones# 設置當前時區
sudo timedatectl set-timezone America/New_York
sudo timedatectl set-time YYYY-MM-DD
sudo timedatectl set-time HH:MM:SS
1.5 查看當前登錄用戶
# 列出當前的session
loginctl list-sessions# 列出當前登錄用戶
loginctl list-users# 列出顯示制定用戶信息
loginctl show-user zhangbuda7788
- unit
systemd 管理不同的系統資源,不同的資源統稱為 unit 系統->unit->具體的servie
2.1 常見的Unit
# 系統服務
Service unit# 多個Unit 構成的一個組
Target unit# 硬件設備
Device unit# 文件系統的掛載點
Mount unit# 自動掛載點
Automount Unit# 文件或路徑
Path unit# 不是由 systemd 啟動的外部進程
Scope unit# 進程組
Slice unit# 快照,可以切回某個快照
Scope unit# 進程間通信的 socket
Socket unit# swap 文件
Swap Unit# 定時器
Time Unit
2.2 查看系統的所有 Unit
# 列出正在運行的 Unit
systemctl list-unit# 列出所有的 Unit 包括沒有找到配置文件的或者啟動失敗的
systemctl list-units --all# 列出所有沒有運行的 unit
systemctl list-units --all --state=inactive# 列出所有加載失敗的 Unit
systemctl list-units --failed# 列出所有正在運行的、類型為 Service 的Unitsystemctl list-units --type=service
- service
3.1 服務的位置
/etc/systemd/system
3.2 查看已經安裝的單元文件(unit-file)
systemctl list-unit-files
3.3 查看已經激活的單元任務
systemctl list-units
3.4 服務的具體操作
systemctl is-active/is-failed/is-enabled/enable/disable/start/restart/reload/stop xxx## 在修改配置文件后,需要重新加載配置文件再啟動相關服務
sudo systemctl daemon-reload## 重啟相關服務
sudo systemctl restart xxx
3.5 查看unit 之間的依賴關系
systemctl list-dependencies xxx查看 包含依賴 target 類型的依賴關系
systemctl list-dependencies -all
3.6 查看配置問價你的狀態
# 列出所有配置文件
systemctl list-unit-files# 列出指定類型的配置文件
## enabled 已建立啟動鏈接
## disabled 沒建立啟動鏈接
## static 該配置文件沒有 [install] 部分,只能作為其他配置文件的依賴
## masked 該配置文件被禁止建立啟動鏈接
systemctl list-unit-files --type=service
3.7 日志
systemd 管理很多服務,包括系統本身的、后續部署的、以及人工添加的,所以這樣可以通過命令 journalctl 命令查看 這幾大塊的所有服務。
# 查看服務日志
sudo journalctl -u xxx
# 查看實時日志
sudo journalctl -u xxx -f
# 查看近100 行日志
sudo journalctl -u xxx -n 100
# 查看制定時間短的日志
sudo journalctl -u xxx --since '2025-06-12 15:00' --until '2025-06-12 16:00'
3.8 配置文件的格式
配置文件是普通的文本文件,可以用文本編輯器打開。配置文件的區塊名和字段名都大小寫敏感。每個區塊內部是一些等號鏈接的鍵值對,鍵值對的等號兩側不能有空格。
[Unit] 定義 Unit 的元數據,配置 當前要跑的service 與主機系統中的 Unit 內的服務之間的關系
Description:簡短描述
Documentation:文檔地址
Requires:當前 Unit 依賴的其他 Unit,如果它們沒有運行,當前 Unit 會啟動失敗
Wants:與當前 Unit 配合的其他 Unit,如果它們沒有運行,當前 Unit 不會啟動失敗
BindsTo:與Requires類似,它指定的 Unit 如果退出,會導致當前 Unit 停止運行
Before:如果該字段指定的 Unit 也要啟動,那么必須在當前 Unit 之后啟動
After:如果該字段指定的 Unit 也要啟動,那么必須在當前 Unit 之前啟動
Conflicts:這里指定的 Unit 不能與當前 Unit 同時運行
Condition...:當前 Unit 運行必須滿足的條件,否則不會運行
Assert...:當前 Unit 運行必須滿足的條件,否則會報啟動失敗[Service] 用來 Service 的配置 這是具體的 服務。所有,它歸屬于 Unit 然后 Unit 又歸屬于整個 Service
Type:定義啟動時的進程行為。它有以下幾種值。
Type=simple:默認值,執行ExecStart指定的命令,啟動主進程
Type=forking:以 fork 方式從父進程創建子進程,創建后父進程會立即退出
Type=oneshot:一次性進程,Systemd 會等當前服務退出,再繼續往下執行
Type=dbus:當前服務通過D-Bus啟動
Type=notify:當前服務啟動完畢,會通知Systemd,再繼續往下執行
Type=idle:若有其他任務執行完畢,當前服務才會運行
ExecStart:啟動當前服務的命令
ExecStartPre:啟動當前服務之前執行的命令
ExecStartPost:啟動當前服務之后執行的命令
ExecReload:重啟當前服務時執行的命令
ExecStop:停止當前服務時執行的命令
ExecStopPost:停止當其服務之后執行的命令
RestartSec:自動重啟當前服務間隔的秒數
Restart:定義何種情況 Systemd 會自動重啟當前服務,可能的值包括always(總是重啟)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
TimeoutSec:定義 Systemd 停止當前服務之前等待的秒數
Environment:指定環境變量[Install] 用來定義如何啟動,以及是否開機啟動
WantedBy:它的值是一個或多個 Target,當前 Unit 激活時(enable)符號鏈接會放入/etc/systemd/system目錄下面以 Target 名 + .wants后綴構成的子目錄中
RequiredBy:它的值是一個或多個 Target,當前 Unit 激活時,符號鏈接會放入/etc/systemd/system目錄下面以 Target 名 + .required后綴構成的子目錄中
Alias:當前 Unit 可用于啟動的別名
Also:當前 Unit 激活(enable)時,會被同時激活的其他 Unit
在 Linux 系統中,systemd target 和傳統的 SysV init 啟動模式 都是用來控制系統啟動時運行哪些服務和程序的機制。但兩者在設計理念、結構、管理方式上有本質區別。
Runlevel | 含義 |
---|---|
0 | 關機 |
1 | 單用戶模式(維護) |
3 | 多用戶模式(無圖形) |
5 | 圖形界面(X11) |
6 | 重啟 |
Target | 等價 Runlevel | 描述 |
---|---|---|
rescue.target | 1 | 單用戶模式 |
multi-user.target | 3 | 多用戶模式,無圖形 |
graphical.target | 5 | 多用戶模式,有圖形界面 |
reboot.target | 6 | 重啟 |
poweroff.target | 0 | 關機 |
default.target | - | 系統默認啟動目標(可配置) |
特性 | SysV Init | systemd target |
---|---|---|
配置文件 | /etc/inittab , /etc/rc*.d/ | /etc/systemd/system/*.target |
啟動機制 | 順序啟動 | 并行啟動,基于依賴關系 |
啟動級別名稱 | runlevel(0~6) | target |
服務控制 | 腳本(/etc/init.d/xxx ) | 單元文件(unit files) |
啟動速度 | 較慢 | 更快(并行 + 依賴分析) |
可讀性、擴展性 | 差,維護復雜 | 強,結構清晰 |
狀態查看命令 | service , chkconfig | systemctl status ,list-units |
設置默認啟動級別 | initdefault in /etc/inittab | systemctl set-default |
unit 官方文檔
阮一峰 systemd
mac 服務
launchctl
launchctl 是 macos 下控制 launchd 的命令行工具
launchd 是 macos 系統初始化和服務管理器(相當于 linux 的 systemd 或 init)
launchctl 允許你家在、啟動、停止、卸載系統或用戶服務
macos 啟動項種類及放置路徑
launch Agent 用戶級別服務,依附圖形登錄會話 ~/Library/LaunchAgents/ (不需要sudo)或者 /Library/LaunchAgents/ (需要sudo)
launch Daemon 系統級別服務,在后臺獨立運行 /Library/LaunchDaemonts/ (需要sudo)
# 啟動服務
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/xxx.plist# 卸載服務
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/xxx.plist# 查看服務狀態
launchctl print gui/$(id -u)/com.xxx.identifier## 查看服務日志, 一般的會在 配置文件 ~/Library/LaunchAgents/xxx.plist 中配置日志目錄 比如 /tmp/frps.log## 擴展,常見的 mac 日志# 系統日志
/var/log/system.log
# 崩潰日志
~/Library/Logs/DiagnosticReports
#系統級應用日志
/Library/Logs
補充:
關于 gui/$(id -u)
其中 id -u 返回的是 501 (可以在終端直接執行)
將服務加載到當前用戶的圖形桌面登錄會話中,而不是僅僅在后臺或終端運行。
延伸
macos 把用戶的圖形桌面環境(Finder、Dock、通知中心、菜單欄圖標等)當作一個特殊的 【 會話 】
某些服務(托盤圖標程序、圖像化客戶端、桌面通知)必須綁定到這個桌面圖形會話中運行,否則不會生效。
這類服務要通過 gui/UID 域注冊給桌面環境, UID 可以通過 uid -u 獲得。什么是當前用戶桌面會話? GUI Session
當登錄macos 后看到桌面界面 (Finder、菜單欄、Dock、應用窗口)
是系統中一個完整的用戶圖形登錄會話
運行時對應的 launchd 域是 gui/ 如 gui/501
只有加載到這個會話中的服務,才能與桌面交互(顯示界面、通知、托盤圖標、剪貼板等)
疑問:
為什么可以 launchctl bootout gui/ ( i d ? u ) / c o m . z h a n g b u d a . f r p s 這樣退出卻不能 l a u n c h c t l b o o t s t r a p g u i / (id -u)/com.zhangbuda.frps 這樣退出卻不能launchctl bootstrap gui/ (id?u)/com.zhangbuda.frps這樣退出卻不能launchctlbootstrapgui/(id -u)/com.zhangbuda.frps這樣啟動,而必須采用 launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.zhangbuda.frps.plist 的方式啟動
bootout 支持 domain+label 的方式 也就是 gui/$(id -u)/com.zhangbuda.frps
相應的 launchctl bootstrap 需要提供完成服務 的路徑,因為服務還沒注冊,系統還不知道 該服務的配置。