在云服务器上用 crontab 跑备份、清理、同步脚本时,经常遇到“手动执行正常,定时却没跑”或“跑了但结果不对”。本文整理几类最常见的原因和对应的写法。
# 查看当前用户的任务
crontab -l
# 查看 cron 服务状态
systemctl status cron || systemctl status crond
# 查看触发记录(Debian/Ubuntu 在 syslog,CentOS 系在 /var/log/cron)
grep CRON /var/log/syslog | tail日志里有触发记录但没有效果,说明问题在命令本身;完全没有记录,则检查服务是否运行、语法是否正确、文件权限是否合规。
cron 以非交互、非登录的方式执行,环境非常精简,PATH 通常只有 /usr/bin:/bin,不会加载 ~/.bashrc 或 /etc/profile。手动执行能找到的 node、python3、docker,在 cron 里可能找不到。
解决办法:
which 命令 查出。SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin在 crontab 行中,未转义的 % 会被当成换行符,% 之后的内容会作为标准输入传给命令。这会让 date +%F 之类的写法出问题:
# 错误:% 被截断
0 2 * * * tar czf /backup/data-$(date +%F).tar.gz /data
# 正确:转义百分号
0 2 * * * tar czf /backup/data-$(date +\%F).tar.gz /data更省事的办法是把逻辑放进脚本,crontab 里只写脚本路径。
cron 任务默认工作目录是用户家目录,脚本里的相对路径会指向错误位置。在脚本开头 cd 到固定目录,或全部使用绝对路径。
默认情况下 cron 会尝试把输出发邮件,服务器未配置邮件时输出就丢了。建议重定向到日志:
*/5 * * * * /opt/job/sync.sh >> /var/log/sync.log 2>&12>&1 要写在重定向之后,否则错误输出不会进入文件。
上一次还没跑完,下一次又启动,容易造成数据重复处理或资源耗尽。可以用 flock 加非阻塞锁:
*/5 * * * * flock -n /var/lock/sync.lock /opt/job/sync.sh >> /var/log/sync.log 2>&1-n 表示拿不到锁就直接退出。脚本异常退出时锁会随进程结束自动释放,比手写 pid 文件可靠。
timedatectl 确认,不要想当然。* 时,满足任意一个就会触发,而不是同时满足。比如 0 3 1 * 1 表示每月 1 号和每个周一都会运行。crontab -l 与日志确认有触发。% 已转义,或逻辑已移入脚本。flock 防重叠。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。