OpenUptime

Cron expression explainer

Paste a crontab schedule to read it in plain words, see when it runs next in UTC or your time zone, and get heartbeat settings that alert you when a run goes missing.

cron 表达式解析

粘贴 crontab 时间表达式,用通俗的话读懂它,查看它接下来在 UTC 或你所在时区的运行时间,并得到在任务漏跑时提醒你的心跳监控设置。

Cron expressioncron 表达式

At 02:30.每天 02:30

Minute分钟303030
Hour小时222 点
Day of month日期*every day每天
Month月份*every month每个月
Day of week星期*every day每天

Next runs接下来的运行时间

  1. –

Heartbeat settings for this schedule适合这个时间表的心跳设置

Period周期––
Grace宽限期––

Cron syntax

A cron expression has five fields separated by spaces. In a crontab file the command follows them on the same line.

┌──────── minute (0–59)
│ ┌────── hour (0–23)
│ │ ┌──── day of month (1–31)
│ │ │ ┌── month (1–12 or JAN–DEC)
│ │ │ │ ┌ day of week (0–7 or SUN–SAT, 0 and 7 are Sunday)
│ │ │ │ │
* * * * * command
FieldValues
Minute0–59
Hour0–23
Day of month1–31
Month1–12
Day of week0–7
SymbolMeaningExample
*Any value* * * * *
,A list of values0 8,12,18 * * *
-A range, both ends included0 9-17 * * *
/A step through a range or **/15 * * * *
JAN–DECMonth names, any case0 0 1 JAN,JUL *
SUN–SATDay names; 0 and 7 are both Sunday0 9 * * MON-FRI

Shorthands

Most cron implementations accept these in place of the five fields:

ExpressionSame asMeaning
@hourly0 * * * *Start of every hour
@daily, @midnight0 0 * * *Every day at 00:00
@weekly0 0 * * 0Sunday at 00:00
@monthly0 0 1 * *First day of the month at 00:00
@yearly, @annually0 0 1 1 *1 January at 00:00
@reboot–Once, when the cron daemon starts

Common schedules

ExpressionMeaning
* * * * *Every minute
*/5 * * * *Every 5 minutes
*/15 * * * *Every 15 minutes
0 * * * *At the start of every hour
0 */6 * * *Every 6 hours, at 00:00, 06:00, 12:00 and 18:00
0 0 * * *Every day at midnight
30 2 * * *Every day at 02:30
0 9 * * 1-5Weekdays at 09:00
0 9-17 * * 1-5Every hour from 09:00 to 17:00 on weekdays
*/10 9-17 * * 1-5Every 10 minutes during working hours
0 0 * * 0Every Sunday at midnight
0 8 * * 6,0Saturdays and Sundays at 08:00
0 0 1 * *The first day of every month
0 0 1,15 * *The 1st and the 15th of every month
0 0 1 */3 *The first day of every quarter
0 0 1 1 *Once a year, on 1 January

Mistakes that catch people out

  • Day of month or day of week: When both fields are restricted, a day that matches either one runs. 0 0 13 * 5 runs on every 13th and every Friday. To run only on Friday the 13th, schedule every Friday and check the date in the script.
  • Steps restart every hour: */7 in the minute field runs at 0, 7 … 56 and again at 0, so the last gap of each hour is 4 minutes. The tool shows the shortest and longest gap for every schedule.
  • Which time zone: Cron uses the time zone of the machine or of the scheduler, which is often UTC on servers and in containers. Check it before you pick an hour.
  • Daylight saving time: When clocks change, a job in the skipped hour can run late or not at all, and one in the repeated hour can run twice, depending on the implementation. Schedule in UTC, or keep daily jobs out of 01:00 to 03:00 local time.
  • The crontab line itself: Cron starts jobs with a short PATH and few environment variables, so use full paths. An unescaped % in the command is read as a new line; write \%.

Cron in other schedulers

  • Kubernetes CronJob: Uses these five fields and the shorthands. Set spec.timeZone to a name such as Europe/Berlin; without it the schedule follows the time zone of the controller manager.
  • GitHub Actions: on.schedule uses these five fields in UTC. The shortest interval is every 5 minutes, and runs can start late when GitHub is busy.
  • Quartz and Spring: Add a seconds field at the start (and Quartz an optional year at the end), need ? in one of the two day fields, and support L, W and #. In Quartz, day of week 1 is Sunday.
  • AWS EventBridge: Writes cron(minutes hours day-of-month month day-of-week year) with six fields, needs ? in one day field and counts days of the week from 1 for Sunday.

