脚本在终端能运行但crontab不执行,90%是环境差异所致:crond使用极简shell环境,不加载.bashrc、path窄(仅/usr/bin:/bin)、home和shell与登录态不同;需确认crond服务运行、任务正确加载、显式设置path/shell/home、用绝对路径、添加日志重定向并对比env输出。

脚本在终端能跑,放进 crontab 却没动静——这不是脚本问题,而是 cron 的执行环境和你想象的不一样。排查核心就三件事:服务有没有在跑、任务有没有真写进去、环境跟不跟得上。
确认 crond 服务正在运行
所有定时任务都靠它撑着。服务停了,再对的配置也白搭。
- 查状态:sudo systemctl status cron(Ubuntu/Debian)或 sudo systemctl status crond(CentOS/RHEL)
- 如果显示 inactive,就启动它:sudo systemctl start cron
- 顺手设为开机自启:sudo systemctl enable cron
验证任务已生效且语法无误
编辑完没保存、格式错一位、行尾多空格,都会让 cron 直接跳过整行。
- 用 crontab -l 看一眼,确认那行任务真出现在列表里
- 核对五段时间字段顺序:分、时、日、月、周(比如 0 3 * * 1 是每周一凌晨 3 点)
- 避免把 # 写在时间字段后面——整行会被当注释忽略
- 用 crontab.guru 粘贴表达式,看它理解得对不对
重点检查环境与路径
这是最常出问题的地方。cron 默认只认 /usr/bin:/bin,不读你的 .bashrc,也不懂 ~ 是谁。
- 在 crontab 文件开头显式声明变量:
PATH=/usr/local/bin:/usr/bin:/bin:/home/username/.local/bin
SHELL=/bin/bash
HOME=/home/username - 脚本里所有命令都用绝对路径,比如 /usr/bin/python3 而不是 python3
- 脚本第一行加 #!/bin/bash,开头加上 cd "$(dirname "$0")" || exit 1,避免相对路径失效
- 临时加一行测试环境:* * * * * env > /tmp/cron_env.txt 2>&1,等一分钟再 cat /tmp/cron_env.txt,对比你手动运行 env 的输出
加日志重定向,别靠猜
没有日志,等于闭眼排错。stdout 和 stderr 都要抓,否则报错你看不到。
- 给任务加完整重定向:0 2 * * * /path/to/script.sh >> /var/log/myjob.log 2>&1
- 注意顺序:2>&1 必须写在 > 或 >> 后面,否则无效
- 查系统级日志:
Ubuntu/Debian:sudo grep CRON /var/log/syslog | tail -20
CentOS/RHEL:sudo journalctl -u crond -n 30 --no-pager - 别忘了 cron 默认会发邮件到 /var/spool/mail/$USER,有时关键错误就藏在里面











