分享 用 Backup 和 Whenever 进行备份

Rei · 发布于 2012年08月02日 · 最后由 jossjoss54 回复于 2014年11月05日 · 8823 次阅读
1
本帖已被设为精华帖!

最近将 CodeCampo 迁移了服务器,然后学习了 Backup 这个 Ruby gem,抛弃了过去蹩脚的备份脚本,实现了优雅的自动备份方案,跟大家分享一下。

备份脚本

首先登录服务器,安装 Backup。

gem install backup

然后初始化备份脚本。

backup generate:model --trigger codecampo --databases="mongodb" --storages="dropbox"

这时 Backup 会帮初始化备份脚本的目录,和我的第一个备份方案「codecampo」,目录结构如下

Backup/
  models/
    codecampo.rb
  config.rb

config.rb 文件里面定义了一些通用配置,不过我用不到,先跳过。

models/codecampo.rb 就是我要编辑的备份方案,在初始化的时候我已经选择了生成 mongodb 的配置和储存端 dropbox 的配置,所以编辑完成后会是这样子的:

Backup::Model.new(:codecampo, 'Description for codecampo') do
  split_into_chunks_of 250

  database MongoDB do |db|
    db.name = "code_campo"
  end

  store_with Dropbox do |db|
    db.api_key     = "***"
    db.api_secret  = "***"
    db.access_type = :app_folder
    db.path        = "/codecampo"
    db.keep        = 25
  end
end

之前选用了 Dropbox 的储存方案,但是还没有配置 api_key,于是登录 dropbox developer 创建一个新应用。应用的资料可以随意,之后可以修改,不过应用名必需是唯一的。之后把面板的 api_key 和 api_secret 填到上面的备份脚本中。如果你还没有注册 Dropbox,可以通过这个邀请链接注册 http://db.tt/tdIsTDAm ,你和我都会额外增加 500M 空间。

备份脚本已经准备得差不多了,还缺最后一步,认证 dropbox 的应用授权。先来跑一遍备份脚本:

backup perform --trigger codecampo

然后脚本会提示打开一个 dropbox 链接确认授权,现在用浏览器打开链接,并点击 Allow

alt text

通过后回到终端,根据提示回车,第一次备份就完成了!Dropbox 认证只需要一次,以后备份脚本会自动使用这次的认证 token 进行备份。

你可以打开 dropbox 的目录,看到你的应用目录下已经有一份备份存档。

定时任务

确认备份任务顺利跑通后,是时候让备份任务定时化,自动执行。定时任务我选择用 Whenever 帮助管理。

安装 Whenever

gem install whenever

创建定时配置文件

cd
mkdir config
wheneverize

然后打开 config/schedule.rb 文件,编辑为以下内容:

every 1.day, :at => '18:00' do
  command "backup perform -t codecampo"
end

接着执行 whenever,看看生成的 crontab 任务的格式是否正确

$ whenever
0 18 * * * /bin/bash -l -c 'backup perform -t codecampo'

这就是我想要的 crontab 任务,于是执行更新

whenever --update-crontab

现在,备份脚本就会自动在 UTC 时间 18:00 跑了(+0800 时区的凌晨2点)。

总结

这个例子只备份了一个数据库 Mongodb,和使用了一个储存方案。如果需要更多类型的备份和储存方案,可以查阅 Backup 的官方文档 https://github.com/meskyanichi/backup

小提示:你可以编写不同的备份方案,然后用不同的定时任务执行,区分一些不同定时频率的备份。

用 Bakcup + Dropbox + Whenever 进行系统备份就是这么容易!

原文链接:http://codecampo.com/topics/628

共收到 42 条回复
395

不错的分享!

3

好文,谢谢 @Rei 分享~

De6df3

早已用上了,唯独遇到需要 sudoer 权限的文件备份很是麻烦

77

之前已经了解过 backup 这个 gem,不过还是懒,还在用之前手写的脚本备分

顺路问一下,MongoDB 怎样做增量备份?

De6df3

#4楼 @HungYuHei 这种就另外搭一台做 Replication 吧

865

我是想问被分卷压缩后的文件如何解压出来?

1

#6楼 @yesmeck 一般 linux 工具合卷

cat pack1 pack2 > pack

如果压缩了,根据压缩格式的不同解压方式不同。

865

#7楼 @Rei

:thumbsup:

