<p>纯工作日执行用0 2 1-5且第3字段为,周末用0 3 6,0;需日期与星期双重校验时在命令前加[ $(date +\%u) -le 5 ] &&等shell判断,或利用/etc/cron.目录配合脚本内逻辑分流。</p>

要让 crontab 区分工作日和非工作日执行不同维护任务,核心在于理解它的时间字段逻辑,并避开“日期 OR 星期”触发陷阱。它本身不直接支持“仅工作日”或“仅周末”这类语义,但可以通过组合字段、辅助判断或目录机制实现稳定可靠的差异化调度。
明确工作日与非工作日的 crontab 表达式写法
crontab 的 日期(day-of-month) 和 星期(day-of-week) 是“或”关系:只要任一条件匹配,任务就执行。因此不能简单写成 0 2 * * 1-5 就认为只在工作日运行——如果某月 1 号恰好是周日,0 2 1 * * 这部分也会触发。
安全做法是:只保留你需要的维度,另一维设为 *,并确保不填具体数字。
-
纯工作日(周一至周五)执行:用
0 2 * * 1-5,同时确保第 3 字段(日期)是*,不要写成0 2 1-31 * 1-5 -
纯周末(周六、周日)执行:用
0 3 * * 6,0或0 3 * * 6,7(0 和 7 都代表周日) -
每月 1 号且必须是工作日才执行:需二次判断,例如:
0 4 1 * * [ $(date +\%u) -le 5 ] && /path/to/backup.sh
其中%u输出 1~7(周一=1,周日=7),-le 5表示仅限周一到周五
用系统级 cron 目录实现免编辑、易维护的分类调度
/etc/cron.weekly、/etc/cron.daily 等目录由系统级 cron 守护进程自动调用,它们本身不区分工作日,但你可以把脚本放入对应目录,并在脚本开头加判断逻辑,比在 crontab 里硬编码更清晰、更利于版本管理。
- 将工作日专用脚本(如数据库健康检查)放入
/etc/cron.hourly/check-db-hourly,并在脚本第一行加:#!/bin/bash<br>[ $(date +\%u) -gt 5 ] && exit 0 # 周六/日跳过
- 将周末专用任务(如全量备份、磁盘深度扫描)放在
/etc/cron.weekly/weekend-maintenance,开头加:[ $(date +\%u) -ne 6 ] && [ $(date +\%u) -ne 7 ] && exit 0 - 所有脚本需有可执行权限:
chmod +x /etc/cron.weekly/weekend-maintenance
结合 shell 判断实现“第 N 个工作日”等高级需求
标准 crontab 不支持“每月第二个工作日”这种表达,但可通过一行命令完成:
-
每月第二个工作日早上 9 点执行报表生成:
0 9 1-7 * * [ $(date +\%u) -eq 1 ] && [ $(date +\%d) -le 7 ] && /opt/scripts/generate-report.sh
原理:每周一是 %u=1;若当天是 1–7 号之间的周一,大概率就是当月第 1 或第 2 个周一(再加一行校验可更准) - 更稳健方案:写一个封装脚本
/opt/bin/weekday-runner.sh,接收参数如2nd-mon,内部用cal或ncal计算真实日期,再决定是否执行后续命令
避免常见陷阱的实操建议
企业环境对稳定性要求高,几个细节必须注意:
- 所有路径写绝对路径:
/usr/bin/python3 /opt/jobs/clean-temp.py,不要用python3 clean-temp.py - 重定向输出,防止邮件堆积或丢失日志:
0 2 * * 1-5 /opt/scripts/backup.sh >> /var/log/backup.log 2>&1 - 测试时先用
date -d "tomorrow 02:00"模拟时间,再手动运行命令验证逻辑 - 修改后务必 reload cron:
sudo systemctl reload cron(Debian/Ubuntu)或sudo systemctl reload crond(RHEL/CentOS)

















