为何通过Cron调用AWS CLI命令无效果?S3备份同步故障
看起来你遇到的是典型的Cron环境与交互式Shell环境不一致的问题——手动运行正常但Cron失效,核心原因是Cron的环境变量、配置加载逻辑和你登录后的Shell完全不一样。结合你的日志和脚本细节,我整理了几个关键排查点和解决方案:
1. 环境变量缺失导致AWS CLI认证失败
手动运行时,你的Shell会自动加载~/.bashrc或/etc/profile里的环境变量(比如AWS的密钥对AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY),但Cron默认不会加载这些配置。即使你说“环境变量已配置”,大概率是指交互式Shell里配置了,但Cron完全没拿到这些变量。
解决方案:
在脚本开头加载Shell环境配置:在
dump_psql.sh的最顶部添加一行,强制加载root用户的Shell环境:source /root/.bashrc如果你的AWS变量是放在系统全局配置
/etc/profile里,就替换成加载这个文件。临时测试:在Cron任务中直接指定变量(不推荐长期硬编码,但可以快速验证):
修改Cron任务行,把AWS密钥也加入环境变量:*/3 * * * * S3_BACKUPS_BUCKET=rake-backups AWS_ACCESS_KEY_ID=你的密钥 AWS_SECRET_ACCESS_KEY=你的密钥 /root/dump_psql.sh > /root/logs/cron-2018-01-28T02:24.log
2. AWS CLI无法找到配置文件
手动运行时,AWS CLI会默认读取/root/.aws/credentials和/root/.aws/config,但Cron运行时的HOME变量可能被重置(哪怕用root用户跑Cron),导致找不到配置文件。
解决方案:
- 在脚本中明确指定AWS配置路径:
修改脚本中的AWS命令,加上配置文件的绝对路径:/usr/local/bin/aws --config-file /root/.aws/config --credentials-file /root/.aws/credentials s3 sync $BACKUP_PATH $S3_URL - 或者强制设置HOME变量:在脚本开头添加:
export HOME=/root
3. 脚本变量引用的小问题(额外发现)
看你的Cron日志输出是Dumping database,而手动运行是Dumping rake database,说明${POSTGRES_DB}变量在Cron环境中没有值。虽然这不是AWS同步失效的直接原因,但会导致脚本逻辑不完整,建议修复:
- 要么在Cron任务行中补充变量:
*/3 * * * * S3_BACKUPS_BUCKET=rake-backups POSTGRES_DB=rake /root/dump_psql.sh > /root/logs/cron-2018-01-28T02:24.log - 要么在脚本里直接使用你已经定义的
DB_NAME变量,把echo "$(date) Dumping ${POSTGRES_DB} database"改成echo "$(date) Dumping ${DB_NAME} database"。
4. 调试技巧:输出更多环境信息
为了精准排查,可以在脚本的AWS命令前添加环境变量输出,方便对比手动和Cron的差异:
echo "=== Current Environment Variables ===" env echo "=== AWS CLI Version ===" /usr/local/bin/aws --version
这样Cron日志里会显示所有环境变量,你可以和手动运行env的输出对比,快速找出缺失的关键变量。
按照上面的方法逐一排查,应该就能解决Cron下AWS sync无效果的问题了。
内容的提问来源于stack exchange,提问作者Vassily

