Python脚本实现自动将数据库备份到 Dropbox
最近,正好发生了一件大事,就是GitLab的运维同学不小心删除了生产的数据,虽然GitLab已经骇人听闻的准备了五种备份机制,但是,仍然导致他们丢失了将近6个小时的用户数据,尤其对他们声誉的损失,是根本无法估量的。反思一下,这个博客Becomin'Charles,也是没有完善的备份的,真是冷汗直冒啊,主要考虑到这是我的个人博客,但是想想已经坚持了快十年了,如果真的丢了的话,还是非常痛心的。
正好,老婆最近正在学习Python编程,我在教她,其实,我是PHP程序员,一点也不喜欢Python,但是说实在,一个外行学编程的话,Python确实比PHP友好太多了,只能推荐她学Python了。正好,借着这个机会,我决定自己也学学Python编程吧,于是,我决定要用Python做一个数据库的自动备份脚本。备份的位置,就用Dropbox来做吧,因为我的服务器是Linode提供的,美国fremont机房,选择美国的存储服务,比较合适。以下是我写得代码,Python小白,敬请指教:
#!/usr/bin/python #coding:utf-8 importsys importos fromyamlimportload fromdatetimeimportdatetime importdropbox fromdropbox.filesimportWriteMode fromdropbox.exceptionsimportApiError,AuthError iflen(sys.argv)<2: print>>sys.stderr,"Usage:%s<config_file>"%sys.argv[0] sys.exit(0) conf=load(file(sys.argv[1],'r')) #configfileisaYAMLlookslike #--- #server-name:127.0.0.1 #local-backup-path:/tmp #remote-backup-path:/backup #dropbox-token:jdkgjdkjg #databases: #-host:localhost #port:3306 #user:user #pass:password #name:database1 #charset:utf8 #-host:localhost #port:3306 #user:user2 #pass:password2 #name:database2 #charset:utf8 fordbinconf['databases']: filename="%s_%s.sql"%(db['name'],datetime.now().strftime("%Y%m%d-%H-%M-%S")) filepath="%s/%s"%(conf['local-backup-path'],filename) cmd="mysqldump-h%s-u%s-p%s-P%s--single-transaction%s>%s"%( db['host'], db['user'], db['pass'], db['port'], db['name'], filepath ) os.system(cmd) cmd="gzip%s"%filepath os.system(cmd) filepath=filepath+'.gz' dbx=dropbox.Dropbox(conf['dropbox-token']) backuppath="%s/%s/%s/%s"%( conf['remote-backup-path'],#remotepath datetime.now().strftime("%Y%m%d"),#datestring conf['server-name'],#servername filename+'.gz') withopen(filepath,'rb')asf: time=datetime.now().strftime("%Y-%m-%d%H:%M:%S") print(time+"Uploading"+filepath+"toDropboxas"+backuppath) try: dbx.files_upload(f.read(),backuppath,mode=WriteMode('overwrite')) exceptApiErroraserr: #Thischecksforthespecificerrorwhereauserdoesn'thave #enoughDropboxspacequotatouploadthisfile if(err.error.is_path()and err.error.get_path().error.is_insufficient_space()): sys.exit("ERROR:Cannotbackup;insufficientspace.") eliferr.user_message_text: print(err.user_message_text) sys.exit() else: print(err) sys.exit()
简单描述下这个代码的思路,这个程序应该满足这个几个要求:
- 使用mysqldump备份数据库到本地
- 应该支持配置文件,允许配置多个数据库
- 可以上传到Dropbox
为了完成这些要求,首先碰到的难题是怎么支持配置文件,一搜,原来Python下有个默认的ConfigParser,可以完成这个任务,但是正常东西比较恶心的是,配置文件必须是以[Section]为单位组织的。其实我的配置显然有些全局配置,还有就是数据库的各种信息是多次重复的,这种配置文件,嵌套能力简直糟糕,必须两层的结构,就很恶心。于是我去网上搜配置文件的格式,好多文章比较了各种配置文件的优劣,其实这文章挺多的,我想了想,以后或许我也可以写文章讲讲我自己的感受了。反正就是很多文章最后都公认YAML是配置文件里最完美的。于是我也决定用这个,果然也有现成的类库,就是PyYAML,特方便,就俩函数load和dump,直接就把文件变成dict格式了。
第二个难题,就是上传Dropbox,后来发现,官方提供了很丰富的API,而且直接就有SDK,(让我眼红的是,官方竟然没有PHP的SDK,这么不受待见么?),研究SDK用法,发现直接就有代码范例,于是直接抄到我的代码里,瞬间完成了50%的代码,爽!
整个代码完成后,我发现,写代码一共也没花多少时间,而且,我学会的Python的方式,我以前一直抱怨Python的文档难用,我发现,其实,最好的方式其实是在交互式的Shell里,用help来查询API,再辅佐以官方文档,才是比较正确的方式。这是刷新了一个我以前的认识的地方。实践下来感觉还不错的。Python的包管理器pip也很好用。
pipinstallPyYAML pipinstalldropbox