在运维mysql数据库时,备份文件往往包含大量敏感业务数据。如果直接通过公网或不可信内网传输明文备份,极易被嗅探或截获。利用linux的管道机制,把mysqldump的输出直接交给gpg做非对称加密,可以实现不落盘的加密传输,既安全又高效。

一、为什么要用管道配合gpg加密备份
传统的备份流程通常是先执行 mysqldump 生成 sql 文件,再调用 gpg 或 openssl 对文件加密,最后用 scp 传走。这种方式会在本地磁盘留下明文备份,一旦服务器被入侵或磁盘被回收,数据就直接暴露。而且两步操作占用双倍空间,大库备份时磁盘压力明显。
管道(pipe)的本质是把前一个命令的标准输出作为后一个命令的标准输入,数据不写文件。配合 gpg 的公钥加密,mysqldump 刚吐出数据就被 gpg 用接收者公钥加密,整个过程内存中完成。即使传输中断,也不会有明文残留,符合最小暴露原则。
二、环境准备与gpg密钥生成
在备份源机器和接收备份的机器上都需要有 gpg 环境。接收方先生成自己的密钥对,并把公钥导出交给备份机。备份机只需导入接收方公钥,不需要私钥,这样即使备份机被攻破,攻击者也无法解密历史备份。
下面是在接收方生成密钥对的示例,过程中按提示设置姓名、邮箱和密码短语。注意密码短语用于保护私钥,不能留空。
# 接收方生成rsa密钥对,长度4096 gpg --full-generate-key # 查看已生成密钥,记下接收者邮箱或key id gpg --list-keys # 导出公钥给备份机 gpg --export -a backup@ipipp.com > backup_pub.asc
备份机导入公钥后,可用如下命令确认。只有出现 pub 且 uid 正确,才说明导入成功。
gpg --import backup_pub.asc gpg --list-keys backup@ipipp.com
三、使用管道加密并传输备份
核心命令是把 mysqldump 通过管道符 | 连到 gpg,再用 ssh 或 nc 把加密流推到远端。下面的例子把 testdb 库加密后直接写入远端文件的写法,避免本地落盘。
# 备份机执行,recipient填接收方uid或邮箱 mysqldump -uroot -p'pwd' testdb | gpg --encrypt --recipient backup@ipipp.com --trust-model always > >(ssh backup@192.168.0.1 "cat > /backup/testdb.sql.gpg")
如果接收方也配置了管道接收,可以更简单:ssh 远程直接运行 cat 接收标准输入。这样连远程临时文件都不用提前建。注意 --trust-model always 是为了跳过首次加密时的信任确认,生产环境可改为显式签名信任。
mysqldump -uroot -p'pwd' testdb | gpg --encrypt --recipient backup@ipipp.com | ssh backup@192.168.0.1 "cat > /backup/testdb.sql.gpg"
四、解密与恢复验证
接收方拿到 testdb.sql.gpg 后,用私钥解密即可还原 sql。解密时需要输入之前设置的保护私钥的密码短语。验证备份有效性建议定期做恢复演练,而不是只看文件大小。
# 接收方解密到标准输出,可配合mysql直接恢复 gpg --decrypt /backup/testdb.sql.gpg | mysql -uroot -p'pwd' testdb
如果只想检查内容头几行,可解密后头看:gpg --decrypt 文件 | head。但注意解密数据不要随意落盘,演练完及时清除临时明文。通过管道加密传输,既满足合规,又降低运维复杂度。
五、常见误区与注意事项
有人误以为在 mysqldump 加 --skip-lock-tables 就能提速且不影响加密,其实大表热备可能不一致。加密不解决一致性,需配合 --single-transaction 对 innodb 做一致性快照。另外 gpg 对称加密(用密码)虽然简单,但密码在多机分发时风险高,非对称更合适。
还有一点,管道中如果 ssh 中断,mysqldump 会收到 SIGPIPE 退出,不会产生半截明文。但建议在脚本里加 set -o pipefail,让任意环节失败都报错,而不是静默成功。做好日志和告警,加密备份才真正可靠。
| 方案 | 是否落盘明文 | 密钥管理 | 适用场景 |
|---|---|---|---|
| 先dump再gpg加密 | 是 | 简单密码或公钥 | 磁盘充足且网络可信 |
| 管道配合gpg加密 | 否 | 接收方公钥 | 公网传输、合规要求高 |