熱門分類
載入中…
目錄0%

🧱 Linux systemctl 與服務管理全攻略(含常見錯誤與自動重啟設定)

    🧱 Linux systemctl 與服務管理全攻略(含常見錯誤與自動重啟設定)

    這篇整理 systemctl 的常用與進階操作:從 查詢與控制服務開機自啟自動重啟策略覆寫 drop-injournalctl 排錯Timer 排程安全強化,提供可直接複製的指令與範例單元檔。

    📑 目錄

    一、常用 systemctl 指令速查

    # 啟動 / 停止 / 重新啟動 / 重新載入設定
    sudo systemctl start nginx
    sudo systemctl stop nginx
    sudo systemctl restart nginx
    sudo systemctl reload nginx
    
    # 查看狀態與即時日誌
    systemctl status nginx
    journalctl -u nginx -f
    
    # 查看是否開機自啟;設定開機自啟 / 取消
    systemctl is-enabled nginx
    sudo systemctl enable nginx
    sudo systemctl disable nginx
    
    # 列出服務、套用變更
    systemctl list-units --type=service --state=running
    sudo systemctl daemon-reload
    
    # 查看單元檔與依賴
    systemctl cat nginx.service
    systemctl list-dependencies multi-user.target
    

    二、開機自動啟動與目標(target)

    enable 會建立 WantedBy 目標(通常 multi-user.target),讓服務於開機時載入。

    # 目前預設 target 與切換
    systemctl get-default
    sudo systemctl set-default multi-user.target
    sudo systemctl isolate rescue.target   # 立即切換到維護模式

    三、自動重啟策略(Restart=)最佳實務

    • Restart=on-failure:非 0 結束碼時重啟,最常用。
    • Restart=always:任何結束都重啟,用於長駐、須高可用的服務。
    • RestartSec=:重啟間隔;StartLimitIntervalSec=StartLimitBurst= 防止瘋狂重啟。
    • 加上 RuntimeMaxSec= 或健康檢查腳本,避免服務卡死無感。

    四、Service Unit 樣板:穩定、可回復、可觀測

    📄 點我展開範例(建議複製後依實際路徑與使用者調整)
    [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
    StartLimitIntervalSec=60
    StartLimitBurst=5
    # --- 環境與日誌 ---
    Environment="ENV=prod" "PORT=8080"
    StandardOutput=journal
    StandardError=journal
    # --- 沙箱化(見下節 Hardening)---
    NoNewPrivileges=true
    PrivateTmp=true
    ProtectSystem=full
    ProtectHome=true
    
    [Install]
    WantedBy=multi-user.target

    五、不改原檔的覆寫:drop-in(systemctl edit)

    不要改套件提供的 /usr/lib/systemd/system/*.service;用 drop-in 更安全。

    sudo systemctl edit myapp.service
    # 會開啟 /etc/systemd/system/myapp.service.d/override.conf
    # 只放差異:
    [Service]
    Restart=always
    Environment="DEBUG=false"
    
    # 套用
    sudo systemctl daemon-reload
    sudo systemctl restart myapp.service
    systemctl cat myapp.service

    六、常見錯誤與排查清單

    • 🔌 啟動卡住:缺 Wants=network-online.target 或未正確等待網路;檢查 NetworkManager-wait-onlinesystemd-networkd-wait-online
    • 🗝 權限錯誤:服務 User= 指定帳號是否擁有目錄與檔案權限;用 chown/chmod 修正。
    • 📁 路徑不存在:在 ExecStartPre=/usr/bin/mkdir -p /var/lib/myapp 先建立。
    • 👻 Type 設錯:傳統 daemon 應 Type=forking;有通知機制才用 notify
    • 🔁 無限重啟:調整 RestartSecStartLimit*,並用 journalctl -xeu 找根因。

    七、journalctl 與啟動耗時分析

    # 當次開機的重要訊息
    journalctl -b -p warning
    
    # 追服務日誌(即時)
    journalctl -u myapp.service -f
    
    # 啟動耗時總覽與關鍵鏈
    systemd-analyze
    systemd-analyze blame
    systemd-analyze critical-chain
    
    # 輸出啟動流程圖(SVG)
    systemd-analyze plot > /tmp/boot.svg

    八、Timer vs cron:事件式排程與補跑

    🕒 範例:每天 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

    九、服務沙箱與資源限制

    • 資源限制CPUQuota=50%MemoryMax=1G
    • 沙箱化選項NoNewPrivileges=truePrivateTmp=trueProtectSystem=fullProtectHome=trueCapabilityBoundingSet=(最小權限)。
    • 臨時限制執行systemd-run --scope -p CPUQuota=50% -p MemoryMax=1G <cmd>
    # 以 50% CPU、1G 記憶體限制執行
    sudo systemd-run --unit=limit-job --scope -p CPUQuota=50% -p MemoryMax=1G /usr/bin/some-task

    🔎 常見問答(FAQ)

    Q1:我改了 unit 檔,但服務沒有套用?
    請先 sudo systemctl daemon-reloadrestart。變更才會被載入。

    Q2:服務已 enable,為何開機沒有跑?
    檢查 WantedBy 所屬 target 是否為系統 get-default 的依附鏈;另查 journalctl -b

    Q3:如何讓 oneshot 任務失敗也能重試?
    [Service] 使用 Restart=on-failureRestartSec=,並將邏輯拆為可重入。

    🧭 行動清單

    ✅ 將既有服務加入 Restart 策略與 StartLimit* 保護
    ✅ 以 systemctl edit 建立 drop-in 覆寫(不動原檔)
    ✅ 用 journalctl 與 systemd-analyze 檢查開機瓶頸
    ✅ 關鍵任務改用 Timer,啟用 Persistent 與 RandomizedDelaySec
    ✅ 套用沙箱化選項與資源上限(CPUQuota / MemoryMax)
      

    — WWFandy・系統管理筆記

    🔗 分享這篇 LINE Facebook X

    沒有留言:

    字級