免主機排程神器:cron-job.org 完整教學

在上一節我們學到了如何在本地端使用 Crontab。但如果你沒有一台 24 小時開機的伺服器,那該怎麼辦呢?

如果你已經將網站或 API 部署到了免費的 PaaS 平台(像是 Render、Heroku 或 Vercel),但這些平台可能不提供免費的「背景定時任務」功能,或者就算有,免費版也有嚴格的限制(例如:伺服器 15 分鐘沒人用就會進入休眠)。

這時候,cron-job.org 就是你的救星!

什麼是 Webhook 排程?

cron-job.org 的運作原理非常簡單。它本質上就是一台位於歐洲的伺服器,你告訴它一個 網址 (URL),以及一個 時間間隔。時間一到,這台伺服器就會去存取你指定的那個網址(就像一個隱形的使用者幫你打開瀏覽器一樣)。

只要你的網址(API)被存取了,你的後端伺服器就會開始執行你寫好的程式碼。這就是所謂的 Webhook 觸發機制

[!TIP] 常見應用場景:防止免費伺服器休眠 (Keep-alive) 許多免費平台(如 Render)如果在 15 分鐘內沒有任何 HTTP 請求,就會把你的伺服器「關機」以節省資源。下一次有人造訪時,會需要等長達 50 秒的開機時間(冷啟動)。 我們可以利用 cron-job.org,設定每 10 分鐘自動戳一次你的網站首頁。這樣一來,你的免費伺服器就會永遠保持在「開機狀態」,不用花半毛錢就獲得付費級別的服務!

註冊與建立第一個 Cronjob

1. 註冊帳號

首先前往 cron-job.org,點選右上角的 Sign Up 註冊一個免費帳號。這是一個已經穩定營運超過十年的非營利服務,非常佛心。

2. 建立新任務 (Create Cronjob)

登入後,點選介面上的 "CREATE CRONJOB" 按鈕。

這時候你會看到幾個需要設定的欄位:

  • Title (標題): 給你的任務取個名字,例如「打卡機器人保活任務」。
  • URL (網址): 填入你要觸發的 API 網址,例如 https://my-fastapi-app.onrender.com/api/daily-task
  • Execution schedule (執行排程): 這裡的介面非常直覺!你可以直接用點選的方式設定頻率:
    • Every minute (每分鐘)
    • Every 5 minutes (每五分鐘)
    • User-defined (自訂):如果你選擇自訂,它的介面跟我們上一節學的 Crontab 非常像,可以讓你勾選特定月份、星期與幾點幾分。

3. 進階設定 (Advanced)

對於基礎的「保活任務」,通常填完上面那些就夠了。但如果你是要觸發一支會修改資料庫的敏感 API,你可能會需要用到進階設定:

  • HTTP Method: 預設是 GET。如果你的後端 API 是設計成接收 POST 請求,你可以在這裡將方法改為 POST
  • Headers: 為了避免網路上無聊的駭客亂戳你的排程 API 導致重複執行,你應該在這裡加上自訂的身分驗證。 例如加入一組:
    • Key: Authorization
    • Value: Bearer my_super_secret_token_123
  • Request Body: 如果是 POST 請求,你還可以在這裡夾帶 JSON 資料傳送給你的後端。

4. 儲存與監控

設定完成後,點擊最下方的 CREATE,你的排程就開始運作了!

在 cron-job.org 的後台,你可以清楚地看到過去幾次執行的成功/失敗紀錄 (History)。如果你的 API 發生錯誤(回傳 500),它還會記錄下伺服器回傳的錯誤訊息,甚至可以設定當任務失敗時,自動寄信到你的信箱警告你!

實戰範例:FastAPI 端點設計

如果你要搭配 cron-job.org 使用,你的後端程式碼(以 Python FastAPI 為例)大概會長這樣:

from fastapi import FastAPI, Depends, HTTPException, Header
import os

app = FastAPI()

# 取得環境變數中的金鑰
CRON_SECRET = os.getenv("CRON_SECRET", "my_super_secret_token_123")

def verify_cron_token(authorization: str = Header(None)):
    """驗證請求是否來自 cron-job.org"""
    if authorization != f"Bearer {CRON_SECRET}":
        raise HTTPException(status_code=401, detail="Unauthorized Request")
    return True

@app.post("/api/daily-task")
async def run_daily_task(authorized: bool = Depends(verify_cron_token)):
    """
    這個 API 會被 cron-job.org 每天定時呼叫
    """
    print("開始執行每日任務...")
    
    # 在這裡寫入你要自動執行的商業邏輯
    # 例如:去資料庫抓報表、發送 Line 通知、清理過期資料等
    
    return {"status": "success", "message": "Daily task completed."}

[!IMPORTANT] 安全性至上! 如果你的 Webhook API 會「寫入資料」或「發送訊息」,絕對不要將它設計成無驗證公開。因為網路上有非常多惡意爬蟲會掃描網址,如果被掃到,你的 API 可能會被一天狂戳一萬次,導致資料庫爆炸或發送一萬封垃圾信。務必像上方範例一樣,使用 Token 進行保護。

透過 cron-job.org 搭配你的後端 API,你已經解決了 80% 的定時任務需求,而且完全沒有增加任何伺服器成本!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!