This tool reads the standard five fields and explains what to change when you paste a Quartz or AWS schedule.

Know when a scheduled job did not run

Cron does not report a job that was skipped, hung or failed. A heartbeat monitor turns that silence into an alert: the job calls a URL each time it finishes, and you are notified when a call does not arrive within the period plus the grace time.

Heartbeat monitors on OpenUptime accept a period from 30 seconds to 24 hours, the shortest your plan allows (5 minutes on Free, 1 minute on Lite and Starter, 30 seconds on Team), and up to 24 hours of grace. Pings do not use check credits.

0 9 * * 1-5 /usr/local/bin/report.sh && curl -fsS -m 10 --retry 3 https://openuptime.app/api/heartbeat/<token> > /dev/null

Questions

What does */5 * * * * mean?

Every 5 minutes: at minute 0, 5, 10 and so on up to 55, every hour of every day.

How do I run a cron job every weekday at 9 a.m.?

Use 0 9 * * 1-5: minute 0, hour 9, any day of the month, any month, Monday through Friday. Cron reads the hour in the server's time zone unless the scheduler lets you set one.

Why does my job run on more days than I expected?

When you restrict both the day of month and the day of week, cron runs on days that match either one. 0 0 13 * 5 runs on every 13th and on every Friday, not only on Friday the 13th.

Is Sunday 0 or 7?

Both, in standard cron. Quartz and AWS count 1 to 7 starting from Sunday, so 1 means Sunday there and Monday in crontab.

Can cron run a job every 30 seconds?

No. The smallest unit of standard cron is a minute. Use two entries with sleep 30 in one of them, a systemd timer, or a scheduler with a seconds field.

Why does */7 in the minute field not run every 7 minutes?

A step counts within the field, so */7 means minutes 0, 7, 14 … 56 and then 0 again at the next hour, a gap of 4 minutes. Only steps that divide 60 (or 24 for hours) are even.

How do I know a cron job actually ran?

Cron does not tell you when a job is skipped or fails. Have the job call a heartbeat URL when it finishes, and get alerted when the call does not arrive within the expected period plus a grace period.

cron 语法

cron 表达式由空格分隔的五个字段组成。在 crontab 文件里,要执行的命令写在同一行的后面。

┌──────── 分钟(0–59)
│ ┌────── 小时(0–23)
│ │ ┌──── 日期(1–31)
│ │ │ ┌── 月份(1–12 或 JAN–DEC)
│ │ │ │ ┌ 星期(0–7 或 SUN–SAT,0 和 7 都是周日)
│ │ │ │ │
* * * * * 命令
字段取值
分钟0–59
小时0–23
日期1–31
月份1–12
星期0–7
符号含义示例
*任意值* * * * *
,列出多个值0 8,12,18 * * *
-范围,包含两端0 9-17 * * *
/在范围或 * 中按步长取值*/15 * * * *
JAN–DEC月份英文缩写,不区分大小写0 0 1 JAN,JUL *
SUN–SAT星期英文缩写;0 和 7 都是周日0 9 * * MON-FRI

简写

大多数 cron 实现都接受用下面的简写代替五个字段:

表达式等同于含义
@hourly0 * * * *每小时整点
@daily, @midnight0 0 * * *每天 00:00
@weekly0 0 * * 0周日 00:00
@monthly0 0 1 * *每月 1 日 00:00
@yearly, @annually0 0 1 1 *1 月 1 日 00:00
@reboot–cron 服务启动时运行一次

常用时间表

表达式含义
* * * * *每分钟
*/5 * * * *每 5 分钟
*/15 * * * *每 15 分钟
0 * * * *每小时整点
0 */6 * * *每 6 小时,在 00:00、06:00、12:00 和 18:00
0 0 * * *每天午夜
30 2 * * *每天 02:30
0 9 * * 1-5工作日 09:00
0 9-17 * * 1-5工作日 09:00 至 17:00 每小时整点
*/10 9-17 * * 1-5工作时间内每 10 分钟
0 0 * * 0每周日午夜
0 8 * * 6,0每周六和周日 08:00
0 0 1 * *每月 1 日
0 0 1,15 * *每月 1 日和 15 日
0 0 1 */3 *每季度第一天
0 0 1 1 *每年 1 月 1 日

