This repository has been archived by the owner on Jan 20, 2024. It is now read-only.
/
backup.sh
149 lines (134 loc) · 4.52 KB
/
backup.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
#!/usr/bin/env bash
CONFIG_FILE="/etc/backups.conf"
# A simple wrapper for a Gentoo ebuild-like `die`.
die() {
echo "$*" 1>&2
exit 1
}
# Source the configuration file.
[[ -f ${CONFIG_FILE} ]] || die "Cannot find ${CONFIG_FILE}. Exiting."
source ${CONFIG_FILE}
# Check the required / optional variables.
[[ -z ${BACKUP_DIR} ]] && die "BACKUP_DIR is not set."
[[ -z ${BACKUP_EXT} ]] && BACKUP_EXT=".tar.gz" # default compression format
[[ -z ${BACKUP_AGE} ]] && BACKUP_AGE=2 # 2 day-old backups stored by default
# Set the date to be inserted to tarball names.
BACKUP_DATE="$(date +%Y-%m-%d-%H-%M)"
# Wrapper around `mkdir -p`.
mkdir_p() {
[[ ! -d "${1}" ]] && mkdir -p "${1}" && \
echo "Created ${1} for you."
}
# Create the backup directory if it does not exist yet.
mkdir_p ${BACKUP_DIR}
# Creates an empty tar archive. Accepts a single parameter, the filename.
empty_archive() {
/usr/bin/env tar -cf "${1}" -T /dev/null --xattrs || \
die "Creating ${1} failed!"
# This works on BSD and Linux. Not tested with others.
}
# Accepts two parameters, the archive filename and the file to be added.
add_to_archive() {
/usr/bin/env tar --xattrs --append -pf 2>/dev/null "${1}" "${2}" || \
die "Adding ${2} to ${1} failed!"
}
clean_up() {
/usr/bin/env find "${1}" -ctime +${BACKUP_AGE} -delete || \
die "Cleanup failed!"
}
backup_docker() {
echo "Running a Docker volumes backup..."
if [[ -z ${BACKUP_DIR_DOCKER} ]]; then
BACKUP_DIR_DOCKER=${BACKUP_DIR}
fi
mkdir_p ${BACKUP_DIR_DOCKER}
filename="${BACKUP_DIR_DOCKER}/${BACKUP_DATE}-docker${BACKUP_EXT}"
# Check the presence of the Docker directory.
[[ -d /var/lib/docker ]] || die "Docker is likely to not be installed."
empty_archive ${filename}
add_to_archive ${filename} /var/lib/docker/volumes
}
backup_postgres() {
echo "Running a PostgreSQL databases backup..."
if [[ -z ${BACKUP_DIR_POSTGRES} ]]; then
BACKUP_DIR_POSTGRES=${BACKUP_DIR}
fi
mkdir_p ${BACKUP_DIR_POSTGRES}
filename="${BACKUP_DIR_POSTGRES}/${BACKUP_DATE}-postgres${BACKUP_EXT}"
# The databases need to be listed in a special variable.
[[ -z ${BACKUP_DATABASES} ]] && die "The databases list is not specified."
for database in "${BACKUP_DATABASES[@]}"; do
dump_name="${filename}-${database}"
pg_dump -Fc $database > ${dump_name} || \
die "Failed backing up database $database."
add_to_archive ${filename} ${dump_name}
rm ${dump_name}
done
}
backup_configs() {
echo "Running config files backups..."
if [[ -z ${BACKUP_DIR_CONFIGS} ]]; then
BACKUP_DIR_CONFIGS=${BACKUP_DIR}
fi
mkdir_p ${BACKUP_DIR_CONFIGS}
filename="${BACKUP_DIR_CONFIGS}/${BACKUP_DATE}-configs${BACKUP_EXT}"
# The files to be saved need to be listed in a special variable.
[[ -z ${BACKUP_FILES} ]] && \
die "The files to be backed up are not specified."
for file in "${BACKUP_FILES[@]}"; do
add_to_archive ${filename} $file
done
}
print_help() {
cat <<EOF
backup.sh: a simple backup script.
Usage:
backup.sh [flags]
Options:
-a | --all: run the default set of backups (configs and Docker as of now)
-p | --postgres: run the backups on PostgreSQL databases
-d | --docker: run the backups on Docker volumes
-c | --configs: run the backups on the files specified in /etc/backups.conf
--no-cleanup: don't cleanup after the backup has finished
EOF
}
case ${1} in
"-a" | "--all")
backup_configs
backup_docker
# backup_postgres
# This is commented out by default, as PostgreSQL backups might be
# preferable to run under a separate user.
;;
"-h" | "--help")
print_help
BACKUP_NO_CLEANUP=1 # prevent cleanup on displaying help
;;
*)
while [[ ! -z ${1} ]]; do
case ${1} in
"-d" | "--docker")
backup_docker
;;
"-p" | "--postgres")
backup_postgres
;;
"-c" | "--configs")
backup_configs
;;
"--no-cleanup")
BACKUP_NO_CLEANUP=1
;;
esac
shift
done
;;
esac
if [[ -z ${BACKUP_NO_CLEANUP} ]]; then
echo "Cleaning up..."
# Run cleanup on every backup directory.
for i in ${BACKUP_DIR} ${BACKUP_DIR_CONFIGS} ${BACKUP_DIR_DOCKER} \
${BACKUP_DIR_POSTGRES}; do
[[ ! -z $i ]] && clean_up $i
done
fi