Python脚本实现自动将数据库备份到 Dropbox


Posted in Python onFebruary 06, 2017

最近,正好发生了一件大事,就是 GitLab 的运维同学不小心删除了生产的数据,虽然 GitLab 已经骇人听闻的准备了五种备份机制,但是,仍然导致他们丢失了将近 6 个小时的用户数据,尤其对他们声誉的损失,是根本无法估量的。反思一下,这个博客 Becomin' Charles,也是没有完善的备份的,真是冷汗直冒啊,主要考虑到这是我的个人博客,但是想想已经坚持了快十年了,如果真的丢了的话,还是非常痛心的。

正好,老婆最近正在学习Python 编程,我在教她,其实,我是PHP 程序员,一点也不喜欢 Python,但是说实在,一个外行学编程的话,Python 确实比PHP 友好太多了,只能推荐她学 Python 了。正好,借着这个机会,我决定自己也学学 Python 编程吧,于是,我决定要用 Python 做一个数据库的自动备份脚本。备份的位置,就用Dropbox 来做吧,因为我的服务器是 Linode 提供的,美国 fremont 机房,选择美国的存储服务,比较合适。以下是我写得代码,Python 小白,敬请指教:

#!/usr/bin/python
#coding:utf-8
 
import sys
import os
from yamlimport load
from datetime import datetime
import dropbox
from dropbox.filesimport WriteMode
from dropbox.exceptions import ApiError, AuthError
 
if len(sys.argv) < 2:
  print >>sys.stderr, "Usage: %s <config_file>" % sys.argv[0]
  sys.exit(0)
 
conf = load(file(sys.argv[1], 'r'))
 
# config file is a YAML looks like
# ---
# 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
 
for dbin conf['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'],    # remote path
      datetime.now().strftime("%Y%m%d"), # date string
      conf['server-name'],       # server name
      filename + '.gz')
  with open(filepath, 'rb') as f:
    time = datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
    print(time + "Uploading " + filepath + " to Dropbox as " + backuppath)
    try:
      dbx.files_upload(f.read(), backuppath, mode=WriteMode('overwrite'))
    except ApiErroras err:
      # This checks for the specific error where a user doesn't have
      # enough Dropbox space quota to upload this file
      if (err.error.is_path() and
          err.error.get_path().error.is_insufficient_space()):
        sys.exit("ERROR: Cannot back up; insufficient space.")
      elif err.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 也很好用。

pip install PyYAML
pip install dropbox
Python 相关文章推荐
python装饰器实例大详解
Oct 25 Python
Python金融数据可视化汇总
Nov 17 Python
Python多线程爬虫实战_爬取糗事百科段子的实例
Dec 15 Python
python-docx修改已存在的Word文档的表格的字体格式方法
May 08 Python
python迭代dict的key和value的方法
Jul 06 Python
python读取并定位excel数据坐标系详解
Jun 26 Python
Python3内置模块random随机方法小结
Jul 13 Python
Python爬取豆瓣视频信息代码实例
Nov 16 Python
Pytorch 多维数组运算过程的索引处理方式
Dec 27 Python
Tensorflow tf.nn.depthwise_conv2d如何实现深度卷积的
Apr 20 Python
Django实现drf搜索过滤和排序过滤
Jun 21 Python
Python+Appium自动化测试的实战
Jun 30 Python
一张图带我们入门Python基础教程
Feb 05 #Python
详解python脚本自动生成需要文件实例代码
Feb 04 #Python
Python中文件I/O高效操作处理的技巧分享
Feb 04 #Python
Django应用程序中如何发送电子邮件详解
Feb 04 #Python
Python算法应用实战之栈详解
Feb 04 #Python
Python算法应用实战之队列详解
Feb 04 #Python
python模块之re正则表达式详解
Feb 03 #Python
You might like
这部好评如潮的动漫 知名梗频出 但是画风劝退很多人
2020/03/08 日漫
支持数组的ADDSLASHES的php函数
2010/02/16 PHP
PHP下使用mysqli的函数连接mysql出现warning: mysqli::real_connect(): (hy000/1040): ...
2016/02/14 PHP
PHP读取CSV大文件导入数据库的实例
2017/07/24 PHP
Laravel框架分页实现方法分析
2018/06/12 PHP
基于jQuery判断两个元素是否有重叠部分的代码
2012/07/25 Javascript
Js 时间函数getYear()的使用问题探讨
2013/04/01 Javascript
window.showModalDialog参数传递中含有特殊字符的处理方法
2013/06/06 Javascript
解析ScrollPic在ie8下只滚动一遍,然后变为空白 ie6,ie7,chrome,firefox正常
2013/06/26 Javascript
jquery验证表单中的单选与多选实例
2013/08/18 Javascript
javascript圆盘抽奖程序实现原理和完整代码例子
2014/06/03 Javascript
深入剖析JavaScript:Object类型
2016/05/10 Javascript
JavaScript如何实现跨域请求
2016/08/05 Javascript
javascript中递归的两种写法
2017/01/17 Javascript
详解Vue-Cli 异步加载数据的一些注意点
2017/08/12 Javascript
详解vue 在移动端体验上的优化解决方案
2019/05/20 Javascript
JavaScript实现点击切换功能
2021/01/27 Javascript
[01:38]DOTA2辉夜杯 欢乐的观众现场采访
2015/12/26 DOTA
使用python将mdb数据库文件导入postgresql数据库示例
2014/02/17 Python
python利用matplotlib库绘制饼图的方法示例
2016/12/18 Python
Python批量查询域名是否被注册过
2017/06/21 Python
python利用正则表达式搜索单词示例代码
2017/09/24 Python
Python数据结构与算法之使用队列解决小猫钓鱼问题
2017/12/14 Python
python: 判断tuple、list、dict是否为空的方法
2018/10/22 Python
python实现QQ批量登录功能
2019/06/19 Python
Django ModelForm组件使用方法详解
2019/07/23 Python
Jupyter notebook运行Spark+Scala教程
2020/04/10 Python
详解numpy1.19.4与python3.9版本冲突解决
2020/12/15 Python
Html5与App的通讯方式详解
2019/10/24 HTML / CSS
大学生职业生涯规划书范文
2014/01/04 职场文书
党性锻炼的心得体会
2014/09/03 职场文书
自主招生推荐信格式模板
2015/03/24 职场文书
答谢酒会主持词
2015/07/02 职场文书
2016七夕情人节寄语
2015/12/04 职场文书
高二化学教学反思
2016/02/22 职场文书
python 如何用terminal输入参数
2021/05/25 Python