掌握Cron表达式

Cron表达式详解

Cron表达式是一种用于配置定时任务的字符串,广泛应用于Linux、Unix系统中的cron服务以及Java的Quartz调度器等。它允许用户以高度灵活的方式定义任务执行的时间。

一个Cron表达式由7个字段组成,每个字段代表一个时间单位。这7个字段从左到右依次是:

  • 秒 (Seconds):允许值范围 0-59

  • 分 (Minutes):允许值范围 0-59

  • 时 (Hours):允许值范围 0-23

  • 日 (Day-of-month):允许值范围 1-31

  • 月 (Month):允许值范围 1-12 或 JAN-DEC

  • 周 (Day-of-week):允许值范围 0-6 (0或7表示周日,1-6表示周一到周六) 或 SUN-SAT

  • 年 (Year):允许值范围 1970-2099 (这个字段是可选的,有些系统或版本可能不包含它)

特殊字符

Cron表达式支持多种特殊字符,以提供更复杂的调度规则:

    • (星号):表示“每”个时间单位。例如,在分钟字段使用 * 表示每分钟。
  • ? (问号):仅用于日 (Day-of-month) 和周 (Day-of-week) 字段,表示不指定。当你需要在两者之一指定值,而不想影响另一个时使用。例如,如果想在每月的10号执行,而不管这天是周几,就可以在周字段使用 ?。

    • (连字符):表示范围。例如,在小时字段使用 9-17 表示上午9点到下午5点。
  • , (逗号):表示列表值。例如,在分钟字段使用 0,15,30,45 表示在每个小时的0、15、30和45分执行。

  • / (斜杠):表示增量。例如,在分钟字段使用 0/5 表示从第0分钟开始,每5分钟执行一次。

  • L (字母L):

    • 在日 (Day-of-month) 字段,表示月的最后一天。例如,L 表示31号(对于1、3、5、7、8、10、12月),28号(对于2月),等等。

    • 在周 (Day-of-week) 字段,表示星期的最后一天(周六)。例如,6L 或 SATL 表示最后一个周六。

  • W (字母W):表示最近的工作日 (Weekday)。仅用于日 (Day-of-month) 字段。例如,如果指定 15W,表示离每月15号最近的工作日执行。如果15号是周六,则在14号(周五)执行;如果15号是周日,则在16号(周一)执行;如果15号是工作日,则在15号执行。

  • (井号):仅用于周 (Day-of-week) 字段,表示该月的第几个周几。例如,6#3 或 FRI#3 表示该月的第三个周五。

示例

以下是一些常见的Cron表达式示例:

  • 0 0 12 * * ?:每天中午12点触发。

  • 0 15 10 ? * *:每天上午10:15触发。

  • 0 0/5 14,18 * * ?:每天下午2点到2:55,以及下午6点到6:55,每5分钟触发一次。

  • 0 0 10 L * ?:每月最后一天上午10点触发。

  • 0 0 10 ? * 2#3:每月第三个周一上午10点触发。

  • 0 0 0 1 1 ? 2026:在2026年1月1日午夜触发。

注意事项

  • 在大多数Cron实现中,秒字段是强制性的,但在某些早期或简化的版本中可能只有6个字段(不包含秒)。

  • 日 (Day-of-month) 和周 (Day-of-week) 字段不能同时指定具体的数值(除了使用 * 或 ?)。如果其中一个指定了数值,另一个必须使用 ?。

  • 年字段是可选的,如果省略,通常表示每年都执行。

掌握Cron表达式可以让你更灵活地控制任务的执行时机,希望这份详细的解析能帮助你更好地理解和使用它!

Linux系统中的cron服务支持的Cron表达式与Java的Quartz调度器略有不同,主要体现在字段数量和部分特殊字符的用法上。

Linux Cron表达式格式

Linux cron表达式通常由5个字段组成,从左到右依次是:

  • 分钟 (Minute):允许值范围 0-59

  • 小时 (Hour):允许值范围 0-23

  • 日 (Day-of-month):允许值范围 1-31

  • 月 (Month):允许值范围 1-12 或 JAN-DEC

  • 周 (Day-of-week):允许值范围 0-7 (0或7表示周日,1-6表示周一到周六) 或 SUN-SAT

注意:

  • Linux cron 不包含“秒”和“年”字段。 因此,最小的调度单位是分钟。

  • 在crontab文件中,这5个时间字段之后通常跟着要执行的命令。如果是系统级别的crontab文件(如/etc/crontab),还会在命令之前指定执行该命令的用户。

