Linux cron 时间格式怎么写?常用命令和最佳实践有哪些?
cron 是什么,适合解决什么问题?
cron 是 Linux/Unix 系统里最常见的定时任务工具,适合做周期性、可重复、对秒级精度要求不高的任务,比如清理日志、备份文件、同步数据、定时拉取接口、跑统计脚本。
它的特点是简单、稳定、系统内置;缺点是默认环境变量很少、日志不集中、任务错过后通常不会自动补跑。所以写 cron 任务时,不只要会写时间表达式,还要处理路径、日志、锁、时区和失败通知。
cron 时间格式怎么写?
普通用户的 crontab 通常是 5 个时间字段加一条命令:
bash* * * * * command # 分 时 日 月 周 命令
常见例子:
bash30 2 * * * /usr/local/bin/backup.sh # 每天 2:30 */5 * * * * /usr/local/bin/check.sh # 每 5 分钟 0 9 * * 1 /usr/local/bin/weekly-report.sh # 每周一 9 点
常用符号包括:* 任意值,, 多个值,- 范围,/ 步长。
日期和星期同时写时有什么坑?
在很多 cron 实现里,日期字段 day-of-month 和星期字段 day-of-week 如果同时被限制,通常是“或”的关系,不是“且”的关系”。
bash0 9 1 * 1 /usr/local/bin/job.sh
很多人以为它表示“每月 1 号且是周一的 9 点执行”。实际上通常表示每月 1 号 9 点执行,周一 9 点也执行。如果真的要表达“每月 1 号并且是周一”,建议在脚本里再判断一次。
crontab 常用命令有哪些?
bashcrontab -e # 编辑当前用户任务 crontab -l # 查看当前用户任务 crontab -r # 删除当前用户所有任务 sudo crontab -u nginx -e sudo crontab -u nginx -l
编辑前建议先备份:
bashcrontab -l > ~/crontab.bak
用户 crontab 的格式是 * * * * * command;/etc/crontab 和 /etc/cron.d/ 里的格式通常多一个运行用户字段:* * * * * user command。不要混用。
cron 的环境变量为什么经常出问题?
cron 执行命令时,不会加载完整交互式 shell 环境。建议在 crontab 顶部显式写清楚:
bashSHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin MAILTO=admin@example.com
命令和脚本尽量用绝对路径,需要进入项目目录时显式 cd。
bash*/10 * * * * cd /data/app && /usr/bin/python3 scripts/sync.py >> /var/log/sync.log 2>&1
日志和防重入怎么做?
cron 自身日志位置和发行版有关:Debian/Ubuntu 常见 grep CRON /var/log/syslog,RHEL/CentOS 常见 grep CRON /var/log/cron,systemd 系统也可以看 journalctl -u cron 或 journalctl -u crond。
生产环境建议自己重定向日志:
bash0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
如果任务执行时间比调度间隔还长,会出现多个实例同时运行。最简单可靠的办法是用 flock 加锁:
bash*/5 * * * * flock -n /var/lock/sync.lock /usr/local/bin/sync.sh >> /var/log/sync.log 2>&1
cron 和时区有什么关系?
cron 按系统时区执行。先确认服务器时区:
bashdate timedatectl
部分 cron 实现支持在 crontab 中设置 CRON_TZ:
bashCRON_TZ=Asia/Shanghai 0 9 * * * /usr/local/bin/report.sh
跨地区部署时,最好把服务器时区、业务时区和任务说明写清楚。对账、结算、计费这类任务,还要做幂等和日期校验,不要只相信 cron 调度。
anacron 和 systemd timer 怎么选?
cron 假设机器一直开着。如果电脑或服务器在计划时间关机,任务通常就错过了。anacron 适合每天、每周、每月这类低频任务,错过后下次开机补跑。
systemd timer 更适合生产服务化任务,它日志进 journald,可声明用户、工作目录、依赖和错过补跑。一个 timer 通常由 .service 和 .timer 两个文件组成。
ini# /etc/systemd/system/report.timer [Timer] OnCalendar=*-*-* 02:30:00 Persistent=true
启用:
bashsudo systemctl daemon-reload sudo systemctl enable --now report.timer systemctl list-timers journalctl -u report.service
简单任务用 cron,生产任务需要状态、日志、依赖、告警时优先考虑 systemd timer。
cron 最佳实践清单
使用绝对路径;显式设置 SHELL 和 PATH;保存日志;用 flock 防重入;脚本要幂等;区分用户 crontab 和系统 cron;注意日期和星期字段的“或”关系;确认时区;复杂逻辑写进脚本;关键任务配置告警。
cron 本身不复杂,真正让任务稳定的是这些细节:命令能不能找到,失败能不能看见,重复执行会不会出事,时间是不是你以为的那个时间。