http://xuhehuan.com/1834.html
这是一篇首发在SAE云计算平台开发者论坛的文章,主要目的就是在通过SAE高级开发者认证后,用来申请新浪微博加V。按照目前的SAE申请微博加V要求,只要同时满足下面两条,加V就手到擒来。
1.通过SAE中级,高级开发者认证。
2.在SAE社区发布一篇原创的文章被加为精华帖。
本篇文章下午发表在SAE开发者论坛后,很快就被版主加精了,以下是当时发表的文章内容,稍有修改。
在7月9号通过中级开发者认证后,16号又通过了高级认证,终于有免费的云豆用了,便迫不及待的将原来一个用EMlog搭建的博客移植到了SAE上来,但不论你在哪里,备份都需要滴。
原来博客的数据是用插件备份的,移植过来后,却没有发现一个完美的数据备份方法,我所说的完美,要求也不高,就是能够实现以下三点:(1)定时自动备份;(2)备份内容发送邮件附件;(3)存储到服务器上的备份数量可控。第一点是基本需求,第二点是防患未然,第三点是个人喜好,不然一天一个备份,一年下来都好几百了,看着碍眼、放着无用且浪费资源。最后,既然网上没找到完全中意的方法,就参考着文档和搜索到的一些信息摸索着实现了,和大家分享下。
1、在需要备份的应用里面创建一个单独用于存储备份的Storage,命名随意,比如:dbbackup;
2、在网站代码的任意目录下新建一个php文件,命名随意,比如dbbackup.php,内容就不能随意了,需根据情况修改,参考下面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<?php
/********************************************************************
** database backup for sae, code from xhhjin (http://xuhehuan.com) **
********************************************************************/
define
(
'DB_DOMAIN'
,
'dbbackup'
)
;
//备份域
define
(
'DB_BACKUP_PATH'
,
'backup'
)
;
//备份路径和文件名
define
(
'DB_BACKUP_NUMBER'
,
20
)
;
//备份数目限制,不超过900
define
(
'DB_MAIL_SMTP'
,
'smtp.163.com'
)
;
//smtp服务器
define
(
'DB_MAIL_PORT'
,
25
)
;
//smtp端口
define
(
'DB_MAIL_SENDEMAIL'
,
'*****@163.com'
)
;
//发送邮件帐号
define
(
'DB_MAIL_PASSWORD'
,
'******'
)
;
//发送邮件密码
define
(
'DB_MAIL_TOEMAIL'
,
'****@126.com'
)
;
//收信邮件帐号
header
(
'Content-Type: text/html; charset=UTF-8'
)
;
$stor
=
new
SaeStorage
(
)
;
$attr
=
array
(
'private'
=
>
false
)
;
$ret
=
$stor
->
setDomainAttr
(
DB_DOMAIN
,
$attr
)
;
$date
=
date
(
'Y-m-d'
)
;
$pathname
=
DB_BACKUP_PATH
.
'/'
.
$date
.
'.sql.zip'
;
//按日期命名
//备份数据库+发邮件
$dj
=
new
SaeDeferredJob
(
)
;
$taskID
=
$dj
->
addTask
(
"export"
,
"mysql"
,
DB_DOMAIN
,
$pathname
,
SAE_MYSQL_DB
,
""
,
""
)
;
$dbbackup_url
=
$stor
->
getUrl
(
DB_DOMAIN
,
$pathname
)
;
$mail
=
new
SaeMail
(
)
;
if
(
$taskID
===
false
)
{
echo
(
"数据库备份失败, errno:"
.
$dj
->
errno
(
)
.
", errmsg: "
.
$dj
->
errmsg
(
)
.
"。 <br>"
)
;
$ret
=
$mail
->
quickSend
(
DB_MAIL_TOEMAIL
,
'数据库备份失败'
,
'数据库备份失败! errno:'
.
$dj
->
errno
(
)
.
', errmsg:'
.
$dj
->
errmsg
(
)
.
'.'
,
DB_MAIL_SENDEMAIL
,
DB_MAIL_PASSWORD
,
DB_MAIL_SMTP
,
DB_MAIL_PORT
)
;
//邮箱通知
}
else
{
do
{
$ret
=
$dj
->
getStatus
(
$taskID
)
;
}
while
(
$ret
===
'waiting'
||
$ret
===
'inqueue'
||
$ret
===
'excuting'
)
;
echo
(
"数据库备份成功, taskID($taskID, $ret)。 <br>"
)
;
$attachdata
=
file_get_contents
(
$dbbackup_url
)
;
$mail
->
setAttach
(
array
(
"db-$date.sql.zip.txt"
=
>
$attachdata
)
)
;
//发送数据库附件,支持的文件后缀参考SAE文档,大小不超过1M
$ret
=
$mail
->
quickSend
(
DB_MAIL_TOEMAIL
,
'数据库备份成功'
,
'数据库备份成功!'
.
' 备份地址:'
.
$dbbackup_url
,
DB_MAIL_SENDEMAIL
,
DB_MAIL_PASSWORD
,
DB_MAIL_SMTP
,
DB_MAIL_PORT
)
;
//邮箱通知
}
//清理多余的备份文件
$domain
=
DB_DOMAIN
;
$path
=
DB_BACKUP_PATH
;
$limitNum
=
DB_BACKUP_NUMBER
;
do
{
//循环获取指定路径文件
$fileArray
=
$stor
->
getListByPath
(
$domain
,
$path
,
$limitNum
+
100
,
0
)
;
$fileList
=
$fileArray
[
'files'
]
;
// 文件名字列表数组
$totalFileNum
=
$fileArray
[
'fileNum'
]
;
// 文件数目
if
(
$totalFileNum
<=
$limitNum
)
{
break
;
//路径下文件数目不大于限制数目,跳出循环
}
foreach
(
$fileList
as
$key
=
>
$value
)
{
$fileTime
[
$key
]
=
$value
[
'uploadTime'
]
;
}
array_multisort
(
$fileTime
,
SORT_DESC
,
$fileList
)
;
// 按照文件上传时间降序排列
//print_r($fileList);
echo
"<br>该目录总共有($totalFileNum)个文件! <br>"
;
for
(
$i
=
0
;
$i
<
$limitNum
;
++
$i
)
{
$file
=
$fileList
[
$i
]
[
'fullName'
]
;
}
//清理限制数目之外的文件
for
(
$i
=
$limitNum
;
$i
<
$totalFileNum
;
$i
++
)
{
$file
=
$fileList
[
$i
]
[
'fullName'
]
;
$stor
->
delete
(
$domain
,
$file
)
;
$fileNum
=
count
(
$fileList
)
;
}
}
while
(
$totalFileNum
>
$limitNum
)
;
//显示清理路径结果
echo
"Domain($domain)的路径($path)中只保留了最新上传的($limitNum)个文件,其余文件已被清除!"
;
$attr
=
array
(
'private'
=
>
true
)
;
$ret
=
$stor
->
setDomainAttr
(
DB_DOMAIN
,
$attr
)
;
//设置domain为private,保护数据
?>
|
<?php
/********************************************************************
** database backup for sae, code from xhhjin (http://xuhehuan.com) **
********************************************************************/
define
(
'DB_DOMAIN'
,
'dbbackup'
)
;
//备份域
define
(
'DB_BACKUP_PATH'
,
'backup'
)
;
//备份路径和文件名
define
(
'DB_BACKUP_NUMBER'
,
20
)
;
//备份数目限制,不超过900
define
(
'DB_MAIL_SMTP'
,
'smtp.163.com'
)
;
//smtp服务器
define
(
'DB_MAIL_PORT'
,
25
)
;
//smtp端口
define
(
'DB_MAIL_SENDEMAIL'
,
'*****@163.com'
)
;
//发送邮件帐号
define
(
'DB_MAIL_PASSWORD'
,
'******'
)
;
//发送邮件密码
define
(
'DB_MAIL_TOEMAIL'
,
'****@126.com'
)
;
//收信邮件帐号
header
(
'Content-Type: text/html; charset=UTF-8'
)
;
$stor
=
new
SaeStorage
(
)
;
$attr
=
array
(
'private'
=
>
false
)
;
$ret
=
$stor
->
setDomainAttr
(
DB_DOMAIN
,
$attr
)
;
$date
=
date
(
'Y-m-d'
)
;
$pathname
=
DB_BACKUP_PATH
.
'/'
.
$date
.
'.sql.zip'
;
//按日期命名
//备份数据库+发邮件
$dj
=
new
SaeDeferredJob
(
)
;
$taskID
=
$dj
->
addTask
(
"export"
,
"mysql"
,
DB_DOMAIN
,
$pathname
,
SAE_MYSQL_DB
,
""
,
""
)
;
$dbbackup_url
=
$stor
->
getUrl
(
DB_DOMAIN
,
$pathname
)
;
$mail
=
new
SaeMail
(
)
;
if
(
$taskID
===
false
)
{
echo
(
"数据库备份失败, errno:"
.
$dj
->
errno
(
)
.
", errmsg: "
.
$dj
->
errmsg
(
)
.
"。 <br>"
)
;
$ret
=
$mail
->
quickSend
(
DB_MAIL_TOEMAIL
,
'数据库备份失败'
,
'数据库备份失败! errno:'
.
$dj
->
errno
(
)
.
', errmsg:'
.
$dj
->
errmsg
(
)
.
'.'
,
DB_MAIL_SENDEMAIL
,
DB_MAIL_PASSWORD
,
DB_MAIL_SMTP
,
DB_MAIL_PORT
)
;
//邮箱通知
}
else
{
do
{
$ret
=
$dj
->
getStatus
(
$taskID
)
;
}
while
(
$ret
===
'waiting'
||
$ret
===
'inqueue'
||
$ret
===
'excuting'
)
;
echo
(
"数据库备份成功, taskID($taskID, $ret)。 <br>"
)
;
$attachdata
=
file_get_contents
(
$dbbackup_url
)
;
$mail
->
setAttach
(
array
(
"db-$date.sql.zip.txt"
=
>
$attachdata
)
)
;
//发送数据库附件,支持的文件后缀参考SAE文档,大小不超过1M
$ret
=
$mail
->
quickSend
(
DB_MAIL_TOEMAIL
,
'数据库备份成功'
,
'数据库备份成功!'
.
' 备份地址:'
.
$dbbackup_url
,
DB_MAIL_SENDEMAIL
,
DB_MAIL_PASSWORD
,
DB_MAIL_SMTP
,
DB_MAIL_PORT
)
;
//邮箱通知
}
//清理多余的备份文件
$domain
=
DB_DOMAIN
;
$path
=
DB_BACKUP_PATH
;
$limitNum
=
DB_BACKUP_NUMBER
;
do
{
//循环获取指定路径文件
$fileArray
=
$stor
->
getListByPath
(
$domain
,
$path
,
$limitNum
+
100
,
0
)
;
$fileList
=
$fileArray
[
'files'
]
;
// 文件名字列表数组
$totalFileNum
=
$fileArray
[
'fileNum'
]
;
// 文件数目
if
(
$totalFileNum
<=
$limitNum
)
{
break
;
//路径下文件数目不大于限制数目,跳出循环
}
foreach
(
$fileList
as
$key
=
>
$value
)
{
$fileTime
[
$key
]
=
$value
[
'uploadTime'
]
;
}
array_multisort
(
$fileTime
,
SORT_DESC
,
$fileList
)
;
// 按照文件上传时间降序排列
//print_r($fileList);
echo
"<br>该目录总共有($totalFileNum)个文件! <br>"
;
for
(
$i
=
0
;
$i
<
$limitNum
;
++
$i
)
{
$file
=
$fileList
[
$i
]
[
'fullName'
]
;
}
//清理限制数目之外的文件
for
(
$i
=
$limitNum
;
$i
<
$totalFileNum
;
$i
++
)
{
$file
=
$fileList
[
$i
]
[
'fullName'
]
;
$stor
->
delete
(
$domain
,
$file
)
;
$fileNum
=
count
(
$fileList
)
;
}
}
while
(
$totalFileNum
>
$limitNum
)
;
//显示清理路径结果
echo
"Domain($domain)的路径($path)中只保留了最新上传的($limitNum)个文件,其余文件已被清除!"
;
$attr
=
array
(
'private'
=
>
true
)
;
$ret
=
$stor
->
setDomainAttr
(
DB_DOMAIN
,
$attr
)
;
//设置domain为private,保护数据
?>
其中第一部分的宏定义是需要根据实际情况修改的,主要是storage、路径和邮箱的设置,具体内容可以参考代码里面的对应说明。这里假设的是将数据文件备份到一个叫dbbackup的storage中的backup文件夹里,并且只保留最新的20个备份;邮件部分则是在执行备份时将最新的数据备份文件发送到你的设定邮箱里,测试中我用的发送邮箱是163的,接收邮箱是126的。需要说明的是,测试时SAE的邮件服务不是很稳定,有时可能会收不到邮件,并且邮件发送的附件大小限制在1M以内,不支持zip的文件后缀,所以你的数据备份文件不超过1M时可以完美的使用本方法,超过的话附件就接收不到了,正常接收到的附件名字类似:db-2014-07-22.sql.zip.txt,下载下来后将.txt去掉即可。
3、在网站代码根目录的config.yaml文件中添加一个cron任务,让备份可以自动定时执行:
|
cron
:
-
description
:
database
backup
url
:
/实际目录
/
dbbackup
.
php
schedule
:
every
day
of
month
03
:
00
handle
:
-
hostaccess
:
if
(
path
~
"/实际目录/dbbackup.php"
)
allow
"127.0.0.1"
|
代码里需替换下正确的目录名字;schedule: every day of month 03:00表示每天凌晨3点开始自动备份,如果发现收不到邮件,很可能是被邮箱判断为垃圾邮件或者被系统退信了,毕竟没有几个人会在凌晨3点发邮件的,这时只要把03:00改成其他的时间(比如23:30)就可以;想更改成每周或每月等等时间备份的可以通过Cron配置生成工具生成后替换修改:http://saetools.sinaapp.com/cron.html;
另外,由于备份中用的了DeferredJob,并且SAE限制DeferredJob每天只能添加10个任务,所以有了这一条:
|
-
hostaccess
:
if
(
path
~
"/实际目录/dbbackup.php"
)
allow
"127.0.0.1"
|
它表示只允许内网访问dbbackup.php文件,这样就可以让Cron服务正常运行并且有效防止了外部的无意或恶意点击,当然,你也可以将自己的IP添加进去测试用,不然直接访问是会403 Forbidden的,修改可以用Appconfig 配置生成工具:http://saetools.sinaapp.com/appconfig.html。
2014年10月19日,更新更完善的备份方法:SAE数据库完美备份加强版。
欢迎转载,转载请注明出处:蔓草札记 » SAE数据库完美备份(自动备份+发送邮件+数量可控)