可行,但需SSH免密登录和远端写入权限;mysqldump | scp失败因scp不接受标准输入,正确方式是mysqldump | ssh "cat > file"或分步mysqldump→scp→清理。

mysqldump 直接通过管道传输到异地服务器是可行的,但必须满足两个前提:SSH 免密登录已配置、远端有写入权限。否则备份会卡在密码输入或权限拒绝阶段,根本不会生成文件。
为什么不能直接用 mysqldump | scp?
这条命令看似合理:mysqldump -u root testdb | scp - /backup/testdb_$(date +%F).sql,但它实际会失败——scp 不接受标准输入流作为源,它只认本地路径或远程路径。你看到的错误通常是:scp: /backup/testdb_2026-04-15.sql: No such file or directory 或更隐蔽的 stdin: is not a tty。正确做法是让远端 cat 接收管道数据并落地。
mysqldump + ssh 管道备份(推荐)
这是最轻量、加密、不落地本地磁盘的方案。核心逻辑是:本地 mysqldump 输出 stdout → 通过 SSH 加密通道传给远端 → 远端用 cat > file 写入。
- 确保已在本地执行过
ssh-copy-id root@192.168.18.220,能免密登录远端 - 远端提前建好目录:
ssh root@192.168.18.220 "mkdir -p /root/mysql-backup" - 执行备份命令:
mysqldump -u root -p'yourpass' --single-transaction testdb | ssh root@192.168.18.220 "cat > /root/mysql-backup/testdb_$(date +\%F_\%H\%M).sql" - 注意
--single-transaction对 InnoDB 很关键,避免锁表;若含 MyISAM 表,得改用--lock-all-tables - 日期格式中的
%需要转义,否则本地 shell 会先解析,导致远端文件名异常
用 scp 分两步走(适合调试或小库)
当管道方式因网络抖动、超时或 SELinux 限制失败时,分步更可控。本质是:先 dump 到本地临时文件 → scp 推送 → 远端清理临时文件。
- 本地生成带时间戳的 dump:
mysqldump -u root -p'yourpass' testdb > /tmp/testdb_$(date +\%F_\%H\%M).sql - 推送并重命名远端文件:
scp /tmp/testdb_$(date +\%F_\%H\%M).sql root@192.168.18.220:/root/mysql-backup/ - 立即清理本地临时文件:
rm /tmp/testdb_$(date +\%F_\%H\%M).sql(别漏掉,否则磁盘悄悄涨满) - 远端可加校验:
ssh root@192.168.18.220 "sha256sum /root/mysql-backup/testdb_$(date +\%F_\%H\%M).sql",与本地比对
常见报错和绕过点
真正卡住你的往往不是语法,而是权限链断裂:
-
Permission denied (publickey):说明ssh-copy-id没生效,检查远端/root/.ssh/authorized_keys权限是否为 600,目录为 700 -
bash: cat: command not found:极少见,但某些精简版系统(如 Alpine)默认没装coreutils,需先在远端运行apk add coreutils或换用dd of=... - 备份中途断开:管道方式无断点续传,
scp方式可加-C(压缩)和-o ConnectTimeout=30提高鲁棒性 - 大库(>2GB)慎用管道:内存缓冲区可能溢出,
scp分步更稳;若坚持管道,可在远端加pv监控流速:ssh ... "pv > /path/file.sql"
远端存储路径、时间戳格式、SSH 用户权限这三点,比命令本身更容易出问题。每次换环境前,先手动 ssh 登进去跑一遍 pwd && touch test && rm test,比反复试备份快得多。


















