如何用 systemd 管理自訂服務 文章首圖

如何用 systemd 管理自訂服務

如何用 systemd 管理自訂服務

在現代 Linux 發行版中,systemd 已經取代了傳統的 SysVinit,成為系統初始化和服務管理的標準。對於開發者和系統管理員來說,能夠自訂並管理自己的服務(Service)是日常工作的核心技能。無論是你寫的 Python 腳本、Node.js 應用,還是其他後台程序,透過 systemd 管理都能讓它們在開機時自動啟動、崩潰時自動重啟,並方便地查看日誌。

這篇文章將引導你從零開始,建立一個簡單的自訂服務,涵蓋檔案建立、權限設定、啟用服務以及除錯技巧。

步驟一:準備測試腳本

首先,我們需要一個簡單的腳本作為示範。為了方便理解,我們建立一個會持續輸出時間的 Python 腳本。請在 /opt 目錄下建立一個資料夾並撰寫腳本:

sudo mkdir -p /opt/myapp
sudo nano /opt/myapp/app.py

在檔案中輸入以下內容:

#!/usr/bin/env python3
import time
import datetime

while True:
    print(f"Current time: {datetime.datetime.now()}")
    time.sleep(5)

儲存並離開後,務必賦予該腳本執行權限:

sudo chmod +x /opt/myapp/app.py

步驟二:建立 systemd 服務單元檔案

systemd 的服務配置檔通常存放在 /etc/systemd/system/ 目錄下,副檔名為 .service。我們要建立一個名為 myapp.service 的檔案。

sudo nano /etc/systemd/system/myapp.service

請填入以下內容。這裡我們使用 UserGroup 來確保服務以非 root 身份運行,這是安全最佳實踐:

[Unit]
Description=My Custom Application Service
After=network.target

[Service]
Type=simple
User=ubuntu
Group=ubuntu
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

關鍵參數說明:

  • ExecStart:指定啟動服務時執行的完整路徑指令。
  • Restart=on-failure:當程式異常退出時,系統會自動重啟服務。
  • WantedBy=multi-user.target:確保服務在系統進入多使用者模式(一般開機狀態)時被啟用。

步驟三:啟用並啟動服務

修改完配置後,必須重新載入 systemd 的 daemon 配置,讓系統識別新的服務檔案。

sudo systemctl daemon-reload

接著,我們啟用並啟動服務:

sudo systemctl enable --now myapp.service

enable 會建立符號連結,確保開機時自動啟動;--now 參數則會立即啟動該服務。你可以透過以下指令檢查服務狀態:

sudo systemctl status myapp.service

如果看到綠色的 active (running) 狀態,且下方有輸出時間訊息,代表服務已成功運行。

常見問題與除錯技巧

1. 服務無法啟動,狀態顯示為 failed

當服務啟動失敗時,systemctl status 通常只會顯示最後幾行錯誤。更詳細的資訊可以透過 journalctl 查詢。由於我們配置了將標準輸出和錯誤導向 journal,你可以使用以下指令查看最近的日誌:

sudo journalctl -u myapp.service -e

-e 參數會直接跳到日誌末尾,-f 則可以即時追蹤日誌(類似 tail -f)。如果發現路徑錯誤或權限問題,請檢查 ExecStart 中的路徑是否正確,以及 User 是否有權限讀取腳本和相關檔案。

2. 修改配置後服務沒有生效

許多使用者在修改 .service 檔案後,直接執行 sudo systemctl restart myapp.service,但發現更改無效。這是因為 systemd 在啟動時會讀取配置,若配置結構有變(例如新增了環境變數或修改了 Restart 策略),有時需要重新載入 daemon 才能完全生效。

標準的更新流程應為:

  1. 編輯服務檔案。
  2. 執行 sudo systemctl daemon-reload
  3. 執行 sudo systemctl restart myapp.service

若仍無法解決,可嘗試 sudo systemctl reload myapp.service,但這僅適用於支援熱重載的服務。對於大多數簡單服務,重啟是必要的。

小結

透過這篇文章,我們學會了如何建立自訂的 systemd 服務單元檔案。這不僅適用於 Python 腳本,同樣也適用於 Go、Node.js、Java 等任何可執行程式。掌握 systemctljournalctl 的組合使用,能讓你在管理後台服務時更加得心應手。記住,良好的服務配置(如正確的權限和重啟策略)是維持系統穩定性的關鍵。