558

以前也用 dropbox ,但发现 bitbucket 不限容量,而且还支持git,就立马转了。 不想用第三方工具,写个备份脚本在 capistrano 更新代码前触发一下

96

Jenkins进行CI,备份毫无压力。

594

#9楼 @happypeter 请问,你是用git做数据库备份吗? 能否说的再详细些,谢谢!

96

#12楼 @ery 基本就是这个 https://gist.github.com/3003659

数据库方面我是外行,我最想要的一个功能就是每次我我从产品 db 里面 dump 出数据之后能有个方式快速的查看一下新增内容,所以我 dump 的时候采用了分行格式,然后用 git 的 diff 功能就可以查看各个时间点上数据内容的变化了。

7284d6

我在rails 3.0.7下用backup 3.0.21 是稳定的,再更新就出错了

142

我是用 sync + crontab 两台机器互相备份,连带图片文件都备份了。

602

cool 头像又变了。。

96

@Rei 在Ubuntu12.04上操作,用crontab -l查看任务,这种写法不能自动执行:

0 22 * * * /bin/bash -l -c 'backup perform -t my_backup'

cat /etc/crontab查看 cron 的主要配置文件得知Ubuntu的写法是:

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

可把上面的

0 22 * * * /bin/bash -l -c 'backup perform -t my_backup'

改成

0 22 * * * /bin/sh -l -c 'backup perform -t my_backup'

还是不能在指定时间自动执行,为什么?

1

#17楼 @lingo rvm 只能在 bash 下用,sh 会出错的。

96

#18楼 @Rei 不太明白。那更改/etc/crontab文件

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

? 这样也试过,仍然不行。

1

#19楼 @lingo 我没动过 /etc/crontab ,这是 system-wide 的 crontab,我是跑在用户上的。

检查一下:

  1. backup perform -t my_backup 是否能正常执行
  2. 把时间间隔调短,比如1分钟再试试。
96

#20楼 @Rei 嗯,1:能正常运行;2:试了,不行。 这是linux的问题,可现在不知如何处理。重启cron服务?断开ssh连接重新登录?都试了。。 问题就在于要执行的命令不会触发。/bin/bash的问题。 这超出你这个分享帖子的范围了,但热心回复,深感谢意:)

445

@Rei 我执行backup perform --trigger codecampo并没有出现认真页面,直接报错!为什么呢?

1

#22楼 @stephen 报错信息贴一下。

445

@Rei

