-
Notifications
You must be signed in to change notification settings - Fork 4
/
pg_backup_rotated.sh
188 lines (138 loc) · 5.59 KB
/
pg_backup_rotated.sh
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
177
178
179
180
181
182
183
184
185
186
187
188
#!/bin/bash
###########################
####### LOAD CONFIG #######
###########################
while [ $# -gt 0 ]; do
case $1 in
-c)
CONFIG_FILE_PATH="$2"
shift 2
;;
*)
${ECHO} "Unknown Option \"$1\"" 1>&2
exit 2
;;
esac
done
if [ -z $CONFIG_FILE_PATH ] ; then
SCRIPTPATH=$(cd ${0%/*} && pwd -P)
CONFIG_FILE_PATH="${SCRIPTPATH}/pg_backup.config"
fi
if [ ! -r ${CONFIG_FILE_PATH} ] ; then
echo "Could not load config file from ${CONFIG_FILE_PATH}" 1>&2
exit 1
fi
source "${CONFIG_FILE_PATH}"
###########################
#### PRE-BACKUP CHECKS ####
###########################
# Make sure we're running as the required backup user
if [ "$BACKUP_USER" != "" -a "$(id -un)" != "$BACKUP_USER" ] ; then
echo "This script must be run as $BACKUP_USER. Exiting." 1>&2
exit 1
fi
###########################
### INITIALISE DEFAULTS ###
###########################
if [ ! $HOSTNAME ]; then
HOSTNAME="localhost"
fi;
if [ ! $USERNAME ]; then
USERNAME="postgres"
fi;
###########################
#### START THE BACKUPS ####
###########################
function perform_backups()
{
SUFFIX=$1
FINAL_BACKUP_DIR=$BACKUP_DIR"`date +\%Y\%m\%d`$SUFFIX-"
#echo "Making backup directory in $FINAL_BACKUP_DIR"
#if ! mkdir -p $FINAL_BACKUP_DIR; then
# echo "Cannot create backup directory in $FINAL_BACKUP_DIR. Go and fix it!" 1>&2
# exit 1;
#fi;
###########################
### SCHEMA-ONLY BACKUPS ###
###########################
for SCHEMA_ONLY_DB in ${SCHEMA_ONLY_LIST//,/ }
do
SCHEMA_ONLY_CLAUSE="$SCHEMA_ONLY_CLAUSE or datname ~ '$SCHEMA_ONLY_DB'"
done
SCHEMA_ONLY_QUERY="select datname from pg_database where false $SCHEMA_ONLY_CLAUSE order by datname;"
echo -e "\n\nPerforming schema-only backups"
echo -e "--------------------------------------------\n"
SCHEMA_ONLY_DB_LIST=`psql -h "$HOSTNAME" -U "$USERNAME" -At -c "$SCHEMA_ONLY_QUERY" postgres`
echo -e "The following databases were matched for schema-only backup:\n${SCHEMA_ONLY_DB_LIST}\n"
for DATABASE in $SCHEMA_ONLY_DB_LIST
do
echo "Schema-only backup of $DATABASE"
if ! pg_dump -Fp -s -h "$HOSTNAME" -U "$USERNAME" "$DATABASE" | gzip --stdout | s3cmd --reduced-redundancy put - $FINAL_BACKUP_DIR"$DATABASE"_SCHEMA.sql.gz.in_progress --no-encrypt; then
echo "[!!ERROR!!] Failed to backup database schema of $DATABASE" 1>&2
else
s3cmd mv $FINAL_BACKUP_DIR"$DATABASE"_SCHEMA.sql.gz.in_progress $FINAL_BACKUP_DIR"$DATABASE"_SCHEMA.sql.gz
fi
done
###########################
###### FULL BACKUPS #######
###########################
for SCHEMA_ONLY_DB in ${SCHEMA_ONLY_LIST//,/ }
do
EXCLUDE_SCHEMA_ONLY_CLAUSE="$EXCLUDE_SCHEMA_ONLY_CLAUSE and datname !~ '$SCHEMA_ONLY_DB'"
done
FULL_BACKUP_QUERY="select datname from pg_database where not datistemplate and datallowconn $EXCLUDE_SCHEMA_ONLY_CLAUSE order by datname;"
echo -e "\n\nPerforming full backups"
echo -e "--------------------------------------------\n"
for DATABASE in `psql -h "$HOSTNAME" -U "$USERNAME" -At -c "$FULL_BACKUP_QUERY" postgres`
do
if [ $ENABLE_PLAIN_BACKUPS = "yes" ]
then
echo "Plain backup of $DATABASE"
if ! pg_dump -Fp -h "$HOSTNAME" -U "$USERNAME" "$DATABASE" | gzip --stdout | s3cmd --reduced-redundancy put - $FINAL_BACKUP_DIR"$DATABASE".sql.gz.in_progress --no-encrypt; then
echo "[!!ERROR!!] Failed to produce plain backup database schema of $DATABASE" 1>&2
else
s3cmd mv $FINAL_BACKUP_DIR"$DATABASE".sql.gz.in_progress $FINAL_BACKUP_DIR"$DATABASE".sql.gz
fi
fi
if [ $ENABLE_CUSTOM_BACKUPS = "yes" ]
then
echo "Custom backup of $DATABASE"
if ! pg_dump -Fc -h "$HOSTNAME" -U "$USERNAME" "$DATABASE" | gzip --stdout | s3cmd --reduced-redundancy put - $FINAL_BACKUP_DIR"$DATABASE".custom.in_progress --no-encrypt; then
echo "[!!ERROR!!] Failed to produce custom backup database schema of $DATABASE" 1>&2
else
s3cmd mv $FINAL_BACKUP_DIR"$DATABASE".custom.in_progress $FINAL_BACKUP_DIR"$DATABASE".custom
fi
fi
done
echo -e "\nAll database backups complete!"
}
# MONTHLY BACKUPS
DAY_OF_MONTH=`date +%d`
if [ $DAY_OF_MONTH -eq 1 ];
then
# Delete all expired monthly directories
find $BACKUP_DIR -maxdepth 1 -name "*-monthly" -exec rm -rf '{}' ';'
perform_backups "-monthly"
exit 0;
fi
# WEEKLY BACKUPS
DAY_OF_WEEK=`date +%u` #1-7 (Monday-Sunday)
EXPIRED_DAYS=`expr $((($WEEKS_TO_KEEP * 7) + 1))`
if [ $DAY_OF_WEEK = $DAY_OF_WEEK_TO_KEEP ];
then
# Delete all expired weekly directories
find $BACKUP_DIR -maxdepth 1 -mtime +$EXPIRED_DAYS -name "*-weekly" -exec rm -rf '{}' ';'
perform_backups "-weekly"
exit 0;
fi
# DAILY BACKUPS
# Delete daily backups $DAYS_TO_KEEP days old or more
#find $BACKUP_DIR -maxdepth 1 -mtime +$DAYS_TO_KEEP -name "*-daily" -exec rm -rf '{}' ';'
#set $deldate to date minus $DAYS_TO_KEEP
deldate=`date +"%Y%m%d" --date="$DAYS_TO_KEEP days ago"`
#remove leading bucket name from s3 object displayed by "s3cmd ls $bucketname"
#compare first 8 chars of s3 object name (minus bucket name) with $deldate,
#if first 8 chars of s3 object name::int <= $deldate then delete those s3 objects
s3cmd ls $BACKUP_DIR | awk -v bucket="$BACKUP_DIR" -v deldate="$deldate" '{gsub(bucket,"",$4);if (substr($4,0,9)<=deldate) system("s3cmd info " bucket$4)}'
#replace s3cmd info by s3cmd del
perform_backups "-daily"