crontab 定时任务不执行的六个原因

举报
yd_284037603 发表于 2026/11/07 19:32:31 2026/11/07
【摘要】 先说在前面「脚本手动跑得好好的,放进 crontab 就不动」几乎是每个运维都遇到过的事。crontab 和交互式 shell 的差别不在语法,而在运行环境:它不读你的登录配置、没有终端、工作目录也不是你以为的那个。下面六个原因按出现频率排,每条都给一条能立刻验证的命令。1. PATH 和环境变量几乎全是空的cron 只给一个极简环境,通常是 PATH=/usr/bin:/bin,不会加载 ...

先说在前面


「脚本手动跑得好好的,放进 crontab 就不动」几乎是每个运维都遇到过的事。crontab 和交互式 shell 的差别不在语法,而在运行环境:它不读你的登录配置、没有终端、工作目录也不是你以为的那个。下面六个原因按出现频率排,每条都给一条能立刻验证的命令。1. PATH 和环境变量几乎全是空的


cron 只给一个极简环境,通常是 PATH=/usr/bin:/bin,不会加载 ~/.bashrc、/etc/profile,也没有你在 shell 里 export 的那些变量。于是 python3、node、docker 或 conda 里的命令全部「command not found」,而 crontab 默认又不把错误显示给你。


    * * * * * env > /tmp/cron-env.txt 2>&1

    cat /tmp/cron-env.txt


修法有三:命令一律写绝对路径(/usr/bin/python3);在 crontab 顶部显式写 PATH=/usr/local/bin:/usr/bin:/bin;或者让脚本自己 source 需要的配置。最稳的是第一种。


2. 相对路径和工作目录不对


cron 执行时的当前目录是用户家目录(或 /,取决于实现),不是脚本所在目录。脚本里写 ./config.yaml、open('data/log.txt') 就会找不到文件,或者悄悄写到了别的地方。


    */5 * * * * cd /opt/app && /usr/bin/python3 /opt/app/backup.py >> /var/log/backup.log 2>&1


顺便说一句:脚本里用 Path(__file__).parent 而不是 os.getcwd() 定位资3. 命令里的 % 没转义


这是最容易莫名其妙的一条:crontab 中未转义的 % 会被解释成换行,后面的内容当作标准输入传给命令。所以带日期的命令经常只执行了半截。


    0 2 * * * /usr/bin/mysqldump db > /backup/db_$(date +%Y%m%d).sql

    0 2 * * * /usr/bin/mysqldump db > /backup/db_$(date +\%Y\%m\%d).sql


更省心的做法是把整段逻辑写进 shell 脚本,crontab 里只留一行脚本路径,这样 crontab 的语法规则就不会干扰脚本内容。


4. 输出被吞掉,失败也没人知道


cron 没有终端,标准输出和错误要么丢掉、要么尝试发给本地邮件(大多数机器上根本没配 MTA)。所以「没执行」和「执行了但报错」看起来一模一样。


    MAILTO=""

    0 3 * * * /opt/app/job.sh >> /var/log/job.log 2>&1

    0 3 * * * /opt/app/job.sh >> /var/log/job.log 2>> /var/log/job.err


调试期还可以直接看系统日志确认「调度到底有没有触发」:grep CRON /var/log/syslog(Debian/Ubuntu)或 grep CROND /var/log/cron(RHEL 系)。日志里有 CRON 行就说明调度正常,问题在脚本内部;连行都没有,才是表达式5. 时区改了,cron 还按老时间跑


改系统时区后如果没重启 cron 守护进程,它仍按启动时读到的时区调度,表现是「任务晚八小时执行」。容器里更常见:镜像默认 UTC,业务按北京时间写表达式。


    timedatectl

    systemctl restart cron

    CRON_TZ=Asia/Shanghai

    0 9 * * * /opt/app/daily.sh


另外注意「每月 1 日 02:30」这类任务在夏令时切换时可能执行两次或跳过一次,能避开就避开。


6. 文件本身的小毛病


几类低级但高频的问题:脚本没有执行位(chmod +x)、从 Windows 拷过来带 CRLF(file job.sh 能看到,dos2unix 修)、crontab 文件最后一行没有换行符(最后一条任务不会被读取)、shebang 写错或用了不存在的解释器路径。还有一条容易忽略:/etc/cron.d/ 下的文件要求属主是 root 且权限不能组/其他可写,否则 cron 会直接忽略并在日志里留一行 WRONG FILE OWNER 或 BAD FILE MODE。


小结:一条最短的排查顺序


先 grep CRON /var/log/syslog 确认调度有没有触发 → 用 env > /tmp/cron-env.txt 看真实环境 → 把所有路径和命令换成绝对路径 → 给命令加 >> log 2>&1 让错误现身 → 再检查 % 转义、时区、脚本换行符和执行位。绝大多数「crontab 不执行」都能在这五步里定位。还有个一劳永逸的习惯:crontab 里永远只放一行调用脚本的路径,把复杂逻辑都放进脚本,环境、日志、错误处理都在脚本里自己管。

或 cron 服务本身的问题。


源,从一开始就避开这个坑。





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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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