ichuan.net

自信打不死的心态活到老

简易安全 rsync 远程多备份方案

场景

web 主机 A,代码和数据库都在上面,需要异地备份数据至主机 B;主机 B 上需要保留最近 5 日的备份供追溯。

备份方案

使用 rsync 做远程备份,考虑安全性,使用 rsync over ssh。首先在 A 上生成 ssh 验证用的公私钥:

ssh-keygen -f ~/.ssh/rsync-key

把公钥追加到 B 的 ~/.ssh/authorized_keys 中。这个文件有种写法,在每行公钥前可以设置些参数,比如限定只能从某个地址登陆,只能执行某个命令:

from="1.2.3.4",command="/root/validate-rsync.sh",no-pty,no-port-forwarding ssh-dss AAAA....

参考这个文档/root/validate-rsync.sh 的内容为:

#!/bin/sh
case "$SSH_ORIGINAL_COMMAND" in
  *\&*)
    echo "Rejected" 
    ;;
  *\;*)
    echo "Rejected"
    ;;
  rsync\ --server*)
    $SSH_ORIGINAL_COMMAND
    ;;
  *)
    echo "Rejected"
    ;;
esac

这样就确保了即使 A 有 B 的 ssh 私钥,也只能用于 rsync 用途。

设 A 主机上代码目录在 /data/htdocs/,需备份至 B 的 /backups/web/,则在 A 上执行:

rsync -azh --stats --delete -e 'ssh -i /root/.ssh/rsync-key' /data/htdocs/ root@B:/backups/web/

对于数据库,可以考虑 dump 出来到网站目录,这样备份时同时把数据库备份了(放在 rsync 执行之前):

/usr/bin/mysqldump -uroot -proot webdb > /data/htdocs/db.bakcup

当然需要对 db.bakcup 设权限,不能让浏览器可以访问到。apache 下可以用 .htaccess 文件来做,nginx 下做法如:

location = /db.backup {
  return 404;
}

多备份方案

就像 /var/log/ 下那些日志文件一样,最初把 web 改为 web.1,下一次把 web.1 改为 web.2,同时把 web 改为 web.1,如此类推。我写了一个小脚本来做这个事:

/root/rsync-dir-rotate.sh /backups/web

这样每次执行就会 rotate 备份 /backups/web,最多保留 5 个(默认)。

合起来

把 A 和 B 上执行的脚本分别放到 crontab 中。由于 rsync over ssh 效率不太高(正常网络下可能 1MB/s 左右),需要把两个脚本的执行时间错开,可以一个半夜执行,一个中午执行。

参考

  1. http://archive09.linux.com/feature/113847

Comments