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删除文件示例分享
Jan 28 Python
Django1.7+python 2.78+pycharm配置mysql数据库
Oct 09 Python
一个基于flask的web应用诞生 组织结构调整(7)
Apr 11 Python
python SMTP实现发送带附件电子邮件
May 22 Python
mac安装scrapy并创建项目的实例讲解
Jun 13 Python
python实现顺时针打印矩阵
Mar 02 Python
Python Django框架实现应用添加logging日志操作示例
May 17 Python
python多线程扫描端口(线程池)
Sep 04 Python
Python 静态方法和类方法实例分析
Nov 21 Python
matplotlib绘制多个子图(subplot)的方法
Dec 03 Python
Python实现SMTP邮件发送
Jun 16 Python
Python描述数据结构学习之哈夫曼树篇
Sep 07 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
php遍历数组的方法分享
2012/03/22 PHP
PHP中Socket连接及读写数据超时问题分析
2016/07/19 PHP
TP3.2.3框架使用CKeditor编辑器在页面中上传图片的方法分析
2019/12/31 PHP
JS 动态获取节点代码innerHTML分析 [IE,FF]
2009/11/30 Javascript
修改js Calendar日历控件 兼容IE9/谷歌/火狐
2013/01/04 Javascript
Jquery同辈元素选中/未选中效果的实例代码
2013/08/01 Javascript
Extjs改变树节点的勾选状态点击按钮将复选框去掉
2013/11/14 Javascript
js 跳出页面的frameset框架示例介绍
2013/12/23 Javascript
jquery实现仿Flash的横向滑动菜单效果代码
2015/09/17 Javascript
基于jQuery实现搜索关键字自动匹配功能
2020/03/26 Javascript
JavaScript如何调试有哪些建议和技巧附五款有用的调试工具
2015/10/28 Javascript
jQuery 3.0 的变化及使用方法
2016/02/01 Javascript
JavaScript设计模式经典之工厂模式
2016/02/24 Javascript
BootStrap实现响应式布局导航栏折叠隐藏效果(在小屏幕、手机屏幕浏览时自动折叠隐藏)
2016/11/30 Javascript
JavaScript数组去重的多种方法(四种)
2017/09/19 Javascript
js实现一个简单的MVVM框架示例
2018/01/15 Javascript
深入浅析Vue中的slots/scoped slots
2018/04/03 Javascript
vue中使用input[type=&quot;file&quot;]实现文件上传功能
2018/09/10 Javascript
layui监听单元格编辑前后交互的例子
2019/09/16 Javascript
layer 关闭指定弹出层的例子
2019/09/25 Javascript
jQuery实现购物车全功能
2021/01/11 jQuery
python实现跨文件全局变量的方法
2014/07/07 Python
python函数形参用法实例分析
2015/08/04 Python
python脚本实现xls(xlsx)转成csv
2016/04/10 Python
python实现ftp文件传输功能
2020/03/20 Python
Python通用唯一标识符uuid模块使用案例
2020/09/10 Python
Pandas中两个dataframe的交集和差集的示例代码
2020/12/13 Python
python+opencv实现车道线检测
2021/02/19 Python
世界上最受欢迎的花店:1-800-Flowers.com
2020/06/01 全球购物
英文产品推荐信
2015/03/27 职场文书
2015年技术工作总结范文
2015/04/20 职场文书
2016年“世界气象日”广播稿
2015/12/17 职场文书
Python爬虫:从m3u8文件里提取小视频的正确操作
2021/05/14 Python
Win11怎么把合并的任务栏分开 Win11任务栏合并分开教程
2022/04/06 数码科技
vscode远程免密登入Linux服务器的配置方法
2022/06/28 Servers
java中如何截取字符串最后一位
2022/07/07 Java/Android