优先用 wget --tries=5 --retry-connrefused --timeout=60 --continue 或 curl -fL --retry 3 --retry-delay 2 -o;下载后校验 gzip -t 和 sha256sum;用 mktemp -d 创建临时目录;导入分 zcat 解压与 mysql 执行两步;crontab 中用绝对路径、显式环境、--defaults-file 存密、日志重定向。
用 curl 或 wget 下载备份文件时,如何确保下载完整不中断
直接用 curl -o 或 wget 下载大备份文件,常遇到连接断开、http 302 跳转失败、或服务端限速导致文件截断。这不是脚本写得不对,而是没处理网络不稳定和重试逻辑。
- 优先用
wget --tries=5 --retry-connrefused --timeout=60 --continue:自动重试、跳过临时拒绝、续传断点 - 避免
curl -O,改用curl -fL --retry 3 --retry-delay 2 -o backup.sql.gz:-f确保 HTTP 错误码直接失败,不静默吞掉 4xx/5xx - 下载后必须校验:
gzip -t backup.sql.gz(检查 gzip 完整性),再sha256sum -c checksums.sha256(如果服务端提供) - 别把下载路径写死在
/tmp——它可能被清理;用mktemp -d创建专属目录,脚本退出前rm -rf
导入 .sql.gz 到 MySQL 时,为什么 zcat file.sql.gz | mysql 常失败
看似一行命令很干净,但实际会丢错误、卡住、忽略字符集或权限问题,尤其当 SQL 文件含 CREATE DATABASE 或跨 schema 操作时。
- 不要管道直连:
zcat backup.sql.gz | mysql -u root -p...无法捕获mysql进程自身的报错(比如认证失败、socket 拒绝),stderr 全被吞掉 - 改用显式解压 + 导入两步:
zcat backup.sql.gz > /tmp/backup.sql && mysql -u root --default-character-set=utf8mb4 ,方便加 <code>set -e和日志定位 - 注意
mysql默认不读取~/.my.cnf的密码配置(安全限制),要么用--defaults-extra-file=指定,要么用MYSQL_PWD环境变量(仅限本地) - 大文件导入前先关 autocommit:
mysql -e "SET autocommit=0; SOURCE /tmp/backup.sql;",否则每条 INSERT 都刷盘,慢十倍以上
如何让脚本判断“最新备份”而不是硬编码文件名
备份文件名带时间戳是常见做法,但靠 ls -t | head -1 极不可靠:文件系统修改时间可能被 touch 伪造,NFS 挂载下 ls -t 顺序不一致,且没考虑文件是否正在写入中(如 backup.sql.gz.part)。
父母的功课——育儿心理学对话支持技能(心虫增强版)。提供结构化对话、情绪识别、场景匹配与安全检测;可选Python脚本(scripts/)在SKILL_DIR/data/本地存储评估历史、洞察与会话状态,不对外传输。核心路径:觉察(看见防御)→接纳(慈悲是……
- 服务端应提供元数据接口,例如
curl -s https://backup.example.com/latest.json返回{"filename":"20240520-020001.sql.gz","size":123456789,"finished":true} - 若只能列目录,用
find /path/to/backups -name "*.sql.gz" -mmin -180(近 3 小时内修改)比ls -t更稳;再配合stat -c "%Y" file取纳秒时间戳排序 - 关键防护:检查文件大小是否 > 1MB(排除空文件)、是否
lsof +D /path/to/backups中无占用进程、用inotifywait -t 5 -e moved_to /path/to/backups等上传完成信号
定时任务里执行导入,为什么经常“找不到命令”或“权限被拒”
crontab 环境极简:PATH 很短、没加载 shell profile、HOME 是 root 或 daemon 用户家目录,mysql、gzip 路径找不到,~/.my.cnf 也读不到。
- 所有命令写绝对路径:
/usr/bin/wget、/usr/bin/mysql、/bin/gzip;用which wget确认 - 在 crontab 条目开头显式声明环境:
PATH=/usr/local/bin:/usr/bin:/bin SHELL=/bin/bash HOME=/root - 数据库密码别放命令行(会被
ps aux看到),也不依赖~/.my.cnf;改用mysql --defaults-file=/etc/mysql/backup.cnf,该文件权限设为600,属主为运行脚本的用户 - 加日志重定向:
2>&1 | logger -t db-restore,不然 cron 失败你根本不知道
最麻烦的不是下载或导入本身,而是备份生成过程和服务端状态不可控——比如备份脚本中途崩溃但文件已写入,或者 S3 的 eventual consistency 导致 list objects 返回旧列表。这类问题没法靠客户端脚本彻底规避,得和服务端约定明确的就绪标记(如上传完成后 PUT 一个 backup.sql.gz.done 空文件)。










