🐧 Linux systemd 深入解析與啟動流程管理
在現代 Linux 發行版中,systemd 幾乎是預設的初始化系統(init),負責 開機流程、服務管理、日誌、定時任務 與 資源控制 等工作。本文從 啟動鏈 到 單元(unit)設計、排錯、安全強化 與 最佳實務,帶你完整掌握。
📑 目錄
- 一、開機啟動鏈(Boot Chain)
- 二、Unit 基礎:類型、目標與依賴
- 三、Service 設計:Type、Restart、Environment
- 四、覆寫與 Drop-in:不動原檔也能客製
- 五、Timer vs cron:事件式排程的優勢
- 六、Socket/Path/Device 啟動:按需載入
- 七、日誌與開機分析:journalctl 與 systemd-analyze
- 八、資源控制與沙箱:cgroups 與 Hardening
- 九、常見錯誤與排查清單
- 十、實用 Recipes(可直接套用)
- 🔗 延伸閱讀
一、開機啟動鏈(Boot Chain)
- Firmware/UEFI → Bootloader(GRUB):載入核心與 initramfs。
- kernel:掛載 root、啟動
PID 1(systemd)。 - systemd:解析預設 target(多使用
default.target指向graphical.target或multi-user.target)。 - 依賴解析:依單元(unit)間的
Requires/Wants、Before/After、Conflicts執行。
# 查看目前預設 target 與切換
systemctl get-default
sudo systemctl set-default multi-user.target
sudo systemctl isolate rescue.target # 立即切到維護模式
二、Unit 基礎:類型、目標與依賴
常見單元類型:
- service:常駐或一次性服務。
- socket:socket-activated 服務(按需啟動)。
- timer:取代或補強 cron 的排程。
- target:一組單元的集合(階段或狀態)。
- path:檔案/目錄變動觸發。
- mount/automount、device:掛載或裝置事件。
# 查依賴與執行關係
systemctl list-dependencies multi-user.target
systemctl cat sshd.service
systemctl status NetworkManager.service
三、Service 設計:Type、Restart、Environment
Type 影響 systemd 判定「服務已就緒」的方式:
simple(預設):主行程不 daemonize。forking:行程fork()後在背景常駐(傳統 daemon)。notify:程式透過 sd_notify 告知「就緒」。oneshot:一次性任務,常搭配RemainAfterExit=yes。
範例:穩定自動重啟的常駐服務
[Unit]
Description=My Web App
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
Restart=on-failure
RestartSec=3
Environment="ENV=prod" "PORT=8080"
# 安全建議(見下節 Hardening)
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.target
四、覆寫與 Drop-in:不動原檔也能客製
不要直接改套件提供的 /usr/lib/systemd/system/*.service。改用覆寫:
sudo systemctl edit myapp.service # 會在 /etc/systemd/system/myapp.service.d/ 建置 drop-in
# 編寫內容(只放差異):
[Service]
Environment="DEBUG=false"
Restart=always
套用並查看:
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
systemctl cat myapp.service
五、Timer vs cron:事件式排程的優勢
- 與 service 綁定:排程觸發對應 service,管理一致。
- 支援搖晃時間(RandomizedDelay):避免尖峰。
- 缺漏補跑(Persistent):機器關機期間的任務會補執行。
範例:每天 02:15 執行備份,若錯過則開機補跑
# /etc/systemd/system/backup.service
[Unit]
Description=Nightly Backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=*-*-* 02:15:00
Persistent=true
RandomizedDelaySec=120
[Install]
WantedBy=timers.target
# 啟用
sudo systemctl enable --now backup.timer
systemctl list-timers --all
六、Socket/Path/Device 啟動:按需載入
socket 啟動讓服務在連線發生時再啟用,降低常駐資源。
# 觀察 socket 與對應 service
systemctl list-sockets
systemctl status ssh.socket
七、日誌與開機分析:journalctl 與 systemd-analyze
# 只看本次開機、重要等級以上
journalctl -b -p warning
# 追服務日誌(即時)
journalctl -u myapp.service -f
# 啟動耗時總覽與關鍵鏈
systemd-analyze
systemd-analyze blame
systemd-analyze critical-chain
# 產生 SVG(於桌面開啟檢視)
systemd-analyze plot > boot.svg
八、資源控制與沙箱:cgroups 與 Hardening
- CPU/記憶體限制:
CPUQuota=50%、MemoryMax=1G - 沙箱化選項:
NoNewPrivileges=true、PrivateTmp=true、ProtectSystem=full、ProtectHome=true、CapabilityBoundingSet= - 臨時服務:
systemd-run --scope/--unit快速掛限制跑任務。
# 以 50% CPU、1G 記憶體限制執行任務
sudo systemd-run --unit=limit-job --scope -p CPUQuota=50% -p MemoryMax=1G /usr/bin/some-task
九、常見錯誤與排查清單
- 服務啟動卡住:檢查
After=network-online.target是否缺Wants=network-online.target;確認systemd-networkd-wait-online或 NetworkManager 連線等待設定。 - 權限問題:服務
User=指定用戶之檔案/目錄權限(參考chmod/chown基礎)。 - 路徑未就緒:使用
pathunit 或在ExecStartPre加入檢查/建立。 - Daemonize 與 Type 不符:傳統 daemon 設
Type=forking,否則 systemd 誤判狀態。 - 錯誤復發:設定
Restart=on-failure與RestartSec=,並加強日誌分析(journalctl -xeu)。
十、實用 Recipes(可直接套用)
🧩 1) 服務需等「網路可用」再啟動
[Unit]
After=network-online.target
Wants=network-online.target
🧩 2) oneshot 初始化 + 常駐服務串聯
# init.service 做準備;myapp.service 真正啟動
[Unit]
Description=Initialize directories
Before=myapp.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/init_dirs.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
🧩 3) 自動重啟並限制重試頻率
[Service]
Restart=on-failure
RestartSec=3
StartLimitIntervalSec=60
StartLimitBurst=5
🧩 4) 硬化一個網頁服務(最小特權)
[Service]
User=www-data
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
CapabilityBoundingSet=
AmbientCapabilities=
ReadWritePaths=/var/lib/myapp
🔗 延伸閱讀(站內)
- Linux 核心參數與 I/O 調校(sysctl)
- Linux 效能監控:top、htop、iotop、nmon
- sed 文字處理速查
- Netplan 與 ifcfg 網路設定
- 檔案權限 rwx、chmod、chown 入門
- Samba Server 安裝與設定
- Linux Proxy(Squid)建置與設定
- 使用 GoAccess 進行網站流量分析
最後更新:2025-10-23 · 作者:WWFandy
沒有留言: