Skip to content

Commit 5141286

Browse files
committed
initial commit
0 parents  commit 5141286

File tree

3 files changed

+264
-0
lines changed

3 files changed

+264
-0
lines changed

.gitignore

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
### Python template
2+
# Byte-compiled / optimized / DLL files
3+
__pycache__/
4+
*.py[cod]
5+
*$py.class
6+
7+
# C extensions
8+
*.so
9+
10+
# Distribution / packaging
11+
.Python
12+
env/
13+
build/
14+
develop-eggs/
15+
dist/
16+
downloads/
17+
eggs/
18+
.eggs/
19+
lib/
20+
lib64/
21+
parts/
22+
sdist/
23+
var/
24+
*.egg-info/
25+
.installed.cfg
26+
*.egg
27+
28+
# PyInstaller
29+
# Usually these files are written by a python script from a template
30+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
31+
*.manifest
32+
*.spec
33+
34+
# Installer logs
35+
pip-log.txt
36+
pip-delete-this-directory.txt
37+
38+
# Unit test / coverage reports
39+
htmlcov/
40+
.tox/
41+
.coverage
42+
.coverage.*
43+
.cache
44+
nosetests.xml
45+
coverage.xml
46+
*,cover
47+
48+
# Translations
49+
*.mo
50+
*.pot
51+
52+
# SQL stuff:
53+
*.zip
54+
*.sql
55+
*.gz
56+
57+
# Sphinx documentation
58+
docs/_build/
59+
60+
# PyBuilder
61+
target/
62+
63+
.idea
64+
65+
# Created by .ignore support plugin (hsz.mobi)

