这类问题我又碰上了一次。CentOS 7.9 上同一个备份脚本手工执行正常,放进 crontab 后每天报 /bin/sh: source: command not found,脚本第一行写的是 source /etc/profile,日志里连环境变量都没加载。

第一反应是「crontab 里没有设 SHELL=/bin/bash」,验证下来不成立。

真正麻烦的地方在于,几个原因的现象几乎一样。cron 默认用 /bin/sh,而 /bin/sh 可能指向 dash 或精简 bash;source 是 bash 内建,sh 下要用点号加载;脚本没有 shebang,执行时完全依赖 cron 的默认解释器。

上来先确认 cron 用的解释器和环境

crontab -l | head -20 && ls -l /bin/sh

接着在 crontab 顶部显式指定 SHELL 和 PATH

printf 'SHELL=/bin/bash\nPATH=/usr/local/bin:/usr/bin:/bin\n' | crontab -

然后把 source 改成 sh 兼容的点号写法

sed -i 's#^source #. #' /opt/scripts/backup.sh

末了用干净环境模拟 cron 执行一次

env -i /bin/sh -c '/opt/scripts/backup.sh'

改之前先确认了最近有没有人动过配置,避免白查一遍。

这次没动代码,只在配置和运行环境上找原因。

隔了一天再看,现象没变,说明不是偶发。

改完先别撤,确认这几项。脚本在 env -i 下能跑通,下一次 cron 执行日志里没有 source: not found,备份文件正常生成。

cron 的环境变量只有极少几个,PATH 和 SHELL 最好写在 crontab 顶部,别依赖登录 shell 的 profile。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189