[2012/12/13 05:41:23][message] Packaging the backup files...
[2012/12/13 05:41:23][message] Splitter configured with a chunk size of 250MB.
[2012/12/13 05:41:23][message] Packaging Complete!
[2012/12/13 05:41:23][message] Cleaning up the temporary files...
[2012/12/13 05:41:23][message] Storage::Dropbox started transferring '2012.12.13.05.41.23.gupiao.tar'.
[2012/12/13 05:41:23][message] Creating a new session!
[2012/12/13 05:41:23][error] ModelError: Backup for Description for gupiao (gupiao) Failed!
[2012/12/13 05:41:23][error]   An Error occured which has caused this Backup to abort before completion.
[2012/12/13 05:41:23][error]   Reason: Storage::Dropbox::ConnectionError
[2012/12/13 05:41:23][error]   Storage::Dropbox::AuthenticationError: Could not create or authenticate a new session
[2012/12/13 05:41:23][error]   Reason: DropboxAuthError
[2012/12/13 05:41:23][error]   Error getting request token.  Is your app key and secret correctly set?  Server returned 403: Forbidden.
[2012/12/13 05:41:23][error] 
[2012/12/13 05:41:23][error] Backtrace:
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/dropbox-sdk-1.2/lib/dropbox_sdk.rb:125:in `get_token'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/dropbox-sdk-1.2/lib/dropbox_sdk.rb:140:in `get_request_token'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/dropbox.rb:147:in `create_write_and_return_new_session!'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/dropbox.rb:59:in `connection'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/dropbox.rb:96:in `block (2 levels) in transfer!'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/dropbox.rb:95:in `open'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/dropbox.rb:95:in `block in transfer!'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/base.rb:79:in `block in files_to_transfer_for'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/base.rb:78:in `each'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/base.rb:78:in `files_to_transfer_for'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/dropbox.rb:93:in `transfer!'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/storage/base.rb:33:in `perform!'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/model.rb:254:in `each'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/model.rb:254:in `block in perform!'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/model.rb:252:in `each'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/model.rb:252:in `perform!'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/cli/utility.rb:74:in `block in perform'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/cli/utility.rb:65:in `each'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/lib/backup/cli/utility.rb:65:in `perform'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/thor-0.16.0/lib/thor/task.rb:27:in `run'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/thor-0.16.0/lib/thor/invocation.rb:120:in `invoke_task'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/thor-0.16.0/lib/thor.rb:275:in `dispatch'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/thor-0.16.0/lib/thor/base.rb:425:in `start'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/gems/backup-3.0.27/bin/backup:11:in `<top (required)>'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/bin/backup:19:in `load'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/bin/backup:19:in `<main>'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/bin/ruby_noexec_wrapper:14:in `eval'
[2012/12/13 05:41:23][error]   /home/stephen/.rvm/gems/ruby-1.9.3-p286/bin/ruby_noexec_wrapper:14:in `<main>'
[2012/12/13 05:41:23][warning] CleanerError: Cleanup Warning
[2012/12/13 05:41:23][warning]   The temporary backup folder '/home/stephen/Backup/.tmp'
[2012/12/13 05:41:23][warning]   appears to contain the backup files which were to be stored:
[2012/12/13 05:41:23][warning]   /home/stephen/Backup/.tmp/2012.12.13.05.41.23.gupiao.tar
[2012/12/13 05:41:23][warning]   
[2012/12/13 05:41:23][warning]   Make sure you check these files before the next scheduled backup for
[2012/12/13 05:41:23][warning]   'Description for gupiao (gupiao)'
[2012/12/13 05:41:23][warning]   These files will be removed at that time!
[2012/12/13 05:41:23][message] ModelError: If you have other Backup jobs (triggers) configured to run,
[2012/12/13 05:41:23][message]   Backup will now attempt to continue...
1

#24楼 @stephen

Error getting request token. Is your app key and secret correctly set? Server returned 403: Forbidden.

是否带星号这两行没设置?

store_with Dropbox do |db|
  db.api_key     = "***" <-
  db.api_secret  = "***" <-
  db.access_type = :app_folder
  db.path        = "/codecampo"
  db.keep        = 25
end
445

@Rei 之前不是,刚刚改了,运行还是这个错误!

store_with Dropbox do |db|
  db.api_key     = "***"
  db.api_secret  = "***"
  db.access_type = :app_folder
  db.path        = "/gupiao"
  db.keep        = 25
end
1

#26楼 @stephen 这不清楚了,按提示就是这两个值无效,开个 vpn 试试?

618

哈哈,ant也是个不错的选择

445

@Rei 这些操作,全部在服务器上进行的把?服务器开VPN?我的是 linode!

1

#29楼 @stephen 那最有可能还是你的 key 和 secret 填错了。(填自己创建的应用的 key 和 secret)

547643

#30楼 @Rei 不知道dropbox这种app_folder的方式安全性如何? 你现在还在用吗?

1

#31楼 @hpyhacking 我现在换用 S3 了,还是 backup gem。

547643

#32楼 @Rei 刚测了一下,S3给力啊。Dropbox干这个事总觉的别扭。

96

顶一下!

1093

如果本地备份的话,怎么设置啊?

460

@Rei 安装 Backup 应该是 gem install backup, bakcup笔误 还有这里 "用 Bakcup + Dropbox + Whenever 进行系统备份就是这么容易" 这是吃冷饭么

4525

成功了,在配Dropbox時折騰了一下,記得在創建時選 Dropbox API app,及 Files and datastores

96

此gem 备份mysql, 其实只是用了mysqldump 嘛?他支持mysql 增量备份的类似策略嘛(备份binlog)。

8351

也可以改成CST时区。

3253

稳定运行了一年多了。这个组合。

2653

在 rbenv 环境下,可能 whenever 生成的 shell 命令不能正确执行,这个时候需要在config/schedule.rb顶端加入env :PATH, ENV['PATH'],确保corn job执行的时候,PATH 环境变量和用户环境时一样的。

96

这gem 备份mysql时候cpu使用量多少啊?

43楼 已删除
De6df3 huacnlee 整理 Backup 存储到国内的云存储 中提及了此贴 11月28日 15:39
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册