GitHub Actions 定时任务完整指南:schedule 触发器从入门到生产

7 阅读4分钟

GitHub Actions 定时任务完整指南:schedule 触发器从入门到生产

GitHub Actions 是目前最流行的 CI/CD 工具之一,除了代码推送触发之外,它还支持 定时触发(schedule) ,也就是用 Cron 表达式来控制 workflow 的执行时间。

本文覆盖 schedule 触发器的所有用法、常见坑和生产最佳实践。


一、基础语法

on:
  schedule:
    - cron: '0 9 * * 1'   # 每周一 UTC 9:00

Cron 表达式 5 个字段:

┌───────────── 分钟 (0-59)
│ ┌───────────── 小时 (0-23)
│ │ ┌───────────── 日 (1-31)
│ │ │ ┌───────────── 月 (1-12)
│ │ │ │ ┌───────────── 星期 (0-60=周日)
│ │ │ │ │
* * * * *

💡 不想手写 Cron 表达式?用 Hey Cron 输入中文描述直接生成,例如输入"每周一早上9点"自动生成 0 9 * * 1,同时输出 GitHub Actions 格式。

常用示例:

表达式含义
0 9 * * 1每周一 UTC 9:00
0 0 * * *每天 UTC 0:00
*/30 * * * *每 30 分钟(最小间隔)
0 9 * * 1-5工作日每天 UTC 9:00
0 0 1 * *每月 1 号 UTC 0:00

二、最小可用示例

name: Weekly Report

on:
  schedule:
    - cron: '0 9 * * 1'  # 每周一 UTC 9:00

jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run report script
        run: python scripts/generate_report.py

三、最常踩的坑

坑 1:时区是 UTC,不是北京时间

GitHub Actions 的 schedule 只支持 UTC 时间,没有时区设置选项。

北京时间 = UTC + 8,换算方法:

想要北京时间执行的时间 - 8 = 填入 cron 的小时数

示例:

想要的北京时间填入 cron
每天早上 9:000 1 * * *(UTC 1:00)
每天下午 18:000 10 * * *(UTC 10:00)
每天凌晨 0:000 16 * * *(UTC 前一天 16:00)

坑 2:最小间隔是 5 分钟

GitHub Actions 不允许 schedule 间隔小于 5 分钟,*/1 * * * * 这种写法会被忽略或报错。

# ❌ 不支持,最小间隔 5 分钟
- cron: '* * * * *'

# ✅ 最短间隔
- cron: '*/5 * * * *'

坑 3:仓库不活跃会被自动禁用

GitHub 官方规定:如果仓库 60 天内没有任何活动,schedule 触发器会被自动禁用。

解决方案:定期 push 代码,或者在 workflow 本身里提交一次空 commit 保持活跃。

坑 4:高负载时存在延迟

GitHub Actions 的 schedule 不是精确定时,高峰期可能延迟 15-30 分钟甚至更长。对时间精度要求高的任务不适合用 GitHub Actions schedule。


四、多个 cron 表达式

一个 workflow 可以设置多个 schedule,任意一个触发时都会执行:

on:
  schedule:
    - cron: '0 9 * * 1'   # 每周一 UTC 9:00
    - cron: '0 9 * * 4'   # 每周四 UTC 9:00

五、同时支持手动触发

生产中推荐加上 workflow_dispatch,这样可以在 GitHub UI 上手动触发,方便测试和紧急执行:

on:
  schedule:
    - cron: '0 9 * * 1'
  workflow_dispatch:       # 加上这行,允许手动触发

加了之后在 Actions 页面会出现 Run workflow 按钮。


六、判断是定时触发还是手动触发

有时需要在 workflow 内部区分触发来源:

steps:
  - name: Check trigger
    run: |
      if [ "${{ github.event_name }}" = "schedule" ]; then
        echo "定时触发"
      else
        echo "手动触发"
      fi

七、实际使用场景

场景 1:定时数据同步

name: Daily Data Sync

on:
  schedule:
    - cron: '0 1 * * *'  # 北京时间每天早上 9:00
  workflow_dispatch:

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run sync
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          API_KEY: ${{ secrets.API_KEY }}
        run: python scripts/sync.py

场景 2:定时清理过期数据

name: Cleanup Old Records

on:
  schedule:
    - cron: '0 16 * * *'  # 北京时间每天凌晨 0:00

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Cleanup
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
        run: |
          node scripts/cleanup.js --days=30

场景 3:定时健康检查

name: Health Check

on:
  schedule:
    - cron: '*/10 * * * *'  # 每 10 分钟

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - name: Check API health
        run: |
          STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health)
          if [ $STATUS -ne 200 ]; then
            echo "Health check failed with status: $STATUS"
            exit 1
          fi
          echo "Health check passed"

场景 4:定时发送周报

name: Weekly Summary

on:
  schedule:
    - cron: '0 1 * * 1'  # 北京时间每周一早上 9:00
  workflow_dispatch:

jobs:
  summary:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Generate and send summary
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
        run: node scripts/weekly-summary.js

八、调试技巧

技巧 1:先用 push 触发测试

写好 workflow 之后,先加一个 push 触发来快速验证逻辑,确认没问题再切回 schedule:

on:
  push:
    branches: [main]   # 测试阶段先用 push 触发
  # schedule:
  #   - cron: '0 9 * * 1'

技巧 2:查看下次执行时间

可以用 crontab.guruHey Cron 验证表达式,确认下次执行时间是否符合预期。

技巧 3:查看历史执行记录

Actions → 选择 workflow → 可以看到每次执行的时间、耗时和日志。


九、安全注意事项

  • 不要在 cron 表达式或 run 命令里硬编码密钥,统一用 ${{ secrets.XXX }} 引用
  • schedule 触发的 workflow 默认使用 repository 权限,注意控制 permissions
  • 对外部 API 调用要加超时和错误处理,避免 workflow 卡死

总结

要点说明
时区只支持 UTC,北京时间需减 8 小时
最小间隔5 分钟
仓库不活跃60 天没活动自动禁用
延迟高峰期可能延迟 15-30 分钟
推荐加上 workflow_dispatch 方便手动触发

GitHub Actions schedule 适合对时间精度要求不高的定时任务,比如每日数据同步、周报生成、定期清理等场景。如果需要精确到分钟级别的定时执行,建议使用云函数 + EventBridge 方案。


如果你需要在 GitHub Actions 和其他平台(Kubernetes、Jenkins、Airflow)之间切换定时任务配置,可以试试 Hey Cron,输入自然语言一次生成所有平台的格式,省去反复查文档的时间。