定时任务
按计划运行命令或 HTTP 请求。创建第一个任务前请阅读“命令在哪里运行”:定时任务不在应用正在运行的容器中执行,而是在一个获得相同变量的一次性容器中执行。
创建定时任务
定时任务在控制台的 Cron Jobs 页面管理,也可以使用 sh0 cron。任务通常关联到一个应用。
- 在侧边栏打开 Cron Jobs,点击 Create Cron Job。
- Name -- 名称,例如
nightly-report。 - Application -- 任务所属的应用。不选应用时,只接受 HTTP 命令(见下文)。
- Schedule -- 5 字段 cron 表达式,按 UTC 计算。
- Command -- HTTP 请求(
curl、wget或单独的 URL),或在容器中运行的程序。 - 可选:Container Image(留空 = 应用的镜像)和 Timeout (seconds),默认 300。然后创建任务。
用 CLI 完成同样的操作(以下命令在服务器上实际执行过):
$ sh0 cron create --app my-api --name nightly-report \
--schedule "0 3 * * *" \
--command "curl -s -X POST https://api.example.com/internal/report"
Cron job 'nightly-report' created (id: 72173a56-1962-47dc-88e5-2a276ef3bfcc)
$ sh0 cron trigger 72173a56-1962-47dc-88e5-2a276ef3bfcc
Cron job 'nightly-report' triggered.
$ sh0 cron runs 72173a56-1962-47dc-88e5-2a276ef3bfcc
RUN ID STATUS EXIT DURATION STARTED
----------------------------------------------------------------------------------------------------
9e329bc7-01c5-41ec-9eb5-5ab745fde533 success 0 295ms 2026-10-02 02:33:23命令在哪里运行
sh0 根据命令和任务设置,按以下顺序选择执行方式:
- HTTP 请求 -- 以
curl或wget开头的命令,或单独的 URL,不经 shell 执行:sh0 从服务器自行发送请求,限时 30 秒。支持-X、-H和-d。响应状态码为 400 或以上时,本次运行记为失败。对于绑定到应用的任务,其项目的内部名称(my-api.internal,或单独的my-api)会解析到对应服务。 - 应用镜像 -- 其他命令在一个从应用当前镜像启动的全新一次性容器中运行,使用非 root 用户,接入 sh0 网络及其项目网络。它不是你正在运行的容器:应用运行时写入的文件不在其中,运行结束后容器即被删除。
- 指定镜像 -- 如果填写了 Container Image,临时容器改用该镜像启动。
- 既无应用也无镜像 -- 非 HTTP 命令在执行时被拒绝。sh0 从不在主机上运行定时命令。
Note
自 1.10.3 起:容器会获得应用的变量。绑定到应用的任务会获得应用及其项目的运行时变量(应用的值优先),与应用自身的容器完全相同。构建时变量不会传入。任务的输出会保存在运行历史中:打印出密钥的命令会把它留在那里,拥有该应用开发者权限的人都能看到。
在一个 Node.js 应用上实测:应用设置了 GREETING,其项目设置了 REGION。任务 env 会同时打印这两个变量,以及镜像内置的变量。
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=0.0.0.0
REGION=eu431
GREETING=hello431
NODE_VERSION=22.23.3
YARN_VERSION=1.22.22
PORT=3000
HOME=/home/nodeGREETING 和 REGION 都在其中。HOME=/home/node 这一行表明使用的是非 root 用户。
命令规则
命令是单个程序加上它的参数。sh0 在创建任务时进行检查:
- 没有 shell。字符
;|&><、反引号、$(和换行都会被拒绝。不支持管道、&&串联和变量展开。 - 引号只在 HTTP 请求中生效。在容器中,命令按空格拆分:
sh -c "echo hi"不会像 shell 那样执行。HTTP 请求会正确处理引号,因此-H "Authorization: Bearer …"可以使用。 - 重定向会被删除而不是被拒绝:
> /dev/null、2>/dev/null、&> /dev/null和2>&1在检查前被移除,因此从 crontab 复制的命令行可以直接使用。 - 最多 4096 个字符。
$ sh0 cron create --app my-api --name cleanup --schedule "0 3 * * *" --command "env | grep X"
Error: Invalid command: Command contains forbidden character '|'. Use simple commands without shell operators. (VALIDATION_ERROR)需要数据库或机密的任务
绑定到应用的任务能看到应用的变量并解析其项目的内部名称,因此像 python manage.py cleanup 这样的命令会读取相同的 DATABASE_URL 并访问相同的 db.internal。如果工作应在正在运行的应用内完成,还有两种方式:
- HTTP 端点。把任务暴露为应用的一个路由,用令牌保护,让定时任务通过内部名称调用它。工作在正在运行的应用内执行,使用其数据库连接和密钥。
- 或在应用内部调度,使用框架自带的调度器(例如 Celery beat、node-cron 或 Laravel 调度器),适用于任务完全不应通过 HTTP 访问的情况。
curl -s -X POST -H "Authorization: Bearer <token>" http://my-api.internal:3000/internal/cleanup Note
sh0 从服务器发送请求,并仅在任务所属项目中正在运行的服务里解析
my-api.internal(或 my-api)。找不到对应运行中服务的名称会以明确的消息失败;不属于任何项目或运行在远程节点上的应用,必须通过其公共 URL 调用。令牌以明文写在任务命令中,任何能查看该任务的人都能看到:不要把它用于其他用途。Cron 表达式语法
sh0 使用标准的 5 字段 cron 表达式,每个字段代表一个时间单位:
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday = 0)
│ │ │ │ │
* * * * *| 符号 | 含义 | 示例 |
|---|---|---|
| * | 所有值 | * * * * * = 每分钟 |
| , | 值列表 | 0 8,12,18 * * * = 上午 8 点、中午、下午 6 点 |
| - | 范围 | 0 9-17 * * * = 上午 9 点到下午 5 点每小时 |
| / | 步长 | */15 * * * * = 每 15 分钟 |
常见模式
# Every minute
* * * * *
# Every 5 minutes
*/5 * * * *
# Every hour at minute 0
0 * * * *
# Every day at midnight
0 0 * * *
# Every day at 3:30 AM
30 3 * * *
# Every Monday at 9:00 AM
0 9 * * 1
# First day of every month at midnight
0 0 1 * *
# Every weekday (Mon-Fri) at 6:00 AM
0 6 * * 1-5 Note
计划按 UTC 计算,与服务器时区无关。
0 3 * * * 在 UTC 03:00 运行。调度器每 60 秒检查一次到期任务,因此执行最多可能比预定时间晚一分钟开始。执行历史与日志
每次执行都会记录状态(success、failed 或 timeout)、退出码、耗时、开始和结束时间以及输出。在控制台中,打开任务的 Execution History,然后点击某次执行的 View output。使用 CLI:sh0 cron runs <id>。
Note
sh0 为每个任务保留最近 100 次执行,更早的记录会被删除。标准输出和错误输出各最多保留 64 KB。
启用和禁用任务
- Disable 停止计划执行,但不删除任务及其历史;Enable 恢复执行。
- Trigger Now(或
sh0 cron trigger <id>)立即执行一次,不受计划限制。 - 删除任务(
sh0 cron delete <id>)会同时删除其执行历史。
超时、重叠与限制
- 超时 -- 默认 300 秒(CLI 中为
--timeout)。超时的执行记为timeout状态,并附带消息 “Job timed out after Ns”。 - 重叠 -- 某个任务的一次执行尚未结束时,调度器不会再启动新的执行。被跳过的那一次不会记录在历史中。
- 每个应用最多 50 个任务。
- 没有重试,也没有失败通知。失败的执行不会重试,也不会发送告警:请查看执行历史,或让任务调用的端点自行报告失败。