容易踩的坑

  • 日期和星期是“或”的关系: 同时限制这两个字段时,满足任意一个的日子都会运行。0 0 13 * 5 会在每月 13 日和每个周五运行。如果只想在“13 号星期五”运行,就安排在每个周五,再在脚本里判断日期。
  • 步长每小时重新开始: 分钟字段写 */7 会在第 0、7……56 分钟运行,然后又从 0 开始,所以每小时最后一段间隔只有 4 分钟。本工具会显示每个时间表的最短和最长间隔。
  • 用的是哪个时区: cron 使用机器或调度器的时区,服务器和容器里通常是 UTC。选定小时之前先确认时区。
  • 夏令时: 时钟调整时,被跳过的那一小时里的任务可能延后或不运行,重复的那一小时里的任务可能运行两次,具体取决于实现。用 UTC 安排,或者让每天的任务避开当地时间 01:00 到 03:00。
  • crontab 这一行本身: cron 启动任务时 PATH 很短、环境变量很少,所以请使用完整路径。命令里未转义的 % 会被当成换行,要写成 \%。

其他调度器里的 cron

  • Kubernetes CronJob: 使用同样的五个字段和简写。可以把 spec.timeZone 设为 Asia/Shanghai 这样的时区名;不设置时按 controller manager 的时区执行。
  • GitHub Actions: on.schedule 使用这五个字段,按 UTC 执行。最短间隔是 5 分钟,GitHub 繁忙时运行可能会延迟。
  • Quartz 和 Spring: 开头多一个秒字段(Quartz 末尾还可以有年份),两个日期字段中必须有一个写 ?,并支持 L、W 和 #。在 Quartz 中,星期的 1 表示周日。
  • AWS EventBridge: 写成 cron(分钟 小时 日期 月份 星期 年份) 共六个字段,一个日期字段必须写 ?,星期从 1 表示周日开始计数。

本工具读取标准的五个字段;粘贴 Quartz 或 AWS 的表达式时,会提示需要改哪里。

定时任务没运行时及时知道

cron 不会报告被跳过、卡住或失败的任务。心跳监控把这种“没有动静”变成告警:任务每次完成时请求一个 URL,如果在周期加宽限期内没有收到请求,你就会收到通知。

OpenUptime 的心跳监控支持 30 秒到 24 小时的周期,最短周期取决于套餐(Free 5 分钟,Lite 和 Starter 1 分钟,Team 30 秒),宽限期最长 24 小时。心跳请求不消耗检查额度。

0 9 * * 1-5 /usr/local/bin/report.sh && curl -fsS -m 10 --retry 3 https://openuptime.app/api/heartbeat/<token> > /dev/null

常见问题

*/5 * * * * 是什么意思?

每 5 分钟运行一次:每天每小时的第 0、5、10……55 分钟。

怎样让定时任务在每个工作日早上 9 点运行?

使用 0 9 * * 1-5:第 0 分钟、9 点、每月任意一天、任意月份、周一至周五。除非调度器允许设置时区,cron 会按服务器的时区理解这个小时。

为什么任务运行的天数比预期多?

如果同时限制了日期和星期,cron 会在满足其中任意一个的日子运行。0 0 13 * 5 会在每月 13 日和每个周五运行,而不只是“13 号星期五”。

周日是 0 还是 7?

在标准 cron 中两者都表示周日。Quartz 和 AWS 用 1 到 7 表示周日到周六,所以 1 在那里是周日,在 crontab 里却是周一。

cron 能每 30 秒运行一次吗?

不能。标准 cron 的最小单位是分钟。可以写两条任务并在其中一条里先 sleep 30,或者改用 systemd timer,或使用带秒字段的调度器。

为什么分钟字段写 */7 并不是每 7 分钟一次?

步长只在字段的范围内计算,所以 */7 表示第 0、7、14……56 分钟,到下一个小时又从 0 开始,中间只隔 4 分钟。只有能整除 60(小时字段为 24)的步长才是均匀的。

怎样确认定时任务真的运行了?

cron 不会告诉你任务被跳过或失败了。让任务在完成时请求一个心跳 URL,如果在预期周期加宽限期内没有收到请求,就会收到告警。