调用mysqldump应使用绝对路径、--defaults-file传凭据、时间戳文件名避开特殊字符、pathlib.path.resolve()确保绝对路径、检查文件存在性、用rclone上传并校验md5、systemd timer替代cron管理定时任务。

用 subprocess 调用 mysqldump 时权限和路径最容易出错
直接在 Python 里拼接字符串执行 mysqldump,常遇到“command not found”或“access denied”,根本原因是:Python 进程没继承你 shell 里的 $PATH,且 MySQL 凭据没显式传入。
- 别依赖环境变量找
mysqldump,用绝对路径,比如/usr/bin/mysqldump(Linux/macOS)或C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqldump.exe(Windows) - 密码绝不能写在命令行参数里(
-p123456),会被ps看见;改用--defaults-file指向一个仅当前用户可读的配置文件(如/home/user/.my.cnf),内容含[client]段 - 输出文件路径必须确保目录存在且有写权限,否则
mysqldump静默失败,只返回非零退出码
生成带时间戳的备份文件名要避开 : 和空格
用 datetime.now().strftime('%Y-%m-%d %H:%M:%S') 直接拼文件名,会在 Windows 上报错,Linux 下也可能被 shell 解析异常——因为 : 在文件系统里合法但 shell 会误判为分隔符,空格则需额外转义。
- 推荐格式:
backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}.sql,例如backup_20240520_143022.sql - 如果用
pathlib.Path构造路径,记得调用.resolve()确保是绝对路径,避免定时任务里工作目录不确定导致写入失败 - 备份前先检查同名文件是否已存在,不覆盖,而是加序号或直接跳过(
if not backup_path.exists(): ...)
上传到云盘选 rclone 而不是手写 HTTP 请求
自己用 requests 传大 SQL 文件到阿里云 OSS 或腾讯云 COS,容易卡在分片、签名、重试逻辑上,而且没法断点续传。用现成工具更稳。
-
rclone配置好远程(如aliyun:backup/),上传就一行:rclone copy /path/to/backup.sql aliyun:backup/ --transfers=2 - 上传后立刻校验:
rclone md5sum对比本地和云端的 MD5,避免网络丢包导致文件损坏 - 不要在 Python 里等上传完成再退出,加
timeout=3600参数防挂起,失败时记录rclone的 stderr 到日志
用 systemd 定时比 cron 更可靠(尤其需要环境变量时)
cron 默认只加载 minimal PATH,很多 Python 脚本跑起来就缺模块或找不到 mysqldump;而 systemd timer 可以明确定义 Environment= 和 WorkingDirectory=。
- 写一个
mysql-backup.service,里面用ExecStart=/usr/bin/python3 /opt/scripts/backup.py,并设置Environment="PATH=/usr/local/bin:/usr/bin:/bin" - 配套
mysql-backup.timer,用OnCalendar=hourly或精确到OnCalendar=*-*-* 02:00:00 - 启用前先手动运行
systemctl --user start mysql-backup.service测试,再看journalctl --user -u mysql-backup查错误
真正麻烦的是 MySQL 权限粒度和 rclone 的 token 刷新——前者要单独建 backup_user 并只赋 SELECT 和 LOCK TABLES,后者得定期更新 access key,这两处一漏,备份就静默失效。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











