Docker-Compose定时Cron任务备份PostgreSQL数据库失败求助
Cron执行Docker Compose数据库备份脚本失败的解决建议
手动跑正常但Cron执行出问题,这种情况十有八九是Cron的执行环境和你登录Shell的环境不一致导致的,我帮你梳理几个核心问题点和修复方案:
1. 解决Docker Compose的环境与路径问题
Cron的默认PATH非常有限,即便你手动能找到docker-compose,Cron可能找不到。另外,Cron执行时没有交互式终端,docker-compose exec需要额外参数才能正常运行:
- 给
docker-compose exec加上-T参数,禁用伪终端分配(非交互式环境必须加,否则会因为找不到TTY报错) - 确保脚本里使用
docker-compose的绝对路径,你可以用which docker-compose命令确认它的实际路径(比如可能是/usr/bin/docker-compose而非你写的/usr/local/bin/) - 在脚本开头显式设置
PATH,覆盖Cron的默认路径:export PATH=/usr/local/bin:/usr/bin:/bin
2. 固定工作目录,避免路径混乱
脚本里用了cd /mydir/,但Cron执行时的默认工作目录可能不是这个,如果切换目录失败,后续的相对路径操作全都会出错:
- 在
cd命令后加上错误判断,切换失败直接退出脚本,避免后续无效操作:cd /mydir/ || { echo "Failed to enter /mydir/" >> /backup/backup.log; exit 1; } - 所有文件操作尽量用绝对路径,比如把
mv pg_data/dbback_ /backup/dbback_$date.sql改成:mv /mydir/pg_data/dbback_ /backup/dbback_$date.sql
3. 增加错误检查与日志记录
原脚本的日志记录不够完善,Cron执行时的错误信息无法准确捕捉,建议:
- 在关键命令(比如
pg_dump、tar)执行后检查返回值,失败时记录日志并退出 - 把所有命令的输出都重定向到日志文件,方便排查问题
- 修改Cron任务,把脚本的输出也追加到日志:
50 22 * * * root /backup/backup.sh >> /backup/cron_backup.log 2>&1
修复后的完整脚本
这里给你调整好的脚本,整合了上面所有的修复点:
#!/bin/bash # 显式设置环境变量,确保能找到Docker相关命令 export PATH=/usr/local/bin:/usr/bin:/bin # 切换到工作目录,失败则退出并记录日志 cd /mydir/ || { echo "[$(date)] Failed to enter /mydir/" >> /backup/backup.log; exit 1; } echo "[$(date)] Dumping database .." >> /backup/backup.log # 使用-T参数,避免Cron无TTY导致的错误,同时记录输出 /usr/local/bin/docker-compose exec -T pg-service pg_dump -U pg -d "MYDB" -f /var/lib/postgresql/dbback_ >> /backup/backup.log 2>&1 # 检查pg_dump是否成功执行 if [ $? -ne 0 ]; then echo "[$(date)] pg_dump failed, aborting backup" >> /backup/backup.log exit 1 fi # 生成备份文件名时间戳 backup_date=$(date +%F_%Hh_%Mm) # 绝对路径移动备份文件 mv /mydir/pg_data/dbback_ /backup/dbback_${backup_date}.sql # 切换到备份目录 cd /backup/ || { echo "[$(date)] Failed to enter /backup/" >> /backup/backup.log; exit 1; } echo "[$(date)] Compressing backup .." >> /backup/backup.log tar -czvf dbback_${backup_date}.tar.gz dbback_${backup_date}.sql >> /backup/backup.log 2>&1 # 检查压缩是否成功,再删除原始SQL文件 if [ $? -eq 0 ]; then rm dbback_${backup_date}.sql echo "[$(date)] Backup completed successfully" >> /backup/backup.log else echo "[$(date)] Compression failed, keeping raw SQL file" >> /backup/backup.log fi
最后验证步骤
- 先手动执行修改后的脚本,确认功能正常
- 等待Cron自动执行,然后查看
/backup/backup.log和/backup/cron_backup.log,确认没有报错 - 检查生成的
dbback_*.tar.gz文件大小,确保不是空文件
内容的提问来源于stack exchange,提问作者Khalil Meg
相关产品推荐
相关产品推荐

