forked from evolix/evobackup
dynamically include dump files
This commit is contained in:
parent
45d0205cc1
commit
282bb6f1bc
|
@ -1,118 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2034,SC2317,SC2155
|
||||
|
||||
#######################################################################
|
||||
# Dump a single file of all PostgreSQL databases
|
||||
#
|
||||
# Arguments: <none>
|
||||
#######################################################################
|
||||
dump_postgresql_global() {
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/postgresql-global"
|
||||
local errors_dir=$(errors_dir_from_dump_dir "${dump_dir}")
|
||||
rm -rf "${dump_dir}" "${errors_dir}"
|
||||
mkdir -p "${dump_dir}" "${errors_dir}"
|
||||
# No need to change recursively, the top directory is enough
|
||||
chmod 700 "${dump_dir}" "${errors_dir}"
|
||||
|
||||
## example with pg_dumpall and with compression
|
||||
local error_file="${errors_dir}/pg_dumpall.err"
|
||||
local dump_file="${dump_dir}/pg_dumpall.sql.gz"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
(sudo -u postgres pg_dumpall) 2> "${error_file}" | gzip --best > "${dump_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${last_rc} -ne 0 ]; then
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: pg_dumpall to ${dump_file} returned an error ${last_rc}" "${error_file}"
|
||||
GLOBAL_RC=${E_DUMPFAILED}
|
||||
else
|
||||
rm -f "${error_file}"
|
||||
fi
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
|
||||
## example with pg_dumpall and without compression
|
||||
## WARNING: you need space in ~postgres
|
||||
# local error_file="${errors_dir}/pg_dumpall.err"
|
||||
# local dump_file="${dump_dir}/pg_dumpall.sql"
|
||||
# log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
#
|
||||
# (su - postgres -c "pg_dumpall > ~/pg.dump.bak") 2> "${error_file}"
|
||||
# mv ~postgres/pg.dump.bak "${dump_file}"
|
||||
#
|
||||
# log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Dump a compressed file per database
|
||||
#
|
||||
# Arguments: <none>
|
||||
#######################################################################
|
||||
dump_postgresql_per_base() {
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/postgresql-per-base"
|
||||
local errors_dir=$(errors_dir_from_dump_dir "${dump_dir}")
|
||||
rm -rf "${dump_dir}" "${errors_dir}"
|
||||
mkdir -p "${dump_dir}" "${errors_dir}"
|
||||
# No need to change recursively, the top directory is enough
|
||||
chmod 700 "${dump_dir}" "${errors_dir}"
|
||||
|
||||
(
|
||||
# shellcheck disable=SC2164
|
||||
cd /var/lib/postgresql
|
||||
databases=$(sudo -u postgres psql -U postgres -lt | awk -F\| '{print $1}' | grep -v "template.*")
|
||||
for database in ${databases} ; do
|
||||
local error_file="${errors_dir}/${database}.err"
|
||||
local dump_file="${dump_dir}/${database}.sql.gz"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
(sudo -u postgres /usr/bin/pg_dump --create -U postgres -d "${database}") 2> "${error_file}" | gzip --best > "${dump_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${last_rc} -ne 0 ]; then
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: pg_dump to ${dump_file} returned an error ${last_rc}" "${error_file}"
|
||||
GLOBAL_RC=${E_DUMPFAILED}
|
||||
else
|
||||
rm -f "${error_file}"
|
||||
fi
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Dump a compressed file per database
|
||||
#
|
||||
# Arguments: <none>
|
||||
#
|
||||
# TODO: add arguments to include/exclude tables
|
||||
#######################################################################
|
||||
dump_postgresql_filtered() {
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/postgresql-filtered"
|
||||
local errors_dir=$(errors_dir_from_dump_dir "${dump_dir}")
|
||||
rm -rf "${dump_dir}" "${errors_dir}"
|
||||
mkdir -p "${dump_dir}" "${errors_dir}"
|
||||
# No need to change recursively, the top directory is enough
|
||||
chmod 700 "${dump_dir}" "${errors_dir}"
|
||||
|
||||
local error_file="${errors_dir}/pg-backup.err"
|
||||
local dump_file="${dump_dir}/pg-backup.tar"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
## example with all tables from MYBASE excepts TABLE1 and TABLE2
|
||||
# pg_dump -p 5432 -h 127.0.0.1 -U USER --clean -F t --inserts -f "${dump_file}" -t 'TABLE1' -t 'TABLE2' MYBASE 2> "${error_file}"
|
||||
|
||||
## example with only TABLE1 and TABLE2 from MYBASE
|
||||
# pg_dump -p 5432 -h 127.0.0.1 -U USER --clean -F t --inserts -f "${dump_file}" -T 'TABLE1' -T 'TABLE2' MYBASE 2> "${error_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${last_rc} -ne 0 ]; then
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: pg_dump to ${dump_file} returned an error ${last_rc}" "${error_file}"
|
||||
GLOBAL_RC=${E_DUMPFAILED}
|
||||
else
|
||||
rm -f "${error_file}"
|
||||
fi
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
}
|
301
client/lib/dump/elasticsearch.sh
Normal file
301
client/lib/dump/elasticsearch.sh
Normal file
|
@ -0,0 +1,301 @@
|
|||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2034,SC2317,SC2155
|
||||
|
||||
#######################################################################
|
||||
# Snapshot Elasticsearch data
|
||||
#
|
||||
# Arguments:
|
||||
# --protocol=<http|https> (default: http)
|
||||
# --cacert=[String] (default: <none>)
|
||||
# path to the CA certificate to use when using https
|
||||
# --host=[String] (default: localhost)
|
||||
# --port=[Integer] (default: 9200)
|
||||
# --user=[String] (default: <none>)
|
||||
# --password=[String] (default: <none>)
|
||||
# --repository=[String] (default: snaprepo)
|
||||
# --snapshot=[String] (default: snapshot.daily)
|
||||
#######################################################################
|
||||
dump_elasticsearch() {
|
||||
local option_protocol="http"
|
||||
local option_cacert=""
|
||||
local option_host="localhost"
|
||||
local option_port="9200"
|
||||
local option_user=""
|
||||
local option_password=""
|
||||
local option_repository="snaprepo"
|
||||
local option_snapshot="snapshot.daily"
|
||||
local option_others=""
|
||||
|
||||
# Parse options, based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||
while :; do
|
||||
case ${1:-''} in
|
||||
--protocol)
|
||||
# protocol options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_protocol="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--protocol' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--protocol=?*)
|
||||
# protocol options, with value separated by =
|
||||
option_protocol="${1#*=}"
|
||||
;;
|
||||
--protocol=)
|
||||
# protocol options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--protocol' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--cacert)
|
||||
# cacert options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_cacert="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--cacert' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--cacert=?*)
|
||||
# cacert options, with value separated by =
|
||||
option_cacert="${1#*=}"
|
||||
;;
|
||||
--cacert=)
|
||||
# cacert options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--cacert' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--host)
|
||||
# host options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_host="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--host' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--host=?*)
|
||||
# host options, with value separated by =
|
||||
option_host="${1#*=}"
|
||||
;;
|
||||
--host=)
|
||||
# host options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--host' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--port)
|
||||
# port options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_port="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--port' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--port=?*)
|
||||
# port options, with value separated by =
|
||||
option_port="${1#*=}"
|
||||
;;
|
||||
--port=)
|
||||
# port options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--port' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--user)
|
||||
# user options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_user="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--user' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--user=?*)
|
||||
# user options, with value separated by =
|
||||
option_user="${1#*=}"
|
||||
;;
|
||||
--user=)
|
||||
# user options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--user' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--password)
|
||||
# password options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_password="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--password' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--password=?*)
|
||||
# password options, with value separated by =
|
||||
option_password="${1#*=}"
|
||||
;;
|
||||
--password=)
|
||||
# password options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--password' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--repository)
|
||||
# repository options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_repository="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--repository' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--repository=?*)
|
||||
# repository options, with value separated by =
|
||||
option_repository="${1#*=}"
|
||||
;;
|
||||
--repository=)
|
||||
# repository options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--repository' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--snapshot)
|
||||
# snapshot options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_snapshot="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--snapshot' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--snapshot=?*)
|
||||
# snapshot options, with value separated by =
|
||||
option_snapshot="${1#*=}"
|
||||
;;
|
||||
--snapshot=)
|
||||
# snapshot options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--snapshot' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--)
|
||||
# End of all options.
|
||||
shift
|
||||
option_others=${*}
|
||||
break
|
||||
;;
|
||||
-?*|[[:alnum:]]*)
|
||||
# ignore unknown options
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: unknown option '${1}' (ignored)"
|
||||
;;
|
||||
*)
|
||||
# Default case: If no more options then break out of the loop.
|
||||
break
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
# Use the default Elasticsearch CA certificate when using HTTPS, if not specified directly
|
||||
local default_cacert="/etc/elasticsearch/certs/http_ca.crt"
|
||||
if [ "${option_protocol}" = "https" ] && [ -z "${option_cacert}" ] && [ -f "${default_cacert}" ]; then
|
||||
option_cacert="${default_cacert}"
|
||||
fi
|
||||
|
||||
local errors_dir="${ERRORS_DIR}/elasticsearch-${option_repository}-${option_snapshot}"
|
||||
rm -rf "${errors_dir}"
|
||||
mkdir -p "${errors_dir}"
|
||||
# No need to change recursively, the top directory is enough
|
||||
chmod 700 "${errors_dir}"
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${option_snapshot}"
|
||||
|
||||
## Take a snapshot as a backup.
|
||||
## Warning: You need to have a path.repo configured.
|
||||
## See: https://wiki.evolix.org/HowtoElasticsearch#snapshots-et-sauvegardes
|
||||
|
||||
local base_url="${option_protocol}://${option_host}:${option_port}"
|
||||
local repository_url="${base_url}/_snapshot/${option_repository}"
|
||||
local snapshot_url="${repository_url}/${option_snapshot}"
|
||||
|
||||
# Verify snapshot repository
|
||||
|
||||
local error_file="${errors_dir}/verify.err"
|
||||
|
||||
declare -a connect_options
|
||||
connect_options=()
|
||||
if [ -n "${option_cacert}" ]; then
|
||||
connect_options+=(--cacert "${option_cacert}")
|
||||
fi
|
||||
if [ -n "${option_user}" ] || [ -n "${option_password}" ]; then
|
||||
local connect_options+=("--user ${option_user}:${option_password}")
|
||||
fi
|
||||
if [ -n "${option_others}" ]; then
|
||||
# word splitting is deliberate here
|
||||
# shellcheck disable=SC2206
|
||||
connect_options+=(${option_others})
|
||||
fi
|
||||
# Add the http return code at the end of the output
|
||||
connect_options+=(--write-out '%{http_code}\n')
|
||||
connect_options+=(--silent)
|
||||
|
||||
declare -a dump_options
|
||||
dump_options=()
|
||||
dump_options+=(--request POST)
|
||||
|
||||
dump_cmd="curl ${connect_options[*]} ${dump_options[*]} ${repository_url}/_verify?pretty"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd} > "${error_file}"
|
||||
|
||||
# test if the last line of the log file is "200"
|
||||
tail -n 1 "${error_file}" | grep --quiet "^200$" "${error_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${last_rc} -ne 0 ]; then
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: repository verification returned an error ${last_rc}" "${error_file}"
|
||||
GLOBAL_RC=${E_DUMPFAILED}
|
||||
else
|
||||
rm -f "${error_file}"
|
||||
|
||||
# Delete snapshot
|
||||
|
||||
declare -a dump_options
|
||||
dump_options=()
|
||||
dump_options+=(--request DELETE)
|
||||
|
||||
dump_cmd="curl ${connect_options[*]} ${dump_options[*]} ${snapshot_url}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd} > /dev/null
|
||||
|
||||
# Create snapshot
|
||||
|
||||
local error_file="${errors_dir}/create.err"
|
||||
|
||||
declare -a dump_options
|
||||
dump_options=()
|
||||
dump_options+=(--request PUT)
|
||||
|
||||
dump_cmd="curl ${connect_options[*]} ${dump_options[*]} ${snapshot_url}?wait_for_completion=true"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd} > "${error_file}"
|
||||
|
||||
# test if the last line of the log file is "200"
|
||||
tail -n 1 "${error_file}" | grep --quiet "^200$" "${error_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${last_rc} -ne 0 ]; then
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: curl returned an error ${last_rc}" "${error_file}"
|
||||
GLOBAL_RC=${E_DUMPFAILED}
|
||||
else
|
||||
rm -f "${error_file}"
|
||||
fi
|
||||
fi
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${option_snapshot}"
|
||||
}
|
|
@ -102,9 +102,9 @@ dump_redis() {
|
|||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_dir}"
|
||||
|
||||
# Copy the Redis database
|
||||
dump_cmd="cp -a ${instance}/dump.rdb ${dump_dir}/dump.rdb 2> ${error_file}"
|
||||
dump_cmd="cp -a ${instance}/dump.rdb ${dump_dir}/dump.rdb"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
${dump_cmd} 2> "${error_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -141,20 +141,46 @@ dump_redis() {
|
|||
# using a custom authentication, instead of /etc/mysql/debian.cnf
|
||||
#
|
||||
# Arguments:
|
||||
# --port=[String] (default: <blank>)
|
||||
# --user=[String] (default: <blank>)
|
||||
# --password=[String] (default: <blank>)
|
||||
# --dump-label=[String] (default: "default")
|
||||
# used as suffix of the dump dir to differenciate multiple instances
|
||||
# Other options after -- are passed as-is to mongodump
|
||||
#
|
||||
# don't forget to create use with read-only access
|
||||
# > use admin
|
||||
# > db.createUser( { user: "mongobackup", pwd: "PASS", roles: [ "backup", ] } )
|
||||
#######################################################################
|
||||
dump_mongodb() {
|
||||
local option_port=""
|
||||
local option_user=""
|
||||
local option_password=""
|
||||
local option_dump_label=""
|
||||
local option_others=""
|
||||
|
||||
# Parse options, based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||
while :; do
|
||||
case ${1:-''} in
|
||||
--port)
|
||||
# port options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_port="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--port' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--port=?*)
|
||||
# port options, with value separated by =
|
||||
option_port="${1#*=}"
|
||||
;;
|
||||
--port=)
|
||||
# port options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--port' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--user)
|
||||
# user options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
|
@ -193,9 +219,29 @@ dump_mongodb() {
|
|||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--password' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--dump-label)
|
||||
# dump-label options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_dump_label="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--dump-label' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--dump-label=?*)
|
||||
# dump-label options, with value separated by =
|
||||
option_dump_label="${1#*=}"
|
||||
;;
|
||||
--dump-label=)
|
||||
# dump-label options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--dump-label' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--)
|
||||
# End of all options.
|
||||
shift
|
||||
option_others=${*}
|
||||
break
|
||||
;;
|
||||
-?*|[[:alnum:]]*)
|
||||
|
@ -211,7 +257,15 @@ dump_mongodb() {
|
|||
shift
|
||||
done
|
||||
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/mongodump"
|
||||
if [ -z "${option_dump_label}" ]; then
|
||||
if [ -n "${option_port}" ]; then
|
||||
option_dump_label="${option_port}"
|
||||
else
|
||||
option_dump_label="default"
|
||||
fi
|
||||
fi
|
||||
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/mongodb-${option_dump_label}"
|
||||
local errors_dir=$(errors_dir_from_dump_dir "${dump_dir}")
|
||||
rm -rf "${dump_dir}" "${errors_dir}"
|
||||
mkdir -p "${dump_dir}" "${errors_dir}"
|
||||
|
@ -221,15 +275,27 @@ dump_mongodb() {
|
|||
local error_file="${errors_dir}.err"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_dir}"
|
||||
|
||||
declare -a options
|
||||
options=()
|
||||
options+=(--username="${option_user}")
|
||||
options+=(--password="${option_password}")
|
||||
options+=(--out="${dump_dir}/")
|
||||
declare -a dump_options
|
||||
dump_options=()
|
||||
if [ -n "${option_port}" ]; then
|
||||
dump_options+=(--port="${option_port}")
|
||||
fi
|
||||
if [ -n "${option_user}" ]; then
|
||||
dump_options+=(--username="${option_user}")
|
||||
fi
|
||||
if [ -n "${option_password}" ]; then
|
||||
dump_options+=(--password="${option_password}")
|
||||
fi
|
||||
dump_options+=(--out="${dump_dir}/")
|
||||
if [ -n "${option_others}" ]; then
|
||||
# word splitting is deliberate here
|
||||
# shellcheck disable=SC2206
|
||||
dump_options+=(${option_others})
|
||||
fi
|
||||
|
||||
dump_cmd=" mongodump ${options[*]} 2> ${error_file} > /dev/null"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
dump_cmd="mongodump ${dump_options[*]}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd} > /dev/null"
|
||||
${dump_cmd} 2> "${error_file}" > /dev/null
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -243,12 +309,12 @@ dump_mongodb() {
|
|||
}
|
||||
|
||||
#######################################################################
|
||||
# Dump MegaCLI configuration
|
||||
# Dump RAID configuration
|
||||
#
|
||||
# Arguments: <none>
|
||||
#######################################################################
|
||||
dump_megacli_config() {
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/megacli"
|
||||
dump_raid_config() {
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/raid"
|
||||
local errors_dir=$(errors_dir_from_dump_dir "${dump_dir}")
|
||||
rm -rf "${dump_dir}" "${errors_dir}"
|
||||
mkdir -p "${dump_dir}" "${errors_dir}"
|
||||
|
@ -260,9 +326,9 @@ dump_megacli_config() {
|
|||
local dump_file="${dump_dir}/megacli.err"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
dump_cmd="megacli -CfgSave -f ${dump_file} -a0 2> ${error_file}"
|
||||
dump_cmd="megacli -CfgSave -f ${dump_file} -a0"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
${dump_cmd} 2> "${error_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -273,15 +339,31 @@ dump_megacli_config() {
|
|||
rm -f "${error_file}"
|
||||
fi
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
elif command -v perccli > /dev/null; then
|
||||
local error_file="${errors_dir}/perccli.cfg"
|
||||
local dump_file="${dump_dir}/perccli.err"
|
||||
# log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
# TODO: find out what the correct command is
|
||||
|
||||
# dump_cmd="perccli XXXX"
|
||||
# log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
# ${dump_cmd} 2> ${error_file}
|
||||
|
||||
# local last_rc=$?
|
||||
# # shellcheck disable=SC2086
|
||||
# if [ ${last_rc} -ne 0 ]; then
|
||||
# log_error "LOCAL_TASKS - ${FUNCNAME[0]}: perccli to ${dump_file} returned an error ${last_rc}" "${error_file}"
|
||||
# GLOBAL_RC=${E_DUMPFAILED}
|
||||
# else
|
||||
# rm -f "${error_file}"
|
||||
# fi
|
||||
# log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
else
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: 'megacli' not found, unable to dump RAID configuration"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: 'megacli' and 'perccli' not found, unable to dump RAID configuration"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Save some traceroute/mtr results
|
||||
#
|
||||
|
@ -427,9 +509,9 @@ dump_rabbitmq() {
|
|||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
dump_cmd="rabbitmqadmin export ${dump_file} 2> ${error_file}"
|
||||
dump_cmd="rabbitmqadmin export ${dump_file}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
${dump_cmd} 2> "${error_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -475,432 +557,3 @@ dump_facl() {
|
|||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_dir}"
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Snapshot Elasticsearch data (single-node cluster)
|
||||
#
|
||||
# Arguments:
|
||||
# --protocol=[String] (default: http)
|
||||
# --host=[String] (default: localhost)
|
||||
# --port=[Integer] (default: 9200)
|
||||
# --user=[String] (default: <none>)
|
||||
# --password=[String] (default: <none>)
|
||||
# --repository=[String] (default: snaprepo)
|
||||
# --snapshot=[String] (default: snapshot.daily)
|
||||
#######################################################################
|
||||
dump_elasticsearch_snapshot_singlenode() {
|
||||
local option_protocol="http"
|
||||
local option_host="localhost"
|
||||
local option_port="9200"
|
||||
local option_user=""
|
||||
local option_password=""
|
||||
local option_repository="snaprepo"
|
||||
local option_snapshot="snapshot.daily"
|
||||
|
||||
# Parse options, based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||
while :; do
|
||||
case ${1:-''} in
|
||||
--protocol)
|
||||
# protocol options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_protocol="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--protocol' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--protocol=?*)
|
||||
# protocol options, with value separated by =
|
||||
option_protocol="${1#*=}"
|
||||
;;
|
||||
--protocol=)
|
||||
# protocol options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--protocol' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--host)
|
||||
# host options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_host="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--host' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--host=?*)
|
||||
# host options, with value separated by =
|
||||
option_host="${1#*=}"
|
||||
;;
|
||||
--host=)
|
||||
# host options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--host' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--port)
|
||||
# port options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_port="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--port' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--port=?*)
|
||||
# port options, with value separated by =
|
||||
option_port="${1#*=}"
|
||||
;;
|
||||
--port=)
|
||||
# port options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--port' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--user)
|
||||
# user options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_user="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--user' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--user=?*)
|
||||
# user options, with value separated by =
|
||||
option_user="${1#*=}"
|
||||
;;
|
||||
--user=)
|
||||
# user options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--user' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--password)
|
||||
# password options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_password="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--password' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--password=?*)
|
||||
# password options, with value separated by =
|
||||
option_password="${1#*=}"
|
||||
;;
|
||||
--password=)
|
||||
# password options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--password' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--repository)
|
||||
# repository options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_repository="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--repository' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--repository=?*)
|
||||
# repository options, with value separated by =
|
||||
option_repository="${1#*=}"
|
||||
;;
|
||||
--repository=)
|
||||
# repository options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--repository' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--snapshot)
|
||||
# snapshot options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_snapshot="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--snapshot' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--snapshot=?*)
|
||||
# snapshot options, with value separated by =
|
||||
option_snapshot="${1#*=}"
|
||||
;;
|
||||
--snapshot=)
|
||||
# snapshot options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--snapshot' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--)
|
||||
# End of all options.
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-?*|[[:alnum:]]*)
|
||||
# ignore unknown options
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: unknown option '${1}' (ignored)"
|
||||
;;
|
||||
*)
|
||||
# Default case: If no more options then break out of the loop.
|
||||
break
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${option_snapshot}"
|
||||
|
||||
## Take a snapshot as a backup.
|
||||
## Warning: You need to have a path.repo configured.
|
||||
## See: https://wiki.evolix.org/HowtoElasticsearch#snapshots-et-sauvegardes
|
||||
|
||||
local base_url="${option_protocol}://${option_host}:${option_port}"
|
||||
local snapshot_url="${base_url}/_snapshot/${option_repository}/${option_snapshot}"
|
||||
|
||||
if [ -n "${option_user}" ] || [ -n "${option_password}" ]; then
|
||||
local option_auth="--user ${option_user}:${option_password}"
|
||||
else
|
||||
local option_auth=""
|
||||
fi
|
||||
|
||||
curl -s -XDELETE "${option_auth}" "${snapshot_url}" >> "${LOGFILE}"
|
||||
curl -s -XPUT "${option_auth}" "${snapshot_url}?wait_for_completion=true" >> "${LOGFILE}"
|
||||
|
||||
# Clustered version here
|
||||
# It basically the same thing except that you need to check that NFS is mounted
|
||||
# if ss | grep ':nfs' | grep -q 'ip\.add\.res\.s1' && ss | grep ':nfs' | grep -q 'ip\.add\.res\.s2'
|
||||
# then
|
||||
# curl -s -XDELETE "${option_auth}" "${snapshot_url}" >> "${LOGFILE}"
|
||||
# curl -s -XPUT "${option_auth}" "${snapshot_url}?wait_for_completion=true" >> "${LOGFILE}"
|
||||
# else
|
||||
# echo 'Cannot make a snapshot of elasticsearch, at least one node is not mounting the repository.'
|
||||
# fi
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${option_snapshot}"
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Snapshot Elasticsearch data (multi-node cluster)
|
||||
#
|
||||
# Arguments:
|
||||
# --protocol=[String] (default: http)
|
||||
# --host=[String] (default: localhost)
|
||||
# --port=[Integer] (default: 9200)
|
||||
# --user=[String] (default: <none>)
|
||||
# --password=[String] (default: <none>)
|
||||
# --repository=[String] (default: snaprepo)
|
||||
# --snapshot=[String] (default: snapshot.daily)
|
||||
# --nfs-server=[IP|HOST] (default: <none>)
|
||||
#######################################################################
|
||||
dump_elasticsearch_snapshot_multinode() {
|
||||
local option_protocol="http"
|
||||
local option_host="localhost"
|
||||
local option_port="9200"
|
||||
local option_user=""
|
||||
local option_password=""
|
||||
local option_repository="snaprepo"
|
||||
local option_snapshot="snapshot.daily"
|
||||
local option_nfs_server=""
|
||||
|
||||
# Parse options, based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||
while :; do
|
||||
case ${1:-''} in
|
||||
--protocol)
|
||||
# protocol options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_protocol="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--protocol' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--protocol=?*)
|
||||
# protocol options, with value separated by =
|
||||
option_protocol="${1#*=}"
|
||||
;;
|
||||
--protocol=)
|
||||
# protocol options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--protocol' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--host)
|
||||
# host options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_host="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--host' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--host=?*)
|
||||
# host options, with value separated by =
|
||||
option_host="${1#*=}"
|
||||
;;
|
||||
--host=)
|
||||
# host options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--host' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--port)
|
||||
# port options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_port="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--port' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--port=?*)
|
||||
# port options, with value separated by =
|
||||
option_port="${1#*=}"
|
||||
;;
|
||||
--port=)
|
||||
# port options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--port' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--user)
|
||||
# user options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_user="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--user' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--user=?*)
|
||||
# user options, with value separated by =
|
||||
option_user="${1#*=}"
|
||||
;;
|
||||
--user=)
|
||||
# user options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--user' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--password)
|
||||
# password options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_password="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--password' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--password=?*)
|
||||
# password options, with value separated by =
|
||||
option_password="${1#*=}"
|
||||
;;
|
||||
--password=)
|
||||
# password options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--password' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--repository)
|
||||
# repository options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_repository="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--repository' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--repository=?*)
|
||||
# repository options, with value separated by =
|
||||
option_repository="${1#*=}"
|
||||
;;
|
||||
--repository=)
|
||||
# repository options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--repository' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--snapshot)
|
||||
# snapshot options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_snapshot="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--snapshot' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--snapshot=?*)
|
||||
# snapshot options, with value separated by =
|
||||
option_snapshot="${1#*=}"
|
||||
;;
|
||||
--snapshot=)
|
||||
# snapshot options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--snapshot' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--nfs-server)
|
||||
# nfs-server options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_nfs_server="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--nfs-server' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--nfs-server=?*)
|
||||
# nfs-server options, with value separated by =
|
||||
option_nfs_server="${1#*=}"
|
||||
;;
|
||||
--nfs-server=)
|
||||
# nfs-server options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--nfs-server' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--)
|
||||
# End of all options.
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-?*|[[:alnum:]]*)
|
||||
# ignore unknown options
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: unknown option '${1}' (ignored)"
|
||||
;;
|
||||
*)
|
||||
# Default case: If no more options then break out of the loop.
|
||||
break
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${option_snapshot}"
|
||||
|
||||
## Take a snapshot as a backup.
|
||||
## Warning: You need to have a path.repo configured.
|
||||
## See: https://wiki.evolix.org/HowtoElasticsearch#snapshots-et-sauvegardes
|
||||
|
||||
local base_url="${option_protocol}://${option_host}:${option_port}"
|
||||
local snapshot_url="${base_url}/_snapshot/${option_repository}/${option_snapshot}"
|
||||
|
||||
if [ -n "${option_user}" ] || [ -n "${option_password}" ]; then
|
||||
local option_auth="--user ${option_user}:${option_password}"
|
||||
else
|
||||
local option_auth=""
|
||||
fi
|
||||
|
||||
# Clustered version here
|
||||
# It basically the same thing except that you need to check that NFS is mounted
|
||||
if ss | grep ':nfs' | grep -q -F "${option_nfs_server}"; then
|
||||
curl -s -XDELETE "${option_auth}" "${snapshot_url}" >> "${LOGFILE}"
|
||||
curl -s -XPUT "${option_auth}" "${snapshot_url}?wait_for_completion=true" >> "${LOGFILE}"
|
||||
else
|
||||
echo 'Cannot make a snapshot of elasticsearch, at least one node is not mounting the repository.'
|
||||
fi
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${option_snapshot}"
|
||||
}
|
|
@ -254,9 +254,9 @@ dump_mysql_summary() {
|
|||
options=()
|
||||
options+=(--sleep=0)
|
||||
|
||||
dump_cmd="pt-mysql-summary ${options[*]} -- ${connect_options[*]} > ${dump_file}"
|
||||
dump_cmd="pt-mysql-summary ${options[*]} -- ${connect_options[*]}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd} 2> "${error_file}"
|
||||
${dump_cmd} 2> "${error_file}" > "${dump_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -470,9 +470,9 @@ dump_mysql_grants() {
|
|||
options+=(--flush)
|
||||
options+=(--no-header)
|
||||
|
||||
dump_cmd="pt-show-grants ${options[*]} > ${dump_file}"
|
||||
dump_cmd="pt-show-grants ${options[*]}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd} 2> "${error_file}"
|
||||
${dump_cmd} 2> "${error_file}" > "${dump_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -806,9 +806,12 @@ dump_mysql_global() {
|
|||
dump_options+=(${option_others})
|
||||
fi
|
||||
|
||||
## WARNING : logging and executing the command must be separate
|
||||
## because otherwise Bash would interpret | and > as strings and not syntax.
|
||||
|
||||
dump_cmd="mysqldump ${connect_options[*]} ${dump_options[*]} 2> ${error_file} | ${compress_cmd} > ${dump_file}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
mysqldump "${connect_options[@]}" "${dump_options[@]}" 2> "${error_file}" | ${compress_cmd} > "${dump_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -838,9 +841,9 @@ dump_mysql_global() {
|
|||
dump_options+=(${option_others})
|
||||
fi
|
||||
|
||||
dump_cmd="mysqldump ${connect_options[*]} ${dump_options[*]} 2> ${error_file} > ${dump_file}"
|
||||
dump_cmd="mysqldump ${connect_options[*]} ${dump_options[*]}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
${dump_cmd} 2> "${error_file}" > "${dump_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -1165,9 +1168,11 @@ dump_mysql_per_base() {
|
|||
dump_options+=(${option_others})
|
||||
fi
|
||||
|
||||
dump_cmd="mysqldump ${connect_options[*]} ${dump_options[*]} 2> ${error_file} | ${compress_cmd} > ${dump_file}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
## WARNING : logging and executing the command must be separate
|
||||
## because otherwise Bash would interpret | and > as strings and not syntax.
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: mysqldump ${connect_options[*]} ${dump_options[*]} | ${compress_cmd} > ${dump_file}"
|
||||
mysqldump "${connect_options[@]}" "${dump_options[@]}" 2> "${error_file}" | ${compress_cmd} > "${dump_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -1197,9 +1202,9 @@ dump_mysql_per_base() {
|
|||
dump_options+=(${option_others})
|
||||
fi
|
||||
|
||||
dump_cmd="mysqldump ${connect_options[*]} ${dump_options[*]} 2> ${error_file} > ${dump_file}"
|
||||
dump_cmd="mysqldump ${connect_options[*]} ${dump_options[*]}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
${dump_cmd} 2> "${error_file}" > "${dump_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -1529,9 +1534,9 @@ dump_mysql_tabs() {
|
|||
fi
|
||||
dump_options+=("${database}")
|
||||
|
||||
dump_cmd="mysqldump ${connect_options[*]} ${dump_options[*]} 2> ${error_file}"
|
||||
dump_cmd="mysqldump ${connect_options[*]} ${dump_options[*]}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
${dump_cmd} 2> "${error_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
343
client/lib/dump/postgresql.sh
Normal file
343
client/lib/dump/postgresql.sh
Normal file
|
@ -0,0 +1,343 @@
|
|||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2034,SC2317,SC2155
|
||||
|
||||
#######################################################################
|
||||
# Dump a single file of all PostgreSQL databases
|
||||
#
|
||||
# Arguments:
|
||||
# --dump-label=[String] (default: "default")
|
||||
# used as suffix of the dump dir to differenciate multiple instances
|
||||
# --compress=<gzip|pigz|bzip2|xz|none> (default: "gzip")
|
||||
# Other options after -- are passed as-is to pg_dump
|
||||
#######################################################################
|
||||
dump_postgresql_global() {
|
||||
local option_dump_label=""
|
||||
local option_compress=""
|
||||
local option_others=""
|
||||
|
||||
# Parse options, based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||
while :; do
|
||||
case ${1:-''} in
|
||||
--dump-label)
|
||||
# dump-label options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_dump_label="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--dump-label' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--dump-label=?*)
|
||||
# dump-label options, with value separated by =
|
||||
option_dump_label="${1#*=}"
|
||||
;;
|
||||
--dump-label=)
|
||||
# dump-label options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--dump-label' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--compress)
|
||||
# compress options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_compress="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--compress' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--compress=?*)
|
||||
# compress options, with value separated by =
|
||||
option_compress="${1#*=}"
|
||||
;;
|
||||
--compress=)
|
||||
# compress options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--compress' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--)
|
||||
# End of all options.
|
||||
shift
|
||||
option_others=${*}
|
||||
break
|
||||
;;
|
||||
-?*|[[:alnum:]]*)
|
||||
# ignore unknown options
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: unknown option '${1}' (ignored)"
|
||||
;;
|
||||
*)
|
||||
# Default case: If no more options then break out of the loop.
|
||||
break
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
case "${option_compress}" in
|
||||
none)
|
||||
compress_cmd="cat"
|
||||
dump_ext=""
|
||||
;;
|
||||
bzip2|bz|bz2)
|
||||
compress_cmd="bzip2 --best"
|
||||
dump_ext=".bz"
|
||||
;;
|
||||
xz)
|
||||
compress_cmd="xz --best"
|
||||
dump_ext=".xz"
|
||||
;;
|
||||
pigz)
|
||||
compress_cmd="pigz --best"
|
||||
dump_ext=".gz"
|
||||
;;
|
||||
gz|gzip|*)
|
||||
compress_cmd="gzip --best"
|
||||
dump_ext=".gz"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "${option_dump_label}" ]; then
|
||||
if [ -n "${option_defaults_group_suffix}" ]; then
|
||||
option_dump_label="${option_defaults_group_suffix}"
|
||||
elif [ -n "${option_port}" ]; then
|
||||
option_dump_label="${option_port}"
|
||||
elif [ -n "${option_socket}" ]; then
|
||||
option_dump_label=$(path_to_str "${option_socket}")
|
||||
else
|
||||
option_dump_label="default"
|
||||
fi
|
||||
fi
|
||||
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/postgresql-${option_dump_label}-global"
|
||||
local errors_dir=$(errors_dir_from_dump_dir "${dump_dir}")
|
||||
rm -rf "${dump_dir}" "${errors_dir}"
|
||||
mkdir -p "${dump_dir}" "${errors_dir}"
|
||||
# No need to change recursively, the top directory is enough
|
||||
chmod 700 "${dump_dir}" "${errors_dir}"
|
||||
|
||||
## example with pg_dumpall and with compression
|
||||
local error_file="${errors_dir}/pg_dumpall.err"
|
||||
local dump_file="${dump_dir}/pg_dumpall.sql${dump_ext}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
declare -a dump_options
|
||||
dump_options=()
|
||||
if [ -n "${option_others}" ]; then
|
||||
# word splitting is deliberate here
|
||||
# shellcheck disable=SC2206
|
||||
dump_options+=(${option_others})
|
||||
fi
|
||||
|
||||
dump_cmd="(sudo -u postgres pg_dumpall ${dump_options[*]}) 2> ${error_file} | ${compress_cmd} > ${dump_file}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${last_rc} -ne 0 ]; then
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: pg_dumpall to ${dump_file} returned an error ${last_rc}" "${error_file}"
|
||||
GLOBAL_RC=${E_DUMPFAILED}
|
||||
else
|
||||
rm -f "${error_file}"
|
||||
fi
|
||||
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
|
||||
## example with pg_dumpall and without compression
|
||||
## WARNING: you need space in ~postgres
|
||||
# local error_file="${errors_dir}/pg_dumpall.err"
|
||||
# local dump_file="${dump_dir}/pg_dumpall.sql"
|
||||
# log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
#
|
||||
# (su - postgres -c "pg_dumpall > ~/pg.dump.bak") 2> "${error_file}"
|
||||
# mv ~postgres/pg.dump.bak "${dump_file}"
|
||||
#
|
||||
# log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Dump a compressed file per database
|
||||
#
|
||||
# Arguments: <none>
|
||||
#######################################################################
|
||||
dump_postgresql_per_base() {
|
||||
local option_dump_label=""
|
||||
local option_compress=""
|
||||
local option_others=""
|
||||
|
||||
# Parse options, based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
|
||||
while :; do
|
||||
case ${1:-''} in
|
||||
--dump-label)
|
||||
# dump-label options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_dump_label="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--dump-label' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--dump-label=?*)
|
||||
# dump-label options, with value separated by =
|
||||
option_dump_label="${1#*=}"
|
||||
;;
|
||||
--dump-label=)
|
||||
# dump-label options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--dump-label' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--compress)
|
||||
# compress options, with value separated by space
|
||||
if [ -n "$2" ]; then
|
||||
option_compress="${2}"
|
||||
shift
|
||||
else
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--compress' requires a non-empty option argument."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--compress=?*)
|
||||
# compress options, with value separated by =
|
||||
option_compress="${1#*=}"
|
||||
;;
|
||||
--compress=)
|
||||
# compress options, without value
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: '--compress' requires a non-empty option argument."
|
||||
exit 1
|
||||
;;
|
||||
--)
|
||||
# End of all options.
|
||||
shift
|
||||
option_others=${*}
|
||||
break
|
||||
;;
|
||||
-?*|[[:alnum:]]*)
|
||||
# ignore unknown options
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: unknown option '${1}' (ignored)"
|
||||
;;
|
||||
*)
|
||||
# Default case: If no more options then break out of the loop.
|
||||
break
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
case "${option_compress}" in
|
||||
none)
|
||||
compress_cmd="cat"
|
||||
dump_ext=""
|
||||
;;
|
||||
bzip2|bz|bz2)
|
||||
compress_cmd="bzip2 --best"
|
||||
dump_ext=".bz"
|
||||
;;
|
||||
xz)
|
||||
compress_cmd="xz --best"
|
||||
dump_ext=".xz"
|
||||
;;
|
||||
pigz)
|
||||
compress_cmd="pigz --best"
|
||||
dump_ext=".gz"
|
||||
;;
|
||||
gz|gzip|*)
|
||||
compress_cmd="gzip --best"
|
||||
dump_ext=".gz"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "${option_dump_label}" ]; then
|
||||
if [ -n "${option_defaults_group_suffix}" ]; then
|
||||
option_dump_label="${option_defaults_group_suffix}"
|
||||
elif [ -n "${option_port}" ]; then
|
||||
option_dump_label="${option_port}"
|
||||
elif [ -n "${option_socket}" ]; then
|
||||
option_dump_label=$(path_to_str "${option_socket}")
|
||||
else
|
||||
option_dump_label="default"
|
||||
fi
|
||||
fi
|
||||
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/postgresql-${option_dump_label}-per-base"
|
||||
local errors_dir=$(errors_dir_from_dump_dir "${dump_dir}")
|
||||
rm -rf "${dump_dir}" "${errors_dir}"
|
||||
mkdir -p "${dump_dir}" "${errors_dir}"
|
||||
# No need to change recursively, the top directory is enough
|
||||
chmod 700 "${dump_dir}" "${errors_dir}"
|
||||
|
||||
(
|
||||
# shellcheck disable=SC2164
|
||||
cd /var/lib/postgresql
|
||||
databases=$(sudo -u postgres psql -U postgres -lt | awk -F \| '{print $1}' | grep -v "template.*")
|
||||
for database in ${databases} ; do
|
||||
local error_file="${errors_dir}/${database}.err"
|
||||
local dump_file="${dump_dir}/${database}.sql${dump_ext}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
declare -a dump_options
|
||||
dump_options=()
|
||||
dump_options+=(--create)
|
||||
dump_options+=(-U postgres)
|
||||
dump_options+=(-d "${database}")
|
||||
if [ -n "${option_others}" ]; then
|
||||
# word splitting is deliberate here
|
||||
# shellcheck disable=SC2206
|
||||
dump_options+=(${option_others})
|
||||
fi
|
||||
|
||||
dump_cmd="(sudo -u postgres /usr/bin/pg_dump ${dump_options[*]}) 2> ${error_file} | ${compress_cmd} > ${dump_file}"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: ${dump_cmd}"
|
||||
${dump_cmd}
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${last_rc} -ne 0 ]; then
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: pg_dump to ${dump_file} returned an error ${last_rc}" "${error_file}"
|
||||
GLOBAL_RC=${E_DUMPFAILED}
|
||||
else
|
||||
rm -f "${error_file}"
|
||||
fi
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Dump a compressed file per database
|
||||
#
|
||||
# Arguments: <none>
|
||||
#
|
||||
# TODO: add arguments to include/exclude tables
|
||||
#######################################################################
|
||||
dump_postgresql_filtered() {
|
||||
local dump_dir="${LOCAL_BACKUP_DIR}/postgresql-filtered"
|
||||
local errors_dir=$(errors_dir_from_dump_dir "${dump_dir}")
|
||||
rm -rf "${dump_dir}" "${errors_dir}"
|
||||
mkdir -p "${dump_dir}" "${errors_dir}"
|
||||
# No need to change recursively, the top directory is enough
|
||||
chmod 700 "${dump_dir}" "${errors_dir}"
|
||||
|
||||
local error_file="${errors_dir}/pg-backup.err"
|
||||
local dump_file="${dump_dir}/pg-backup.tar"
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: start ${dump_file}"
|
||||
|
||||
## example with all tables from MYBASE excepts TABLE1 and TABLE2
|
||||
# pg_dump -p 5432 -h 127.0.0.1 -U USER --clean -F t --inserts -f "${dump_file}" -t 'TABLE1' -t 'TABLE2' MYBASE 2> "${error_file}"
|
||||
|
||||
## example with only TABLE1 and TABLE2 from MYBASE
|
||||
# pg_dump -p 5432 -h 127.0.0.1 -U USER --clean -F t --inserts -f "${dump_file}" -T 'TABLE1' -T 'TABLE2' MYBASE 2> "${error_file}"
|
||||
|
||||
local last_rc=$?
|
||||
# shellcheck disable=SC2086
|
||||
if [ ${last_rc} -ne 0 ]; then
|
||||
log_error "LOCAL_TASKS - ${FUNCNAME[0]}: pg_dump to ${dump_file} returned an error ${last_rc}" "${error_file}"
|
||||
GLOBAL_RC=${E_DUMPFAILED}
|
||||
else
|
||||
rm -f "${error_file}"
|
||||
fi
|
||||
log "LOCAL_TASKS - ${FUNCNAME[0]}: stop ${dump_file}"
|
||||
}
|
|
@ -18,9 +18,7 @@ if [[ "${TRACE-0}" == "1" ]]; then
|
|||
fi
|
||||
|
||||
source "${LIBDIR}/utilities.sh"
|
||||
source "${LIBDIR}/dump-mysql.sh"
|
||||
source "${LIBDIR}/dump-postgresql.sh"
|
||||
source "${LIBDIR}/dump-misc.sh"
|
||||
source "${LIBDIR}"/dump/*.sh
|
||||
|
||||
# Called from main, it is wrapping the local_tasks function defined in the real script
|
||||
local_tasks_wrapper() {
|
||||
|
|
Loading…
Reference in a new issue