Linux Cron支持的特殊字符

Linux cron支持的特殊字符与通用Cron表达式类似,但有一些细微差别:

    • (星号):表示“每”个时间单位。例如,在分钟字段使用 * 表示每分钟。
    • (连字符):表示范围。例如,在小时字段使用 9-17 表示上午9点到下午5点。
  • , (逗号):表示列表值。例如,在分钟字段使用 0,15,30,45 表示在每个小时的0、15、30和45分执行。

  • / (斜杠):表示增量。例如,在分钟字段使用 */5 表示从第0分钟开始,每5分钟执行一次。也可以与范围结合使用,如 0-10/2 表示在0到10分钟之间,每2分钟执行一次(即0, 2, 4, 6, 8, 10分)。

  • ? (问号):在Linux cron中通常不被广泛支持或以相同的语义支持。在某些特定的cron实现中可能支持,但通常建议避免在Linux crontab中使用它。如果你需要在日 (Day-of-month) 和周 (Day-of-week) 字段中选择一个,另一个通常会使用 * 来表示“不关心”,但这可能导致冲突。

    • 重要提示: 当日 (Day-of-month)和周 (Day-of-week)同时指定具体值时(而非*),cron的执行逻辑是:只要其中一个匹配,命令就会执行。例如,0 0 1 * 5 表示每月1号和每周五都会执行。这与Quartz的 ? 行为(只匹配其中一个,另一个必须是 ?)有显著区别。
  • L (字母L):

    • 在日 (Day-of-month) 字段,表示月的最后一天。

    • 在周 (Day-of-week) 字段,表示星期的最后一天(周六)。

    • 注意: Linux cron对 LW 和 # 等更复杂的字符通常不直接支持。

Linux Cron的特殊字符串(Non-standard)

除了上述表达式外,Linux cron还支持一些方便的特殊字符串,它们是常用时间表达式的简写:

  • @reboot:系统启动时执行一次。

  • @yearly 或 @annually:每年执行一次,等同于 0 0 1 1 * (每年1月1日午夜)。

  • @monthly:每月执行一次,等同于 0 0 1 * * (每月1日午夜)。

  • @weekly:每周执行一次,等同于 0 0 * * 0 (每周日午夜)。

  • @daily 或 @midnight:每天执行一次,等同于 0 0 * * * (每天午夜)。

  • @hourly:每小时执行一次,等同于 0 * * * * (每小时的0分)。

这些特殊字符串可以直接放在crontab条目的时间字段位置,后面跟着要执行的命令。

示例

            • command:每分钟执行 command。
  • 0 */2 * * * command:每两小时执行 command (在0分)。

  • 30 9 * * 1-5 command:周一到周五的上午9:30执行 command。

  • 0 0 1 * * command:每月1日午夜执行 command。

  • 0 18 L * * command:每月最后一天下午6点执行 command。

  • @daily command:每天午夜执行 command。

编辑和查看Cron任务

  • crontab -e:编辑当前用户的crontab文件。第一次使用会让你选择一个编辑器。

  • crontab -l:列出当前用户的crontab任务。

  • crontab -r:删除当前用户的crontab文件(请谨慎使用)。

Linux Cron的额外注意事项

  • 执行环境: cron任务的执行环境可能与你直接在终端中运行命令的环境不同。例如,PATH环境变量可能不完整。因此,最好在命令中指定绝对路径,或者在crontab文件的开头定义PATH等环境变量。

  • 输出重定向: cron任务的任何输出(标准输出和标准错误)都会以邮件的形式发送给执行任务的用户。如果不想收到这些邮件,可以将输出重定向到/dev/null,例如:command > /dev/null 2>&1。

  • 日志: cron的执行日志通常记录在/var/log/syslog或/var/log/cron中(具体取决于Linux发行版),可以通过查看这些日志来调试任务执行问题。

  • 时区: cron任务通常基于系统设置的本地时区执行。

  • 系统级crontab: 除了用户自己的crontab (crontab -e编辑的),还有系统级的crontab文件(如/etc/crontab)以及/etc/cron.d/、/etc/cron.hourly/、/etc/cron.daily/、/etc/cron.weekly/、/etc/cron.monthly/目录,它们用于管理系统级或软件包安装的定时任务。

理解这些差异对于在Linux环境中正确配置和管理定时任务至关重要。