定时任务又没跑?cron 排错五步

举报
yd_260072176 发表于 2026/11/03 10:58:20 2026/11/03
【摘要】 定时任务又没跑?cron 排错五步rsync 备份脚本,手动跑得好好的;塞进 crontab 每天 2:30 跑,第二天一看,备份目录是空的。脚本没动过,cron 也没见报错——或者报错了,你根本没看见。核心一句话先摆出来:cron 的运行环境和你的登录 shell 是两码事。手动能跑、定时不跑,九成是环境问题,不是脚本问题。 第一步:确认 cron 真的在干活先看服务活没活着:syste...

定时任务又没跑?cron 排错五步

rsync 备份脚本,手动跑得好好的;塞进 crontab 每天 2:30 跑,第二天一看,备份目录是空的。脚本没动过,cron 也没见报错——或者报错了,你根本没看见。

核心一句话先摆出来:cron 的运行环境和你的登录 shell 是两码事。手动能跑、定时不跑,九成是环境问题,不是脚本问题。

第一步:确认 cron 真的在干活

先看服务活没活着:

systemctl status cron        # Debian/Ubuntu 叫 cron
systemctl status crond       # RHEL/CentOS 叫 crond

再看任务有没有被加载:crontab -l 能看到才算数。改完 crontab 不用重启,cron 每分钟自己重读,但语法写错了它可不会提醒你。

最后看它到底触发过没有:

grep CRON /var/log/syslog          # Debian/Ubuntu
grep CRON /var/log/cron            # RHEL/CentOS
# 或者
journalctl -u cron --since "1 hour ago"

日志里出现 (root) CMD (/home/deploy/backup.sh),说明触发了,问题在执行环节;连这行都没有,问题在任务本身没被调度起来。

第二步:环境变量——头号嫌疑人

cron 给任务的环境极简:PATH 通常只有 /usr/bin:/bin,不加载 ~/.bashrc,工作目录是你的家目录。

最经典的死法:脚本里写了 rsync、docker、python3,手动跑时 PATH 里有 /usr/local/bin,cron 里没有 → command not found,任务静默失败。

两种治法,选一种坚持到底:

  1. 脚本里所有外部命令写绝对路径(which rsync 查出来写死);
  2. 或者在 crontab 文件开头声明环境:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
30 2 * * * /home/deploy/backup.sh

顺带:脚本里凡是依赖当前目录的,开头加一行 cd /确定的/目录 || exit 1。

第三步:输出去哪了——没日志等于没排错

cron 默认把任务的输出发邮件给本机用户。服务器上没配 MTA,这些输出直接石沉大海,你看到的只有"没跑"。

铁律:每条定时任务都必须有自己的日志文件:

30 2 * * * /home/deploy/backup.sh >> /var/log/backup.log 2>&1

2>&1 不能省——报错信息走的是 stderr,不加它,恰恰最关键的错误信息丢了。

第四步:% 转义——crontab 专属的坑

crontab 语法里 % 是特殊字符,会被转成换行。于是:

# 错:% 被吃掉,date 命令被拦腰截断
0 2 * * * /bin/date +%F >> /tmp/date.log
# 对:反斜杠转义
0 2 * * * /bin/date +\%F >> /tmp/date.log

这个坑只存在于 crontab 行内——脚本文件里写 date +%F 完全没问题。坑的是把带 % 的命令直接写在 crontab 里的人。

第五步:权限、用户、时区三件套

  • 权限:脚本必须有执行权限(chmod +x),cron 不会帮你补。
  • 用户:crontab -e 是当前用户的任务;/etc/crontab 和 /etc/cron.d/ 是系统任务,必须写用户名那一列(30 2 * * * root /home/deploy/backup.sh),漏了用户整行不生效。
  • 时区:date 看一眼。很多云服务器默认 UTC,你设的"2:30"可能是 UTC 的 2:30,也就是北京时间 10:30。用 timedatectl 确认,时区不对先对时区。

三个真实踩坑

1. 脚本里写了相对路径。 cron 的 HOME 是对的,但"当前工作目录"未必是你想的那个。凡是路径,写绝对的。

2. 任务加到了 root 的 crontab,脚本却在普通用户家目录下,root 读不了。 跨用户调用,先想权限。

3. 用 */5 * * * * 跑一个要 10 分钟的任务。 cron 不管上一次跑完没,到点就起新的,两个实例互相踩。长任务加文件锁(flock -n /tmp/backup.lock),或者换 systemd timer,它有防重叠语义。

什么时候别用 cron

  • 需要失败重试、依赖编排:用 systemd timer + service(Restart= 定向拉起);
  • 秒级调度:cron 最小粒度 1 分钟;
  • 机器会休眠关机:错过的任务 cron 不会补跑。

收尾一句话:cron 只管"到点叫醒",不管"醒来之后世界对不对"。排错按顺序来:服务活着 → 任务被加载 → 环境变量 → 输出日志 → 权限时区。五步走完,定时任务再闹脾气,你至少知道去哪儿找它。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。