-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpgdumpres.py
More file actions
176 lines (139 loc) · 7.71 KB
/
pgdumpres.py
File metadata and controls
176 lines (139 loc) · 7.71 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/env python3
import argparse
import subprocess
import sys
import getpass
# Function to run commands and control errors
def run_command(command, success_message):
result = subprocess.run(command, shell=True)
if result.returncode != 0:
print(f"Error: Command failed with return code {result.returncode}")
sys.exit(1)
else:
print(success_message)
# Function to dump roles
def dumpRoles(user, password, host):
filename = f"backup_roles_{host}.sql"
command = f"PGPASSWORD={password} pg_dumpall -r --no-role-passwords -h {host} -U {user} > {filename}"
run_command(command, "Roles dump completed successfully")
# Modify the file to remove unwanted words
try:
with open(filename, 'r') as file:
content = file.read()
content = content.replace("NOBYPASSRLS", "").replace("NOSUPERUSER", "").replace(" ", " ").replace(" ;", ";")
with open(filename, 'w') as file:
file.write(content)
print(f"Roles dump completed and unwanted words removed from {filename}. Check roles prior restore.")
except Exception as e:
print(f"An error occurred while modifying the file: {e}")
# Function to dump databases
def dumpFull(user, password, host, db):
filename = f"backup_full_{host}_{db}.dump"
command = f"PGPASSWORD={password} pg_dump -O -h {host} -U {user} -d {db} -f {filename}"
run_command(command, "Full database dump completed successfully")
# Function to dump databases compressed
def dumpFullCompress(user, password, host, db):
filename = f"backup_full_compressed_{host}_{db}.dump"
command = f"PGPASSWORD={password} pg_dump -O -Fc -h {host} -U {user} -d {db} -f {filename}"
run_command(command, "Compressed full database dump completed successfully")
# Function to dump whole schemas
def dumpSchema(user, password, host, db):
filename = f"backup_schema_{host}_{db}.dump"
command = f"PGPASSWORD={password} pg_dump -O -s -h {host} -U {user} -d {db} -f {filename}"
run_command(command, "Schema dump completed successfully")
# Modify the file to remove unwanted words
try:
with open(filename, 'r') as file:
content = file.read()
content = content.replace("DEFAULT NULL::character varying", "DEFAULT NULL")
with open(filename, 'w') as file:
file.write(content)
print(f"Schema dump completed and unwanted words removed from {filename}")
except Exception as e:
print(f"An error occurred while modifying the file: {e}")
# Function to restore uncompressed files with psql, indicated for roles, schemas and small DB dumps
def restore(user, password, host, db, dumpFile):
command = f"PGPASSWORD={password} psql -h {host} -U {user} -d {db}-f {dumpFile}"
run_command(command, "Restore completed successfully")
# Function to restore compressed files with pg_restore, best solution for massive DB dumps
def restoreCompress(user, password, host, db, dumpFile):
command = f"PGPASSWORD={password} pg_restore -h {host} -U {user} -d {db} -Fc {dumpFile}"
run_command(command, "Compressed restore completed successfully")
def main():
examples = """\
Examples:
Dump roles:
python pgdumpres.py --host 127.0.0.1 --user myuser --dumpRole
Dump full database:
python pgdumpres.py --host 127.0.0.1 --user myuser --db mydb --dumpFull
Dump compressed full database:
python pgdumpres.py --host 127.0.0.1 --user myuser --db mydb --dumpFullCompress
Dump schema:
python pgdumpres.py --host 127.0.0.1 --user myuser --db mydb --dumpSchema
Restore from uncompressed file:
python pgdumpres.py --host 127.0.0.1 --user myuser --db mydb --dumpFile backup_file.sql --restore
Restore from compressed file:
python pgdumpres.py --host 127.0.0.1 --user myuser --db mydb --dumpFile backup_file.dump --restoreCompress
"""
parser = argparse.ArgumentParser(
description="PostgreSQL Database dump & restore script",
epilog=examples,
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("--host", required=True, help="Host name or IP address of the database server")
parser.add_argument("--user", required=True, help="Database user")
parser.add_argument("--password", help="Database password (optional, if not provided it will be requested interactively)")
parser.add_argument("--db", help="Database name (required for dumpFull, dumpFullCompress, dumpSchema dumps, restore and restoreCompress)")
parser.add_argument("--dumpFile", help="Dump filename for restoration (required for restore and restoreCompress)")
parser.add_argument("--dumpFull", action='store_true', help="Dump the database schema & data")
parser.add_argument("--dumpRole", action='store_true', help="Dump the roles")
parser.add_argument("--dumpSchema", action='store_true', help="Dump the schema")
parser.add_argument("--dumpFullCompress", action='store_true', help="Dump the database schema & data compressed")
parser.add_argument("--restore", action='store_true', help="Restore uncompressed files with psql, indicated for roles, schemas and small DB dumps")
parser.add_argument("--restoreCompress", action='store_true', help="Restore compressed files with pg_restore, best solution for massive DB dumps")
# Define variables
args = parser.parse_args()
dump_actions = [args.dumpFull, args.dumpRole, args.dumpSchema, args.dumpFullCompress]
restore_actions = [args.restore, args.restoreCompress]
# Check that a action parameter is pased
if sum(dump_actions) + sum(restore_actions) == 0:
print("Error: You must provide at least one of --dumpFull, --dumpRole, --dumpSchema, --dumpFullCompress, --restore, or --restoreCompress.")
sys.exit(1)
# Check that a dump and restore actions parameters are not combined
if sum(dump_actions) > 0 and sum(restore_actions) > 0:
print("Error: You cannot combine dump and restore actions in the same execution.")
sys.exit(1)
# Request password interactively if not provided
if not args.password:
args.password = getpass.getpass(prompt='Database password: ')
# Check that only one of dumpFull, dumpRole, dumpSchema, dumpFullCompress is provided
if sum(dump_actions) > 1:
print("Error: You must provide exactly one of --dumpFull, --dumpFullCompress, --dumpRole or --dumpSchema.")
sys.exit(1)
# Check that only one of restore, restoreCompress is provided
if sum(restore_actions) > 1:
print("Error: You must provide exactly one of --restore or --restoreCompress.")
sys.exit(1)
# Ensure db is provided when required
if (args.dumpFull or args.dumpSchema or args.dumpFullCompress or args.restore or args.restoreCompress) and not args.db:
print("Error: --db is required when using --dumpFull, --dumpSchema, --dumpFullCompress, --restore or --restoreCompress.")
sys.exit(1)
# Ensure dumpFile is provided when required
if (args.restore or args.restoreCompress) and not args.dumpFile:
print("Error: --dumpFile is required when using --restore or --restoreCompress.")
sys.exit(1)
# Execute the appropriate function based on the arguments
if args.dumpRole:
dumpRoles(args.user, args.password, args.host)
elif args.dumpFull:
dumpFull(args.user, args.password, args.host, args.db)
elif args.dumpFullCompress:
dumpFullCompress(args.user, args.password, args.host, args.db)
elif args.dumpSchema:
dumpSchema(args.user, args.password, args.host, args.db)
elif args.restore:
restore(args.user, args.password, args.host, args.db, args.dumpFile)
elif args.restoreCompress:
restoreCompress(args.user, args.password, args.host, args.db, args.dumpFile)
if __name__ == "__main__":
main()