iT邦幫忙

2026 iThome 鐵人賽

DAY 24
0
IT Operation

大學生的VirtualBox虛擬機與Ubuntu實戰30天系列 第 24 篇

Day 24|服務化架構:從 Crontab 邁向 Systemd 系統服務管理

  • 分享至 

  • xImage
  •  

在上一篇中,我們透過 Crontab 實現了定時排程執行 Python 腳本。然而在正式的生產環境或伺服器維運中,Crontab 存在架構上的局限:它缺乏完善的生命週期控制(無法即時啟動、停止或重新載入)、無法在程式崩潰時自動重啟,且日誌排查完全仰賴外部重導向。

若需要讓程式以常駐服務(Daemon)的形式在背景穩定運作,現代 Linux(如 Ubuntu)的標準解決方案是Systemd。透過定義 .service 單元設定檔,能讓 Python 腳本納入系統服務管理體系,享有自動重啟、開機自啟動以及集中化日誌管理。


1.Crontab 與 Systemd Service 的架構差異

  • Crontab(排程觸發):
    • 運作機制:在特定時間點「由外向內」喚醒程序,執行完畢即結束。
    • 適用場景:週期性批次處理(例如每小時抓取一次資料、每日凌晨資料庫備份)。
    • 管理痛點:若程式異常崩潰,排程不會主動修復。
  • Systemd Service(常駐服務):
    • 運作機制:系統開機或手動啟動後持續運行於背景。
    • 適用場景:長期連線監聽、API 服務、WebSocket 即時資料串流。
    • 維運優勢:支援崩潰時自動重啟、即時狀態檢驗以及原生日誌系統)。

2.將腳本改寫為常駐迴圈模式
Systemd 常駐服務需要持續執行的程序。我們將 fetch_data.py 微調,加入無窮迴圈與適當的休眠間隔(此處設定每 60 秒抓取一次):

from datetime import datetime
import time
import requests


def get_crypto_price():
    url = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd"
    now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()
        data = response.json()
        btc_usd = data["bitcoin"]["usd"]
        print(f"[{now}] 抓取成功 - BTC: ${btc_usd:,.2f} USD", flush=True)
    except requests.exceptions.RequestException as error:
        print(f"[{now}] 請求失敗 - {error}", flush=True)


if __name__ == "__main__":
    print("比特幣即時報價監控服務啟動...")
    while True:
        get_crypto_price()
        time.sleep(60)

3.建立 Systemd Service 單元檔
Systemd 的全域服務設定檔統一放置於 /etc/systemd/system/ 目錄下。
(1)建立服務設定檔
使用 sudo 權限建立名為 crypto-tracker.service 的檔案:

sudo nano /etc/systemd/system/crypto-tracker.service

(2)撰寫單元設定內容
寫入以下標準三段式設定結構:

[Unit]
Description=Bitcoin Price Fetcher Daemon Service
After=network.target

[Service]
Type=simple
User=ithome
WorkingDirectory=/home/ithome/projects/demo_project
ExecStart=/home/ithome/projects/demo_project/.venv/bin/python /home/ithome/projects/demo_project/fetch_data.py
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

關鍵欄位解析:

  • [Unit] 區塊:
    • Description:服務的說明摘要。
    • After=network.target:指示系統必須在網路堆疊初始化完成後,才可啟動此服務。
  • [Service] 區塊:
    • Type=simple:標準常駐程式類型,Systemd 會將 ExecStart 啟動的程序視為主服務程序。
    • User=ithome:指定以一般使用者身分執行,避免使用 root 執行非特權應用帶來的安全性風險。
    • WorkingDirectory:服務啟動時的工作目錄。
    • ExecStart:服務啟動指令,直譯器與腳本均必須使用完整絕對路徑。
    • Restart=always 與 RestartSec=5:若程式異常終止或崩潰,Systemd 會在間隔 5 秒後自動重啟程序。
  • [Install] 區塊:
    • WantedBy=multi-user.target:設定開機進入標準多使用者文字模式時掛載該服務。

編輯完成後,按 Ctrl + O ➔ Enter 存檔,按 Ctrl + X 退出。


4.服務生命週期控制與日誌檢驗
(1)重新載入 Systemd 設定
新增或變更 .service 檔案後,必須通知 Systemd 重新讀取組態:

sudo systemctl daemon-reload

(2)啟動服務並檢視狀態

sudo systemctl start crypto-tracker.service
sudo systemctl status crypto-tracker.service

若終端機顯示 Active: active (running),即代表背景服務已正式進入常駐運作狀態。
(3)啟用開機自動啟動

sudo systemctl enable crypto-tracker.service

(4)使用 journalctl 追蹤服務日誌
透過以下指令即時追蹤日誌輸出

journalctl -u crypto-tracker.service -f

(按下 Ctrl + C 即可退出即時日誌檢視)


5.常駐服務生命週期控制指令
當服務已經在背景持續運行時,可依需求進行管理:

操作需求 執行指令
檢視服務運行狀態 sudo systemctl status crypto-tracker.service
手動停止服務 sudo systemctl stop crypto-tracker.service
重新啟動服務 sudo systemctl restart crypto-tracker.service
取消開機自啟動 sudo systemctl disable crypto-tracker.service

|明日目標:我們會用 Linux 內建最簡單的防火牆工具(UFW),學習怎麼只開必要的通訊埠,把不需要的連線擋在門外,不讓主機隨便被陌生人連進來。|


上一篇
Day 23|自動化排程:Linux Crontab 基礎與 Python 腳本背景執行
下一篇
Day 25|Linux UFW 防火牆基礎與連接埠安全管制
系列文
大學生的VirtualBox虛擬機與Ubuntu實戰30天 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言