README.md

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
phpmyadmin_sql_backup.py
2+
==============================
3+
4+
What is it?
5+
-----------
6+
7+
A Python 3 script to automate the download of SQL backups via a [phpMyAdmin](https://www.phpmyadmin.net/) web interface.
8+
9+
This is useful when your web hosting provider does not grant you access the the console but you want to automate the backup of your database (without having to manually use the browser).
10+
11+
It has been tested with Python 3.5 and phpMyAdmin 4.3.6 + 4.5.4.1 + 4.7.0-dev
12+
13+
_Note_: The web interface of phpMyAdmin may change in the future and break this script. Please file a bug report (including your version of phpMyAdmin) if you encounter this issue.
14+
15+
### Usage
16+
17+
usage: phpmyadmin_sql_backup.py [-h] [-o OUTPUT_DIRECTORY] [-p]
18+
[-e EXCLUDE_DBS]
19+
[--compression {none,zip,gzip}]
20+
[--basename BASENAME] [--timeout TIMEOUT]
21+
[--overwrite-existing] [--dry-run]
22+
url user password
23+
24+
Automates the download of SQL dump backups via a phpMyAdmin web interface.
25+
26+
positional arguments:
27+
url phpMyAdmin login page url
28+
user phpMyAdmin login user
29+
password phpMyAdmin login password
30+
31+
optional arguments:
32+
-h, --help show this help message and exit
33+
-o OUTPUT_DIRECTORY, --output-directory OUTPUT_DIRECTORY
34+
output directory for the SQL dump file
35+
-p, --prepend-date prepend the current UTC date + time to the filename:
36+
"YYYY-MM-DD--HH-MM-SS-UTC_"
37+
-e EXCLUDE_DBS, --exclude-dbs EXCLUDE_DBS
38+
comma separated list for database names to exclude
39+
from the dump
40+
--compression {none,zip,gzip}
41+
compression method of the output file (default: none)
42+
--basename BASENAME the desired basename (without extension) of the SQL
43+
dump file (default: the name given by phpMyAdmin
44+
--timeout TIMEOUT timeout in seconds for the requests (default: 60)
45+
--overwrite-existing overwrite existing backup files (instead of appending
46+
a number to the name)
47+
--dry-run dry run, do not actually download the dump
48+
49+
Written by Christoph Haunschmidt. Version: 2016-03-10.0
50+
51+
#### Examples
52+
53+
`phpmyadmin_sql_backup.py "http://www.example.com/phpmyadmin/" your_user your_password`
54+
55+
Downloads a plain text `.sql` backup of all tables to the current working directory.
56+
57+
---
58+
59+
`phpmyadmin_sql_backup.py "http://www.example.com/phpmyadmin/" your_user your_password --exclude mydb2,mydb4 -p --basename example_dump -o /tmp --compression zip`
60+
61+
Downloads a zipped dump with databases `mydb2` & `mydb4` excluded, the base name `example_dump` and a prepended UTC date / time to the directory `/tmp`, e.g. `/tmp/2016-03-11--15-19-04-UTC_example_dump.zip`.
62+
63+
Requirements
64+
------------
65+
66+
- [Grab - python web-scraping framework](http://grablib.org/) - install via ``pip install -U grab``
67+
68+
Changelog
69+
---------
70+
71+
Currently, there is no changelog; the best option at the moment is to read the commit messages.
72+
73+
License
74+
-------
75+
76+
GNU GPL
77+
78+
Acknowledgements
79+
----------------
80+
81+
### Authors
82+
83+
- Christoph Haunschmidt

phpmyadmin_sql_backup.py

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/usr/bin/env python3
2+
#
3+
# This program is free software: you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation, either version 3 of the License, or
6+
# (at your option) any later version.
7+
#
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU General Public License
14+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
#
16+
####################################################################################
17+
#
18+
# A Python script to automate the download of SQL dump backups
19+
# via a phpMyAdmin web interface.
20+
#
21+
# tested on Python 3.5
22+
#
23+
# Christoph Haunschmidt 2016-03
24+
25+
import argparse
26+
import os
27+
import re
28+
import datetime
29+
30+
import grab
31+
32+
__version__ = '2016-03-10.0'
33+
34+
CONTENT_DISPOSITION_FILENAME_RE = re.compile(r'^.*filename="(?P<filename>[^"]+).*$')
35+
36+
37+
def download_sql_backup(url, user, password, dry_run=False, overwrite_existing=False, prepend_date=True, basename='',
38+
output_directory=os.getcwd(), exclude_dbs=None, compression='none', timeout=60, **kwargs):
39+
exclude_dbs = exclude_dbs.split(',') or []
40+
encoding = '' if compression == 'gzip' else 'gzip'
41+
42+
g = grab.Grab(encoding=encoding, timeout=timeout)
43+
g.go(url)
44+
45+
g.doc.set_input_by_id('input_username', user)
46+
g.doc.set_input_by_id('input_password', password)
47+
g.doc.submit()
48+
49+
g.doc.text_assert('server_export.php')
50+
export_url = g.doc.select("id('topmenu')//a[contains(@href,'server_export.php')]/@href").text()
51+
g.go(export_url)
52+
53+
dbs_available = [option.attrib['value'] for option in g.doc.form.inputs['db_select[]']]
54+
55+
file_response = g.doc.submit(
56+
extra_post=[('db_select[]', db_name) for db_name in dbs_available if db_name not in exclude_dbs] + [
57+
('compression', compression)])
58+
59+
m = CONTENT_DISPOSITION_FILENAME_RE.match(g.response.headers['Content-Disposition'])
60+
if not m:
61+
raise ValueError(
62+
'Could not determine SQL backup filename from {}'.format(g.response.headers['Content-Disposition']))
63+
64+
content_filename = m.group('filename')
65+
filename = content_filename if not basename else basename + os.path.splitext(content_filename)[1]
66+
if prepend_date:
67+
prefix = datetime.datetime.utcnow().strftime(r'%Y-%m-%d--%H-%M-%S-UTC_')
68+
filename = prefix + filename
69+
out_filename = os.path.join(output_directory, filename)
70+
71+
if os.path.isfile(out_filename) and not overwrite_existing:
72+
basename, ext = os.path.splitext(out_filename)
73+
n = 1
74+
print('File {} already exists, to overwrite it use: --overwrite-existing'.format(out_filename))
75+
while True:
76+
alternate_out_filename = basename + '_({})'.format(n) + ext
77+
if not os.path.isfile(alternate_out_filename):
78+
out_filename = alternate_out_filename
79+
break
80+
n += 1
81+
82+
if not dry_run:
83+
file_response.save(out_filename)
84+
85+
return out_filename
86+
87+
88+
if __name__ == '__main__':
89+
parser = argparse.ArgumentParser(
90+
description='Automates the download of SQL dump backups via a phpMyAdmin web interface.',
91+
epilog='Written by Christoph Haunschmidt. Version: {}'.format(__version__))
92+
93+
parser.add_argument('url', help='phpMyAdmin login page url')
94+
parser.add_argument('user', help='phpMyAdmin login user')
95+
parser.add_argument('password', help='phpMyAdmin login password')
96+
parser.add_argument('-o', '--output-directory', default=os.getcwd(), help='output directory for the SQL dump file')
97+
parser.add_argument('-p', '--prepend-date', action='store_true', default=False,
98+
help='prepend the current UTC date + time to the filename: "YYYY-MM-DD--HH-MM-SS-UTC_"')
99+
parser.add_argument('-e', '--exclude-dbs', default='',
100+
help='comma separated list for database names to exclude from the dump')
101+
parser.add_argument('--compression', default='none', choices=['none', 'zip', 'gzip'],
102+
help='compression method of the output file (default: %(default)s)')
103+
parser.add_argument('--basename',
104+
help='the desired basename (without extension) of the SQL dump file (default: the name given by phpMyAdmin')
105+
parser.add_argument('--timeout', type=int, default=60,
106+
help='timeout in seconds for the requests (default: %(default)s)')
107+
parser.add_argument('--overwrite-existing', action='store_true', default=False,
108+
help='overwrite existing backup files (instead of appending a number to the name)')
109+
parser.add_argument('--dry-run', action='store_true', default=False,
110+
help='dry run, do not actually download the dump')
111+
112+
ARGS = parser.parse_args()
113+
114+
dump_fn = download_sql_backup(**vars(ARGS))
115+
116+
print('{} saved SQL dump to: {}'.format(('Would have' if ARGS.dry_run else 'Successfully'), dump_fn))

0 commit comments

Comments
 (0)