定时任务的五个坑:为什么你的 cron 不按点跑

举报
yd_238022924 发表于 2026/11/06 00:16:31 2026/11/06
【摘要】 环境变量、% 转义、静默失败、任务重叠、开机补跑——五个最常见的 cron 问题和对策。

定时任务的五个坑:为什么你的 cron 不按点跑

坑一:环境变量不是你想的那样

手动执行脚本时它能跑,写成定时任务就报“找不到命令”,这是最常见的情况。

原因很简单:cron 执行时用的是最小环境,PATH 通常只有 /usr/bin:/bin,你在 .bashrc 里加的路径它一概不认。

解决办法有两个:要么在脚本里写全绝对路径,要么在脚本开头自己设好环境:

#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

我更推荐第一种——脚本里不依赖任何环境,走到哪都能跑。

坑二:% 在 crontab 里是换行符

这一条坑过无数人。crontab 里 % 有特殊含义,表示换行,后面的内容会被当成标准输入。

所以这行是坏的:

0 3 * * * /usr/bin/date +%F > /tmp/d.log

应该写成:

0 3 * * * /usr/bin/date +\%F > /tmp/d.log

或者干脆把逻辑放进脚本文件,crontab 里只调脚本。后者更省心。

坑三:没有输出,就以为成功了

cron 默认会把输出发邮件,但机器上通常没装邮件服务,或者邮件进了垃圾箱。结果就是:任务失败了,你什么都不知道。

稳妥的做法是每次执行都落日志,并且区分成功失败:

{
  echo "start $(date)"
  /path/to/task.sh
  echo "exit=$? $(date)"
} >> /var/log/mytask.log 2>&1

日志要有轮转,不然迟早把磁盘写满。

坑四:上一轮还没跑完,下一轮又来了

如果一个任务执行时间可能超过调度间隔,就会出现重叠。两个进程同时改同一个文件,轻则数据错乱,重则互相删除。

最简单的防护是加锁:

exec 9>/var/lock/mytask.lock
flock -n 9 || exit 0

-n 表示拿不到锁就立刻退出,不排队。这样同一时刻只有一个实例在跑。

坑五:机器重启后任务补跑

有些实现(比如 anacron)会在开机后补跑错过的任务,但普通 cron 不会——关机期间该跑的任务就直接跳过了。

如果你的任务是“每天必须做一次”,就得自己补:在脚本里记录上次成功时间,启动时检查是否已经超期。

LAST=$(cat /var/lib/mytask.last 2>/dev/null || echo 0)
NOW=$(date +%s)
if [ $((NOW - LAST)) -gt 86400 ]; then
  run_task
fi

一个习惯建议

调试定时任务时,别等真的到点。把时间设成下一分钟,看它到底跑不跑、报什么错,比盯着日志猜快得多。

另外,写完 crontab 记得用 crontab -l 确认真的写进去了——编辑器的保存失败是很常见的。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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