这类问题我又碰上了一次。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。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
