Crontab 任务不执行?90% 的运维都死在这 3 个环境变量坑里
诡异的“消失”现场
你写了一个完美的备份脚本 backup.sh:
#!/bin/bash
# 备份数据库
mysqldump -u root -p123456 dbname > /backup/db.sql
echo "Backup done" >> /tmp/log.txt
手动运行 ./backup.sh,一切正常。
于是你满怀信心地把它加入 Crontab:
0 3 * * * /home/user/backup.sh
第二天早上查看 /backup/db.sql —— 文件不存在。
查看 /tmp/log.txt —— 也没有日志。
你开始怀疑人生:难道是服务器半夜重启了?难道是 Crontab 没启动?
别猜了,90% 的原因都是环境变量问题。
坑一:PATH 变量的“失忆”
当你登录终端(Shell)时,系统会自动加载 /etc/profile、~/.bashrc 等配置文件,你的 PATH 变量里包含了 /usr/local/bin、/usr/bin 等常用路径。
但是,Crontab 执行时的环境是“裸奔”的。
在 Crontab 的执行环境中,PATH 通常只有 /usr/bin:/bin。如果你的 mysqldump 安装在 /usr/local/mysql/bin/mysqldump,脚本执行时就会报错:command not found。
✅ 解决方案
方法一:使用绝对路径(推荐)
在脚本中把所有命令都写成绝对路径:
#!/bin/bash
/usr/local/mysql/bin/mysqldump -u root ...
方法二:手动定义 PATH
在脚本开头重新定义 PATH:
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# 你的业务逻辑
坑二:相对路径的“迷路”
#!/bin/bash
# 错误示范
cat ./config.ini
在 Crontab 中执行时,当前工作目录(CWD)通常是用户的家目录(~),而不是脚本所在的目录。如果你的脚本里用了 ./config.ini,它会去家目录下找,而不是脚本同级目录下找。
✅ 解决方案
在脚本开头先 cd 到脚本所在目录:
#!/bin/bash
cd "$(dirname "$0")" || exit
# 现在可以使用相对路径了
cat ./config.ini
坑三:% 符号的“特殊含义”
你想在 Crontab 里直接写一行命令,带上时间戳:
# 错误示范
* * * * * echo "Run at $(date +%Y-%m-%d)" >> /tmp/cron.log
你会发现命令根本没执行,或者报错。
原因是:在 Crontab 文件中,% 被视为换行符(newline)。 所有 % 后面的内容都会被当作标准输入传给前面的命令。
✅ 解决方案
必须对 % 进行转义:
# 正确示范
* * * * * echo "Run at $(date +\%Y-\%m-\%d)" >> /tmp/cron.log
终极调试大法
如果以上都检查了还是不行,请在 Crontab 条目后面加上这一句:
* * * * * /path/to/script.sh > /tmp/cron_debug.log 2>&1
这会将**标准输出(stdout)和标准错误(stderr)**都重定向到日志文件中。打开日志一看,报错信息通常一目了然。
运维不仅要靠经验,更要靠工具。遇到时间计算问题?试试 本网站的时间戳转换工具,支持秒级/毫秒级转换和时区处理。