Compare commits

...

25 Commits

Author SHA1 Message Date
Clemens Schwaighofer
acd5d369eb Merge branch 'development' into shellcheck-cleanup 2025-08-20 22:41:54 +09:00
Clemens Schwaighofer
07896af1ae Zabbix port override settings fix
use OPT var prefix for options
add missing init in functions init
2025-08-20 22:37:37 +09:00
Clemens Schwaighofer
8de971b922 Fix Zabbix db port override settings 2025-08-20 22:16:49 +09:00
Clemens Schwaighofer
e7699015c5 Allow override of zabbix db port 2025-08-20 22:14:19 +09:00
Clemens Schwaighofer
de9d5d3588 Zabbix backup set port to 5432 default to override internal set ports 2025-08-20 22:11:38 +09:00
Clemens Schwaighofer
8407defe4f Starting shellcheck cleanup 2024-09-04 10:58:48 +09:00
Clemens Schwaighofer
28dd6cb911 Merge branch 'master' into development 2024-09-04 10:38:58 +09:00
Clemens Schwaighofer
ab47692848 borg backup default settings file sample update 2024-09-04 10:37:36 +09:00
Clemens Schwaighofer
4267cb5b32 Bug Fix in gitea backup for temp dir check 2024-09-04 10:37:16 +09:00
Clemens Schwaighofer
f24daba195 Add shellcheckrc 2024-09-03 12:40:39 +09:00
Clemens Schwaighofer
98890b87f5 gitea module fix chown call
do not use ".", use ":" for username and group separator
2024-06-11 10:33:47 +09:00
Clemens Schwaighofer
a5bc90bb89 Text fix in PostgreSQL backup module 2024-06-10 09:52:06 +09:00
Clemens Schwaighofer
5af6a84d5f Mysql/PostgreSQL module version string update 2024-06-07 15:08:49 +09:00
Clemens Schwaighofer
14d71f3053 Naming update for full update info text 2024-06-07 15:08:20 +09:00
Clemens Schwaighofer
24d4fb694f Typo in postgresql module for full dump filename 2024-06-07 14:25:00 +09:00
Clemens Schwaighofer
f9fbbcc6de Version fix for master script 2024-06-07 09:57:21 +09:00
Clemens Schwaighofer
64e876a9a4 Fix run time output template string 2024-06-07 09:56:51 +09:00
Clemens Schwaighofer
694e54ca9c Missed out duration calculation in postgresql run time output 2024-06-07 09:16:52 +09:00
Clemens Schwaighofer
09bd6015ac Version update for modules gitea, mysql, postgresql 2024-06-07 09:12:04 +09:00
Clemens Schwaighofer
5b8b0afec2 Fix not initialized new gitea variable names 2024-06-07 09:09:02 +09:00
Clemens Schwaighofer
0cc7e574fe Borg backup update for gitea dump, mysql/postgresql info block
Gitea dump has now settings for
- temp folder (GITEA_TEMP_DIR)
- new name for working dir (GITEA_WORKING_DIR) from old (GITEA_TMP)

MySQL and PostgreSQL exports have a run time output per db dump set and not only at the end of the full run
2024-06-06 10:30:48 +09:00
Clemens Schwaighofer
beffbee20c Add missing OPT_REMOTE to commands
check, compact commands had OPT_REMOTE missing
2023-05-10 16:30:23 +09:00
Clemens Schwaighofer
72f3f86eb6 Test for different command lookup check 2022-11-22 09:36:30 +09:00
Clemens Schwaighofer
c0f9634442 add *.compact to git ignore file 2022-11-14 20:27:42 +09:00
Clemens Schwaighofer
0e379d6ce0 Bump borg file module version number 2022-08-30 10:00:05 +09:00
19 changed files with 209 additions and 157 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ borg.backup.*.include
borg.backup.*.exclude borg.backup.*.exclude
borg.backup.*.schema-only borg.backup.*.schema-only
borg.backup.*.init borg.backup.*.init
borg.backup.*.compact

2
.shellcheckrc Normal file
View File

@@ -0,0 +1,2 @@
shell=bash
external-sources=true

View File

@@ -220,10 +220,10 @@ The postgres user must be added to the backup group for this, so that the basic
### PostgreSQL Config variables ### PostgreSQL Config variables
Variable | Default | Description | Variable | Default | Description |
| - | - | - | | - | - | - |
DATABASE_FULL_DUMP | | if empty, dump per databse, if set dump all in one file, if set to schema dump only schema | DATABASE_FULL_DUMP | | if empty, dump per databse, if set dump all in one file, if set to schema dump only schema |
DATABASE_USER | | overide username to connect to database | DATABASE_USER | | overide username to connect to database |
### PostgreSQL Control files ### PostgreSQL Control files
@@ -239,10 +239,10 @@ If non root ident authentication run is used, be sure that the `mysql` user is i
### MySQL Config variables ### MySQL Config variables
Variable | Default | Description | Variable | Default | Description |
| - | - | - | | - | - | - |
DATABASE_FULL_DUMP | | if empty, dump per databse, if set dump all in one file, if set to schema dump only schema | DATABASE_FULL_DUMP | | if empty, dump per databse, if set dump all in one file, if set to schema dump only schema |
MYSQL_DB_CONFIG | | override file for connection. In modern mariaDB installations it is rcommended to run the script as root or mysql user and use the ident authentication instead. | MYSQL_DB_CONFIG | | override file for connection. In modern mariaDB installations it is rcommended to run the script as root or mysql user and use the ident authentication instead. |
### MySQLControl files ### MySQLControl files
@@ -259,12 +259,13 @@ This user is neede to create the temporary dump folder and access for the git fi
### gitea Config Variables ### gitea Config Variables
Variable | Default | Description | Variable | Default | Description |
| - | - | - | | - | - | - |
GIT_USER | git | The user that runs gitea | | GIT_USER | git | The user that runs gitea |
GITEA_TMP | /tmp/gitea/ | Where the temporary dump files from the backup are stored, as user git | | GITEA_WORKING_DIR | /var/tmp/gitea/ | Where the temporary dump files from the backup are stored, as user git |
GITEA_BIN | /usr/local/bin/gitea | Where the gitea binary is located | | GITEA_TEMP_DIR | /var/tmp/ | General temporary folder |
GITEA_CONFIG | /etc/gitea/app.ini | The configuration file for gitea | | GITEA_BIN | /usr/local/bin/gitea | Where the gitea binary is located |
| GITEA_CONFIG | /etc/gitea/app.ini | The configuration file for gitea |
### gitea Control files ### gitea Control files
@@ -274,12 +275,12 @@ There are no control files for gitea backup
### zabbix Config Variables ### zabbix Config Variables
Variable | Default | Description | Variable | Default | Description |
| - | - | - | | - | - | - |
ZABBIX_DUMP | /usr/local/bin/zabbix-dump | | ZABBIX_DUMP | /usr/local/bin/zabbix-dump | |
ZABBIX_DATABASE | '' | Must be set as either psql or mysql | ZABBIX_DATABASE | '' | Must be set as either psql or mysql |
ZABBIX_CONFIG | '' | if not set uses default location | ZABBIX_CONFIG | '' | if not set uses default location |
ZABBIX_UNKNOWN_TABLES | '' | if set, changed to -f (force) | ZABBIX_UNKNOWN_TABLES | '' | if set, changed to -f (force) |
### zabbix Control files ### zabbix Control files

View File

@@ -31,16 +31,16 @@ MODULE_LIST="file gitea mysql pgsql zabbix"
# -n for dry run test # -n for dry run test
while getopts ":c:snd" opt; do while getopts ":c:snd" opt; do
case "${opt}" in case "${opt}" in
c|config) c) # config
BASE_FOLDER=${OPTARG}; BASE_FOLDER=${OPTARG};
;; ;;
s|nosudo) s) # nosudo
PGSQL_SUDO=0; PGSQL_SUDO=0;
;; ;;
d|debug) d) # debug
DEBUG=1; DEBUG=1;
;; ;;
n|dryrun) n) # dryrun
DRYRUN=1; DRYRUN=1;
;; ;;
:) :)
@@ -64,9 +64,10 @@ if [ ! -f "${BASE_FOLDER}${SETTINGS_FILE}" ]; then
echo "Could not find: ${BASE_FOLDER}${SETTINGS_FILE}"; echo "Could not find: ${BASE_FOLDER}${SETTINGS_FILE}";
exit; exit;
fi; fi;
# shellcheck source="borg.backup.settings"
. "${BASE_FOLDER}${SETTINGS_FILE}"; . "${BASE_FOLDER}${SETTINGS_FILE}";
if [ ! -z "${TARGET_BORG_PATH}" ]; then if [ -n "${TARGET_BORG_PATH}" ]; then
OPT_REMOTE="--remote-path="$(printf "%q" "${TARGET_BORG_PATH}"); OPT_REMOTE="--remote-path="$(printf "%q" "${TARGET_BORG_PATH}");
fi; fi;
export BORG_BASE_DIR="${BASE_FOLDER}"; export BORG_BASE_DIR="${BASE_FOLDER}";
@@ -82,16 +83,16 @@ for MODULE in ${MODULE_LIST}; do
TARGET_FOLDER=${TARGET_FOLDER#/} TARGET_FOLDER=${TARGET_FOLDER#/}
# and add slash front and back and escape the path # and add slash front and back and escape the path
TARGET_FOLDER=$(printf "%q" "/${TARGET_FOLDER}/"); TARGET_FOLDER=$(printf "%q" "/${TARGET_FOLDER}/");
if [ ! -z "${TARGET_USER}" ] && [ ! -z "${TARGET_HOST}" ] && [ ! -z "${TARGET_PORT}" ]; then if [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ] && [ -n "${TARGET_PORT}" ]; then
TARGET_SERVER="ssh://${TARGET_USER}@${TARGET_HOST}:${TARGET_PORT}/"; TARGET_SERVER="ssh://${TARGET_USER}@${TARGET_HOST}:${TARGET_PORT}/";
# host/port # host/port
elif [ ! -z "${TARGET_HOST}" ] && [ ! -z "${TARGET_PORT}" ]; then elif [ -n "${TARGET_HOST}" ] && [ -n "${TARGET_PORT}" ]; then
TARGET_SERVER="ssh://${TARGET_HOST}:${TARGET_PORT}/"; TARGET_SERVER="ssh://${TARGET_HOST}:${TARGET_PORT}/";
# user/host # user/host
elif [ ! -z "${TARGET_USER}" ] && [ ! -z "${TARGET_HOST}" ]; then elif [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_USER}@${TARGET_HOST}:"; TARGET_SERVER="${TARGET_USER}@${TARGET_HOST}:";
# host # host
elif [ ! -z "${TARGET_HOST}" ]; then elif [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_HOST}:"; TARGET_SERVER="${TARGET_HOST}:";
fi; fi;
# we dont allow special characters, so we don't need to special escape it # we dont allow special characters, so we don't need to special escape it
@@ -112,14 +113,14 @@ for MODULE in ${MODULE_LIST}; do
if [ "${MODULE}" = "gitea" ]; then if [ "${MODULE}" = "gitea" ]; then
# if just date, add gitea, # if just date, add gitea,
# else rename # else rename
if [ ! -z "${i##gitea*}" ]; then if [ -n "${i##gitea*}" ]; then
target_name="${MODULE},${i}"; target_name="${MODULE},${i}";
else else
target_name=$(echo $i | sed -e 's/gitea-/gitea,/'); target_name=$(echo $i | sed -e 's/gitea-/gitea,/');
fi; fi;
elif [ "${MODULE}" = "zabbix" ]; then elif [ "${MODULE}" = "zabbix" ]; then
# if zabbix is missing, prefix # if zabbix is missing, prefix
if [ ! -z "${i##zabbix*}" ]; then if [ -n "${i##zabbix*}" ]; then
target_name="${MODULE},${i}"; target_name="${MODULE},${i}";
else else
target_name=$(echo $i | sed -e 's/zabbix-settings-/zabbix,settings-/'); target_name=$(echo $i | sed -e 's/zabbix-settings-/zabbix,settings-/');

View File

@@ -4,7 +4,7 @@
# set last edit date + time # set last edit date + time
MODULE="file"; MODULE="file";
MODULE_VERSION="1.2.2"; MODULE_VERSION="1.2.3";
DIR="${BASH_SOURCE%/*}" DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
@@ -45,7 +45,7 @@ while read include_folder; do
echo "# [C] Comment: '${include_folder}'"; echo "# [C] Comment: '${include_folder}'";
else else
# skip if it is empty # skip if it is empty
if [ ! -z "${include_folder}" ]; then if [ -n "${include_folder}" ]; then
# if this is a glob, do a double check that the base folder actually exists (?) # if this is a glob, do a double check that the base folder actually exists (?)
if [[ "${include_folder}" =~ $REGEX_GLOB ]]; then if [[ "${include_folder}" =~ $REGEX_GLOB ]]; then
# if this is */ then allow it # if this is */ then allow it
@@ -99,7 +99,7 @@ if [ -s "${BASE_FOLDER}${EXCLUDE_FILE}" ]; then
# remove non valid ones and warn # remove non valid ones and warn
#TMP_EXCLUDE_FILE=$(mktemp --tmpdir ${EXCLUDE_FILE}.XXXXXXXX); # non mac #TMP_EXCLUDE_FILE=$(mktemp --tmpdir ${EXCLUDE_FILE}.XXXXXXXX); # non mac
TMP_EXCLUDE_FILE=$(mktemp "${TEMPDIR}${EXCLUDE_FILE}".XXXXXXXX); TMP_EXCLUDE_FILE=$(mktemp "${TEMPDIR}${EXCLUDE_FILE}".XXXXXXXX);
while read exclude_folder; do while read -r exclude_folder; do
# strip any leading spaces from that folder # strip any leading spaces from that folder
exclude_folder=$(echo "${exclude_folder}" | sed -e 's/^[ \t]*//'); exclude_folder=$(echo "${exclude_folder}" | sed -e 's/^[ \t]*//');
# folder or any type of file is ok # folder or any type of file is ok
@@ -108,7 +108,7 @@ if [ -s "${BASE_FOLDER}${EXCLUDE_FILE}" ]; then
echo "# [C] Comment: '${exclude_folder}'"; echo "# [C] Comment: '${exclude_folder}'";
else else
# skip if it is empty # skip if it is empty
if [ ! -z "${exclude_folder}" ]; then if [ -n "${exclude_folder}" ]; then
# if it DOES NOT start with a / we assume free folder and add as is # if it DOES NOT start with a / we assume free folder and add as is
if [[ "${exclude_folder}" != /* ]]; then if [[ "${exclude_folder}" != /* ]]; then
echo "${exclude_folder}" >> ${TMP_EXCLUDE_FILE}; echo "${exclude_folder}" >> ${TMP_EXCLUDE_FILE};

View File

@@ -54,20 +54,20 @@ if [ ${RUN_CHECK} -eq 1 ]; then
OPT_GLOB=""; OPT_GLOB="";
if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then
OPT_GLOB="-a '${CHECK_PREFIX}'" OPT_GLOB="-a '${CHECK_PREFIX}'"
elif [ ! -z "${CHECK_PREFIX}" ]; then elif [ -n "${CHECK_PREFIX}" ]; then
OPT_GLOB="-P ${CHECK_PREFIX}"; OPT_GLOB="-P ${CHECK_PREFIX}";
fi; fi;
# debug/dryrun # debug/dryrun
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} check ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} ${OPT_GLOB} ${REPOSITORY}"; echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} check ${OPT_REMOTE} ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} ${OPT_GLOB} ${REPOSITORY}";
fi; fi;
# run info command if not a dry drun # run info command if not a dry drun
if [ ${DRYRUN} -eq 0 ]; then if [ ${DRYRUN} -eq 0 ]; then
# if glob add glob command directly # if glob add glob command directly
if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then
${BORG_COMMAND} check ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} -a "${CHECK_PREFIX}" ${REPOSITORY}; ${BORG_COMMAND} check ${OPT_REMOTE} ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} -a "${CHECK_PREFIX}" ${REPOSITORY};
else else
${BORG_COMMAND} check ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} ${OPT_GLOB} ${REPOSITORY}; ${BORG_COMMAND} check ${OPT_REMOTE} ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} ${OPT_GLOB} ${REPOSITORY};
fi; fi;
fi; fi;
# print additional info for use --repair command # print additional info for use --repair command
@@ -75,7 +75,7 @@ if [ ${RUN_CHECK} -eq 1 ]; then
if [ ${VERBOSE} -eq 1 ] && [ ${CHECK} -eq 1 ]; then if [ ${VERBOSE} -eq 1 ] && [ ${CHECK} -eq 1 ]; then
echo ""; echo "";
echo "In case of needed repair: " echo "In case of needed repair: "
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} check ${OPT_PROGRESS} --repair ${OPT_GLOB} ${REPOSITORY}"; echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} check ${OPT_REMOTE} ${OPT_PROGRESS} --repair ${OPT_GLOB} ${REPOSITORY}";
echo "Before running repair, a copy from the backup should be made because repair might damage a backup" echo "Before running repair, a copy from the backup should be made because repair might damage a backup"
fi; fi;
fi; fi;

View File

@@ -16,7 +16,7 @@ if [ $# -ge 1 ] && [ "$1" = "1" ]; then
printf "${PRINTF_MASTER_BLOCK}" "ERROR" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_MASTER_BLOCK}" "ERROR" "$(date +'%F %T')" "${MODULE}";
else else
# running time calculation # running time calculation
DURATION=$[ $(date +'%s')-$START ]; DURATION=$(( $(date +'%s')-START ));
echo "=== [Run time: $(convert_time ${DURATION})]"; echo "=== [Run time: $(convert_time ${DURATION})]";
printf "${PRINTF_MASTER_BLOCK}" "END" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_MASTER_BLOCK}" "END" "$(date +'%F %T')" "${MODULE}";
fi; fi;

View File

@@ -7,7 +7,7 @@ fi;
# compact (only if BORG COMPACT is set) # compact (only if BORG COMPACT is set)
# only for borg 1.2 # only for borg 1.2
if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
RUN_COMPACT=0; RUN_COMPACT=0;
if [ $# -ge 1 ] && [ "$1" = "auto" ]; then if [ $# -ge 1 ] && [ "$1" = "auto" ]; then
# strip any spaces and convert to int # strip any spaces and convert to int
@@ -18,11 +18,11 @@ if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then
fi; fi;
# get current date timestmap # get current date timestmap
CURRENT_DATE=$(date +%s); CURRENT_DATE=$(date +%s);
if [ ${COMPACT_INTERVAL} -eq 1 ]; then if [ "${COMPACT_INTERVAL}" -eq 1 ]; then
RUN_COMPACT=1; RUN_COMPACT=1;
# set new compact time here # set new compact time here
echo ${CURRENT_DATE} > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}"; echo "${CURRENT_DATE}" > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
elif [ ${COMPACT_INTERVAL} -gt 1 ]; then elif [ "${COMPACT_INTERVAL}" -gt 1 ]; then
# else load last timestamp and check if today - last time stamp > days # else load last timestamp and check if today - last time stamp > days
if [ -z "${LAST_COMPACT_DATE}" ]; then if [ -z "${LAST_COMPACT_DATE}" ]; then
LAST_COMPACT_DATE=$(cat "${BASE_FOLDER}${BACKUP_COMPACT_FILE}" 2>/dev/null | sed -e 's/ //g'); LAST_COMPACT_DATE=$(cat "${BASE_FOLDER}${BACKUP_COMPACT_FILE}" 2>/dev/null | sed -e 's/ //g');
@@ -32,25 +32,26 @@ if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then
LAST_COMPACT_DATE=0; LAST_COMPACT_DATE=0;
fi; fi;
# if the difference greate than compact date, run. COMPACT INTERVAL is in days # if the difference greate than compact date, run. COMPACT INTERVAL is in days
if [ $(($CURRENT_DATE-$LAST_COMPACT_DATE)) -ge $((${COMPACT_INTERVAL}*86400)) ]; then if [ $((CURRENT_DATE-LAST_COMPACT_DATE)) -ge $((COMPACT_INTERVAL*86400)) ]; then
RUN_COMPACT=1; RUN_COMPACT=1;
# set new compact time here # set new compact time here
echo ${CURRENT_DATE} > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}"; echo "${CURRENT_DATE}" > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
fi; fi;
fi; fi;
elif [ ${COMPACT} -eq 1 ]; then elif [ "${COMPACT}" -eq 1 ]; then
RUN_COMPACT=1; RUN_COMPACT=1;
fi; fi;
if [ ${RUN_COMPACT} -eq 1 ]; then if [ ${RUN_COMPACT} -eq 1 ]; then
# reset to normal IFS, so command works here # reset to normal IFS, so command works here
IFS=${_IFS}; IFS=${_IFS};
# shellcheck disable=SC2059
printf "${PRINTF_SUB_BLOCK}" "COMPACT" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "COMPACT" "$(date +'%F %T')" "${MODULE}";
BORG_COMPACT="${BORG_COMMAND} compact -v ${OPT_PROGRESS} ${REPOSITORY}"; BORG_COMPACT="${BORG_COMMAND} compact ${OPT_REMOTE} -v ${OPT_PROGRESS} ${REPOSITORY}";
if [ ${DEBUG} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMPACT}"; echo "${BORG_COMPACT}";
fi; fi;
if [ ${DRYRUN} -eq 0 ]; then if [ "${DRYRUN}" -eq 0 ]; then
${BORG_COMPACT}; ${BORG_COMPACT};
fi; fi;
fi; fi;

View File

@@ -5,21 +5,21 @@ if [ -z "${MODULE}" ]; then
exit 1; exit 1;
fi; fi;
if [ ${INFO} -eq 1 ]; then if [ "${INFO}" -eq 1 ]; then
printf "${PRINTF_SUB_BLOCK}" "INFO" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "INFO" "$(date +'%F %T')" "${MODULE}";
# show command on debug or dry run # show command on debug or dry run
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ] || [ "${DRYRUN}" -eq 1 ]; then
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY}"; echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY}";
fi; fi;
# run info command if not a dry drun # run info command if not a dry drun
if [ ${DRYRUN} -eq 0 ]; then if [ "${DRYRUN}" -eq 0 ]; then
${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY}; ${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY};
fi; fi;
if [ "${MODULE}" = "files" ]; then if [ "${MODULE}" = "files" ]; then
if [ $FOLDER_OK -eq 1 ]; then if [ "$FOLDER_OK" -eq 1 ]; then
echo "--- [Run command]:"; echo "--- [Run command]:";
#IFS="#"; #IFS="#";
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${COMMAND} "${FOLDERS_Q[*]}; echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${COMMAND} ${FOLDERS_Q[*]}";
else else
echo "[!] No folders where set for the backup"; echo "[!] No folders where set for the backup";
fi; fi;

View File

@@ -24,7 +24,7 @@ function version {
} }
# version for all general files # version for all general files
VERSION="4.4.0"; VERSION="4.5.4";
# borg version and borg comamnd # borg version and borg comamnd
BORG_VERSION=""; BORG_VERSION="";
@@ -95,7 +95,8 @@ PRINTF_INFO_STRING="%-23s: %s\n";
PRINTF_MASTER_BLOCK="=== [%-8s: %19s] ==[%s]====================================>\n"; PRINTF_MASTER_BLOCK="=== [%-8s: %19s] ==[%s]====================================>\n";
PRINTF_SUB_BLOCK="|-- [%-8s: %19s] --[%s]------------------------------------>\n"; PRINTF_SUB_BLOCK="|-- [%-8s: %19s] --[%s]------------------------------------>\n";
PRINTF_SUBEXT_BLOCK="|-- [%-8s: %s: %19s] --[%s]------------------------------------>\n"; PRINTF_SUBEXT_BLOCK="|-- [%-8s: %s: %19s] --[%s]------------------------------------>\n";
PRINTF_DB_SUB_BLOCK=">>- [%-8s: %s] =======================[%s]====================================>\n"; PRINTF_DB_SUB_BLOCK="|>- [%-8s: %s] ==[%s]=======================>\n";
PRINTF_DB_RUN_TIME_SUB_BLOCK=">>- [%-8s: %s] ==[%s]==[Run time: %s]=======================>\n";
# opt flags # opt flags
OPT_VERBOSE=""; OPT_VERBOSE="";
OPT_PROGRESS=""; OPT_PROGRESS="";
@@ -152,17 +153,21 @@ MYSQL_DB_CONFIG="";
MYSQL_DB_CONFIG_PARAM=""; MYSQL_DB_CONFIG_PARAM="";
# gitea module # gitea module
GIT_USER=""; GIT_USER="";
GITEA_TMP=""; GITEA_WORKING_DIR="";
GITEA_TEMP_DIR="";
GITEA_BIN=""; GITEA_BIN="";
GITEA_CONFIG=""; GITEA_CONFIG="";
GITEA_EXPORT_TYPE="";
# zabbix module # zabbix module
ZABBIX_DUMP_BIN=""; ZABBIX_DUMP_BIN="";
ZABBIX_CONFIG=""; ZABBIX_CONFIG="";
ZABBIX_DATABASE=""; ZABBIX_DATABASE="";
ZABBIX_UNKNOWN_TABLES=""; ZABBIX_UNKNOWN_TABLES="";
ZABBIX_DB_PORT="";
OPT_ZABBIX_DUMP=""; OPT_ZABBIX_DUMP="";
OPT_ZABBIX_CONFIG=""; OPT_ZABBIX_CONFIG="";
OPT_ZABBIX_UNKNOWN_TABLES=""; OPT_ZABBIX_UNKNOWN_TABLES="";
OPT_ZABBIX_DB_PORT="";
# default keep 7 days, 4 weeks, 6 months, 1 year # default keep 7 days, 4 weeks, 6 months, 1 year
# if set 0, ignore/off # if set 0, ignore/off
# note that for last/hourly it is needed to create a different # note that for last/hourly it is needed to create a different
@@ -334,26 +339,26 @@ if [ ${PRINT} -eq 1 ] && ([ ${INIT} -eq 1 ] || [ ${VERIFY} -eq 1 ] || [ ${INFO}
exit 1; exit 1;
fi; fi;
# if tag is set, you can't have init, verify, info, etc # if tag is set, you can't have init, verify, info, etc
if [ ! -z "${ONE_TIME_TAG}" ] && ([ ${PRINT} -eq 1 ] || [ ${INIT} -eq 1 ] || [ ${VERIFY} -eq 1 ] || [ ${INFO} -eq 1 ]); then if [ -n "${ONE_TIME_TAG}" ] && ([ ${PRINT} -eq 1 ] || [ ${INIT} -eq 1 ] || [ ${VERIFY} -eq 1 ] || [ ${INFO} -eq 1 ]); then
echo "Cannot have -T '${ONE_TIME_TAG}' option with -i info, -V verify, -I initialize or -P print option at the same time"; echo "Cannot have -T '${ONE_TIME_TAG}' option with -i info, -V verify, -I initialize or -P print option at the same time";
exit 1; exit 1;
fi; fi;
# verify only alphanumeric, no spaces, only underscore and dash # verify only alphanumeric, no spaces, only underscore and dash
if [ ! -z "${ONE_TIME_TAG}" ] && ! [[ "${ONE_TIME_TAG}" =~ ^[A-Za-z0-9_-]+$ ]]; then if [ -n "${ONE_TIME_TAG}" ] && ! [[ "${ONE_TIME_TAG}" =~ ^[A-Za-z0-9_-]+$ ]]; then
echo "One time tag '${ONE_TIME_TAG}' must be alphanumeric with dashes and underscore only."; echo "One time tag '${ONE_TIME_TAG}' must be alphanumeric with dashes and underscore only.";
exit 1; exit 1;
elif [ ! -z "${ONE_TIME_TAG}" ]; then elif [ -n "${ONE_TIME_TAG}" ]; then
# all ok, attach . at the end # all ok, attach . at the end
ONE_TIME_TAG=${ONE_TIME_TAG}"."; ONE_TIME_TAG=${ONE_TIME_TAG}".";
fi; fi;
# if -D, cannot be with -T, -i, -C, -I, -P # if -D, cannot be with -T, -i, -C, -I, -P
if [ ! -z "${DELETE_ONE_TIME_TAG}" ] && ([ ! -z "${ONE_TIME_TAG}" ] || [ ${PRINT} -eq 1 ] || [ ${INIT} -eq 1 ] || [ ${VERIFY} -eq 1 ] || [ ${INFO} -eq 1 ]); then if [ -n "${DELETE_ONE_TIME_TAG}" ] && ([ -n "${ONE_TIME_TAG}" ] || [ ${PRINT} -eq 1 ] || [ ${INIT} -eq 1 ] || [ ${VERIFY} -eq 1 ] || [ ${INFO} -eq 1 ]); then
echo "Cannot have -D delete tag option with -T one time tag, -i info, -V verify, -I initialize or -P print option at the same time"; echo "Cannot have -D delete tag option with -T one time tag, -i info, -V verify, -I initialize or -P print option at the same time";
exit 1; exit 1;
fi; fi;
# -D also must be in valid backup set format # -D also must be in valid backup set format
# ! [[ "${DELETE_ONE_TIME_TAG}" =~ ^[A-Za-z0-9_-]+\.${MODULE},(\*-)?[0-9]{4}-[0-9]{2}-[0-9]{2}T\*$ ]] # ! [[ "${DELETE_ONE_TIME_TAG}" =~ ^[A-Za-z0-9_-]+\.${MODULE},(\*-)?[0-9]{4}-[0-9]{2}-[0-9]{2}T\*$ ]]
if [ ! -z "${DELETE_ONE_TIME_TAG}" ] && ! [[ "${DELETE_ONE_TIME_TAG}" =~ ^[A-Za-z0-9_-]+\.${MODULE},([A-Za-z0-9_-]+-)?[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$ ]] && ! [[ "${DELETE_ONE_TIME_TAG}" =~ ^[A-Za-z0-9_-]+\.${MODULE},(\*-)?[0-9]{4}-[0-9]{2}-[0-9]{2}T\*$ ]]; then if [ -n "${DELETE_ONE_TIME_TAG}" ] && ! [[ "${DELETE_ONE_TIME_TAG}" =~ ^[A-Za-z0-9_-]+\.${MODULE},([A-Za-z0-9_-]+-)?[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$ ]] && ! [[ "${DELETE_ONE_TIME_TAG}" =~ ^[A-Za-z0-9_-]+\.${MODULE},(\*-)?[0-9]{4}-[0-9]{2}-[0-9]{2}T\*$ ]]; then
echo "Delete one time tag '${DELETE_ONE_TIME_TAG}' is in an invalid format. " echo "Delete one time tag '${DELETE_ONE_TIME_TAG}' is in an invalid format. "
echo "Please verify existing tags with -P option." echo "Please verify existing tags with -P option."
echo "For a globing be sure it is in the format of: TAG.MODULE,*-YYYY-MM-DDT*"; echo "For a globing be sure it is in the format of: TAG.MODULE,*-YYYY-MM-DDT*";
@@ -366,7 +371,7 @@ if [ ${CHECK_VERIFY_DATA} -eq 1 ] && [ ${CHECK} -eq 0 ]; then
exit 1; exit 1;
fi; fi;
# -p can't be set without -C # -p can't be set without -C
if [ ! -z "${CHECK_PREFIX}" ] && [ ${CHECK} -eq 0 ]; then if [ -n "${CHECK_PREFIX}" ] && [ ${CHECK} -eq 0 ]; then
echo "-p (pattern|glob) for check cannot be run without -C (Check) options"; echo "-p (pattern|glob) for check cannot be run without -C (Check) options";
exit 1; exit 1;
fi; fi;
@@ -399,20 +404,21 @@ fi;
. "${BASE_FOLDER}${SETTINGS_FILE}"; . "${BASE_FOLDER}${SETTINGS_FILE}";
# if OPTION SET overrides ALL others # if OPTION SET overrides ALL others
if [ ! -z "${OPT_BORG_EXECUTEABLE}" ]; then if [ -n "${OPT_BORG_EXECUTEABLE}" ]; then
BORG_COMMAND="${OPT_BORG_EXECUTEABLE}"; BORG_COMMAND="${OPT_BORG_EXECUTEABLE}";
if [ ! -f "${BORG_COMMAND}" ]; then if [ ! -f "${BORG_COMMAND}" ]; then
echo "borg command not found with option -b: ${BORG_COMMAND}"; echo "borg command not found with option -b: ${BORG_COMMAND}";
exit; exit;
fi; fi;
# if in setting file, use this # if in setting file, use this
elif [ ! -z "${BORG_EXECUTEABLE}" ]; then elif [ -n "${BORG_EXECUTEABLE}" ]; then
BORG_COMMAND="${BORG_EXECUTEABLE}"; BORG_COMMAND="${BORG_EXECUTEABLE}";
if [ ! -f "${BORG_COMMAND}" ]; then if [ ! -f "${BORG_COMMAND}" ]; then
echo "borg command not found with setting: ${BORG_COMMAND}"; echo "borg command not found with setting: ${BORG_COMMAND}";
exit; exit;
fi; fi;
elif ! command -v borg &> /dev/null; then elif ! command -v borg &> /dev/null; then
# elif [ -z ($command -v borg) ]; then
echo "borg backup seems not to be installed, please verify paths"; echo "borg backup seems not to be installed, please verify paths";
exit; exit;
fi; fi;
@@ -445,7 +451,7 @@ if [ -z "${CHECK_INTERVAL}" ]; then
CHECK_INTERVAL="${DEFAULT_CHECK_INTERVAL}"; CHECK_INTERVAL="${DEFAULT_CHECK_INTERVAL}";
fi; fi;
# deprecated name FORCE_CHECK, use FORCE_VERIFY instead # deprecated name FORCE_CHECK, use FORCE_VERIFY instead
if [ ! -z "${FORCE_CHECK}" ]; then if [ -n "${FORCE_CHECK}" ]; then
FORCE_VERIFY="${FORCE_CHECK}"; FORCE_VERIFY="${FORCE_CHECK}";
fi; fi;
if [ -z "${FORCE_VERIFY}" ]; then if [ -z "${FORCE_VERIFY}" ]; then
@@ -476,48 +482,48 @@ SETTINGS_FILE_SUB=$(echo "${SETTINGS_FILE}" | sed -e "s/\.settings/\.${MODULE,,}
if [ -f "${BASE_FOLDER}${SETTINGS_FILE_SUB}" ]; then if [ -f "${BASE_FOLDER}${SETTINGS_FILE_SUB}" ]; then
. "${BASE_FOLDER}${SETTINGS_FILE_SUB}"; . "${BASE_FOLDER}${SETTINGS_FILE_SUB}";
# if SUB_ set override master # if SUB_ set override master
if [ ! -z "${SUB_BACKUP_FILE}" ]; then if [ -n "${SUB_BACKUP_FILE}" ]; then
BACKUP_FILE=${SUB_BACKUP_FILE} BACKUP_FILE=${SUB_BACKUP_FILE}
fi; fi;
# if sub backup set it set, override current # if sub backup set it set, override current
if [ ! -z "${SUB_BACKUP_SET}" ]; then if [ -n "${SUB_BACKUP_SET}" ]; then
BACKUP_SET=${SUB_BACKUP_SET}; BACKUP_SET=${SUB_BACKUP_SET};
fi; fi;
# ovrride compression # ovrride compression
if [ ! -z "${SUB_COMPRESSION}" ]; then if [ -n "${SUB_COMPRESSION}" ]; then
COMPRESSION=${SUB_COMPRESSION}; COMPRESSION=${SUB_COMPRESSION};
fi; fi;
if [ ! -z "${SUB_COMPRESSION_LEVEL}" ]; then if [ -n "${SUB_COMPRESSION_LEVEL}" ]; then
COMPRESSION_LEVEL=${SUB_COMPRESSION_LEVEL}; COMPRESSION_LEVEL=${SUB_COMPRESSION_LEVEL};
fi; fi;
# compact interval override # compact interval override
if [ ! -z "${SUB_COMPACT_INTERVAL}" ]; then if [ -n "${SUB_COMPACT_INTERVAL}" ]; then
COMPACT_INTERVAL="${SUB_COMPACT_INTERVAL}"; COMPACT_INTERVAL="${SUB_COMPACT_INTERVAL}";
fi; fi;
# override check interval # override check interval
if [ ! -z "${SUB_CHECK_INTERVAL}" ]; then if [ -n "${SUB_CHECK_INTERVAL}" ]; then
CHECK_INTERVAL="${SUB_CHECK_INTERVAL}"; CHECK_INTERVAL="${SUB_CHECK_INTERVAL}";
fi; fi;
# check override for keep time # check override for keep time
if [ ! -z "${SUB_KEEP_LAST}" ]; then if [ -n "${SUB_KEEP_LAST}" ]; then
KEEP_LAST=${SUB_KEEP_LAST}; KEEP_LAST=${SUB_KEEP_LAST};
fi; fi;
if [ ! -z "${SUB_KEEP_HOURS}" ]; then if [ -n "${SUB_KEEP_HOURS}" ]; then
KEEP_HOURS=${SUB_KEEP_HOURS}; KEEP_HOURS=${SUB_KEEP_HOURS};
fi; fi;
if [ ! -z "${SUB_KEEP_DAYS}" ]; then if [ -n "${SUB_KEEP_DAYS}" ]; then
KEEP_DAYS=${SUB_KEEP_DAYS}; KEEP_DAYS=${SUB_KEEP_DAYS};
fi; fi;
if [ ! -z "${SUB_KEEP_WEEKS}" ]; then if [ -n "${SUB_KEEP_WEEKS}" ]; then
KEEP_WEEKS=${SUB_KEEP_WEEKS}; KEEP_WEEKS=${SUB_KEEP_WEEKS};
fi; fi;
if [ ! -z "${SUB_KEEP_MONTHS}" ]; then if [ -n "${SUB_KEEP_MONTHS}" ]; then
KEEP_MONTHS=${SUB_KEEP_MONTHS}; KEEP_MONTHS=${SUB_KEEP_MONTHS};
fi; fi;
if [ ! -z "${SUB_KEEP_YEARS}" ]; then if [ -n "${SUB_KEEP_YEARS}" ]; then
KEEP_YEARS=${SUB_KEEP_YEARS}; KEEP_YEARS=${SUB_KEEP_YEARS};
fi; fi;
if [ ! -z "${SUB_KEEP_WITHIN}" ]; then if [ -n "${SUB_KEEP_WITHIN}" ]; then
KEEP_WITHIN=${SUB_KEEP_WITHIN}; KEEP_WITHIN=${SUB_KEEP_WITHIN};
fi; fi;
fi; fi;
@@ -565,7 +571,7 @@ fi
# log file set and check # log file set and check
# option folder overrides all other folders # option folder overrides all other folders
if [ ! -z "${OPT_LOG_FOLDER}" ]; then if [ -n "${OPT_LOG_FOLDER}" ]; then
LOG_FOLDER="${OPT_LOG_FOLDER}"; LOG_FOLDER="${OPT_LOG_FOLDER}";
fi; fi;
# if empty folder set to default folder # if empty folder set to default folder
@@ -627,15 +633,15 @@ function convert_time
done; done;
for ((i=0; i<${#output[@]}; i++)); do for ((i=0; i<${#output[@]}; i++)); do
if [ ${output[$i]} -gt 0 ] || [ ! -z "$time_string" ]; then if [ ${output[$i]} -gt 0 ] || [ -n "$time_string" ]; then
if [ ! -z "${time_string}" ]; then if [ -n "${time_string}" ]; then
time_string=${time_string}" "; time_string=${time_string}" ";
fi; fi;
time_string=${time_string}${output[$i]}${timenames[$i]}; time_string=${time_string}${output[$i]}${timenames[$i]};
fi; fi;
done; done;
if [ ! -z ${ms} ] && [ "${ms}" != "nan" ] && [ ${ms} -gt 0 ]; then if [ -n "${ms}" ] && [ "${ms}" != "nan" ] && [ "${ms}" -gt 0 ]; then
time_string=${time_string}" "${ms}"ms"; time_string="${time_string} ${ms}ms";
fi; fi;
# just in case the time is 0 # just in case the time is 0
if [ -z "${time_string}" ]; then if [ -z "${time_string}" ]; then

View File

@@ -30,7 +30,7 @@ printf "${PRINTF_INFO_STRING}" "Base folder" "${BASE_FOLDER}";
printf "${PRINTF_INFO_STRING}" "Module init date" "${BACKUP_INIT_DATE}"; printf "${PRINTF_INFO_STRING}" "Module init date" "${BACKUP_INIT_DATE}";
# print last compact date if positive integer # print last compact date if positive integer
# only if borg > 1.2 # only if borg > 1.2
if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
if [ "${COMPACT_INTERVAL##*[!0-9]*}" ]; then if [ "${COMPACT_INTERVAL##*[!0-9]*}" ]; then
printf "${PRINTF_INFO_STRING}" "Module compact interval" "${COMPACT_INTERVAL}"; printf "${PRINTF_INFO_STRING}" "Module compact interval" "${COMPACT_INTERVAL}";
if [ -f "${BASE_FOLDER}${BACKUP_COMPACT_FILE}" ]; then if [ -f "${BASE_FOLDER}${BACKUP_COMPACT_FILE}" ]; then
@@ -57,15 +57,15 @@ fi;
# if force verify is true set VERIFY to 1 unless INFO is 1 # if force verify is true set VERIFY to 1 unless INFO is 1
# Needs bash 4.0 at lesat for this # Needs bash 4.0 at lesat for this
if [ "${FORCE_VERIFY,,}" = "true" ] && [ ${INFO} -eq 0 ]; then if [ "${FORCE_VERIFY,,}" = "true" ] && [ "${INFO}" -eq 0 ]; then
VERIFY=1; VERIFY=1;
if [ ${DEBUG} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ]; then
echo "Force repository verify"; echo "Force repository verify";
fi; fi;
fi; fi;
# remote borg path # remote borg path
if [ ! -z "${TARGET_BORG_PATH}" ]; then if [ -n "${TARGET_BORG_PATH}" ]; then
if [[ "${TARGET_BORG_PATH}" =~ \ |\' ]]; then if [[ "${TARGET_BORG_PATH}" =~ \ |\' ]]; then
echo "Space found in ${TARGET_BORG_PATH}. Aborting"; echo "Space found in ${TARGET_BORG_PATH}. Aborting";
echo "There are issues with passing on paths with spaces" echo "There are issues with passing on paths with spaces"
@@ -102,16 +102,16 @@ TARGET_SERVER='';
# allow host only (if full setup in .ssh/config) # allow host only (if full setup in .ssh/config)
# user@host OR ssh://user@host:port/ IF TARGET_PORT is set # user@host OR ssh://user@host:port/ IF TARGET_PORT is set
# user/host/port # user/host/port
if [ ! -z "${TARGET_USER}" ] && [ ! -z "${TARGET_HOST}" ] && [ ! -z "${TARGET_PORT}" ]; then if [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ] && [ -n "${TARGET_PORT}" ]; then
TARGET_SERVER="ssh://${TARGET_USER}@${TARGET_HOST}:${TARGET_PORT}/"; TARGET_SERVER="ssh://${TARGET_USER}@${TARGET_HOST}:${TARGET_PORT}/";
# host/port # host/port
elif [ ! -z "${TARGET_HOST}" ] && [ ! -z "${TARGET_PORT}" ]; then elif [ -n "${TARGET_HOST}" ] && [ -n "${TARGET_PORT}" ]; then
TARGET_SERVER="ssh://${TARGET_HOST}:${TARGET_PORT}/"; TARGET_SERVER="ssh://${TARGET_HOST}:${TARGET_PORT}/";
# user/host # user/host
elif [ ! -z "${TARGET_USER}" ] && [ ! -z "${TARGET_HOST}" ]; then elif [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_USER}@${TARGET_HOST}:"; TARGET_SERVER="${TARGET_USER}@${TARGET_HOST}:";
# host # host
elif [ ! -z "${TARGET_HOST}" ]; then elif [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_HOST}:"; TARGET_SERVER="${TARGET_HOST}:";
fi; fi;
# we dont allow special characters, so we don't need to special escape it # we dont allow special characters, so we don't need to special escape it
@@ -120,13 +120,13 @@ printf "${PRINTF_INFO_STRING}" "Repository" "${REPOSITORY}";
# check if given compression name and level are valid # check if given compression name and level are valid
OPT_COMPRESSION=''; OPT_COMPRESSION='';
if [ ! -z "${COMPRESSION}" ]; then if [ -n "${COMPRESSION}" ]; then
# valid compression # valid compression
if [ "${COMPRESSION}" = "lz4" ] || [ "${COMPRESSION}" = "zlib" ] || [ "${COMPRESSION}" = "lzma" ] || [ "${COMPRESSION}" = "zstd" ]; then if [ "${COMPRESSION}" = "lz4" ] || [ "${COMPRESSION}" = "zlib" ] || [ "${COMPRESSION}" = "lzma" ] || [ "${COMPRESSION}" = "zstd" ]; then
OPT_COMPRESSION="-C=${COMPRESSION}"; OPT_COMPRESSION="-C=${COMPRESSION}";
# if COMPRESSION_LEVEL, check it is a valid regex # if COMPRESSION_LEVEL, check it is a valid regex
# for zlib, zstd, lzma # for zlib, zstd, lzma
if [ ! -z "${COMPRESSION_LEVEL}" ] && ([ "${COMPRESSION}" = "zlib" ] || [ "${COMPRESSION}" = "lzma" ] || [ "${COMPRESSION}" = "zstd" ]); then if [ -n "${COMPRESSION_LEVEL}" ] && { [ "${COMPRESSION}" = "zlib" ] || [ "${COMPRESSION}" = "lzma" ] || [ "${COMPRESSION}" = "zstd" ]; }; then
MIN_COMPRESSION=0; MIN_COMPRESSION=0;
MAX_COMPRESSION=0; MAX_COMPRESSION=0;
case "${COMPRESSION}" in case "${COMPRESSION}" in
@@ -177,7 +177,7 @@ KEEP_OPTIONS=();
# keep info string (for files) # keep info string (for files)
KEEP_INFO=""; KEEP_INFO="";
# override standard keep for tagged backups # override standard keep for tagged backups
if [ ! -z "${ONE_TIME_TAG}" ]; then if [ -n "${ONE_TIME_TAG}" ]; then
BACKUP_SET="{now:%Y-%m-%dT%H:%M:%S}"; BACKUP_SET="{now:%Y-%m-%dT%H:%M:%S}";
# set empty to avoid problems # set empty to avoid problems
KEEP_OPTIONS=(""); KEEP_OPTIONS=("");
@@ -185,32 +185,32 @@ else
# build options and info string, # build options and info string,
# also flag BACKUP_SET check if hourly is set # also flag BACKUP_SET check if hourly is set
BACKUP_SET_VERIFY=0; BACKUP_SET_VERIFY=0;
if [ ${KEEP_LAST} -gt 0 ]; then if [ "${KEEP_LAST}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-last=${KEEP_LAST}"); KEEP_OPTIONS+=("--keep-last=${KEEP_LAST}");
KEEP_INFO="${KEEP_INFO}, last: ${KEEP_LAST}"; KEEP_INFO="${KEEP_INFO}, last: ${KEEP_LAST}";
fi; fi;
if [ ${KEEP_HOURS} -gt 0 ]; then if [ "${KEEP_HOURS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-hourly=${KEEP_HOURS}"); KEEP_OPTIONS+=("--keep-hourly=${KEEP_HOURS}");
KEEP_INFO="${KEEP_INFO}, hourly: ${KEEP_HOURS}"; KEEP_INFO="${KEEP_INFO}, hourly: ${KEEP_HOURS}";
BACKUP_SET_VERIFY=1; BACKUP_SET_VERIFY=1;
fi; fi;
if [ ${KEEP_DAYS} -gt 0 ]; then if [ "${KEEP_DAYS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-daily=${KEEP_DAYS}"); KEEP_OPTIONS+=("--keep-daily=${KEEP_DAYS}");
KEEP_INFO="${KEEP_INFO}, daily: ${KEEP_DAYS}"; KEEP_INFO="${KEEP_INFO}, daily: ${KEEP_DAYS}";
fi; fi;
if [ ${KEEP_WEEKS} -gt 0 ]; then if [ "${KEEP_WEEKS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-weekly=${KEEP_WEEKS}"); KEEP_OPTIONS+=("--keep-weekly=${KEEP_WEEKS}");
KEEP_INFO="${KEEP_INFO}, weekly: ${KEEP_WEEKS}"; KEEP_INFO="${KEEP_INFO}, weekly: ${KEEP_WEEKS}";
fi; fi;
if [ ${KEEP_MONTHS} -gt 0 ]; then if [ "${KEEP_MONTHS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-monthly=${KEEP_MONTHS}"); KEEP_OPTIONS+=("--keep-monthly=${KEEP_MONTHS}");
KEEP_INFO="${KEEP_INFO}, monthly: ${KEEP_MONTHS}"; KEEP_INFO="${KEEP_INFO}, monthly: ${KEEP_MONTHS}";
fi; fi;
if [ ${KEEP_YEARS} -gt 0 ]; then if [ "${KEEP_YEARS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-yearly=${KEEP_YEARS}"); KEEP_OPTIONS+=("--keep-yearly=${KEEP_YEARS}");
KEEP_INFO="${KEEP_INFO}, yearly: ${KEEP_YEARS}"; KEEP_INFO="${KEEP_INFO}, yearly: ${KEEP_YEARS}";
fi; fi;
if [ ! -z "${KEEP_WITHIN}" ]; then if [ -n "${KEEP_WITHIN}" ]; then
# check for invalid string. can only be number + H|d|w|m|y # check for invalid string. can only be number + H|d|w|m|y
if [[ "${KEEP_WITHIN}" =~ ^[0-9]+[Hdwmy]{1}$ ]]; then if [[ "${KEEP_WITHIN}" =~ ^[0-9]+[Hdwmy]{1}$ ]]; then
KEEP_OPTIONS+=("--keep-within=${KEEP_WITHIN}"); KEEP_OPTIONS+=("--keep-within=${KEEP_WITHIN}");
@@ -244,7 +244,7 @@ fi;
if [ -f "${BASE_FOLDER}${BACKUP_LOCK_FILE}" ]; then if [ -f "${BASE_FOLDER}${BACKUP_LOCK_FILE}" ]; then
LOCK_PID=$(cat "${BASE_FOLDER}${BACKUP_LOCK_FILE}" 2>/dev/null); LOCK_PID=$(cat "${BASE_FOLDER}${BACKUP_LOCK_FILE}" 2>/dev/null);
# check if lock file pid has an active program attached to it # check if lock file pid has an active program attached to it
if [ -f /proc/${LOCK_PID}/cmdline ]; then if [ -f "/proc/${LOCK_PID}/cmdline" ]; then
echo "Script is already running on PID: ${$}"; echo "Script is already running on PID: ${$}";
. "${DIR}/borg.backup.functions.close.sh" 1; . "${DIR}/borg.backup.functions.close.sh" 1;
exit 1; exit 1;
@@ -272,11 +272,11 @@ _BORG_PRUNE="${BORG_COMMAND} prune ${OPT_REMOTE} -v --list ${OPT_PROGRESS} ${DRY
# set base path to config directory to keep cache/config separated # set base path to config directory to keep cache/config separated
export BORG_BASE_DIR="${BASE_FOLDER}"; export BORG_BASE_DIR="${BASE_FOLDER}";
# ignore non encrypted access # ignore non encrypted access
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=${_BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK}; export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK="${_BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK}";
# ignore moved repo access # ignore moved repo access
export BORG_RELOCATED_REPO_ACCESS_IS_OK=${_BORG_RELOCATED_REPO_ACCESS_IS_OK}; export BORG_RELOCATED_REPO_ACCESS_IS_OK="${_BORG_RELOCATED_REPO_ACCESS_IS_OK}";
# and for debug print that tout # and for debug print that tout
if [ ${DEBUG} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ]; then
echo "export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=${_BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK};"; echo "export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=${_BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK};";
echo "export BORG_RELOCATED_REPO_ACCESS_IS_OK=${_BORG_RELOCATED_REPO_ACCESS_IS_OK};"; echo "export BORG_RELOCATED_REPO_ACCESS_IS_OK=${_BORG_RELOCATED_REPO_ACCESS_IS_OK};";
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";"; echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";";
@@ -288,10 +288,10 @@ COMMAND_INFO="${COMMAND_EXPORT}${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY}"
# if this is user@host, we need to use ssh command to verify if the file is there # if this is user@host, we need to use ssh command to verify if the file is there
# else a normal verify is ok # else a normal verify is ok
# unless explicit given, verify is skipped # unless explicit given, verify is skipped
if [ ${VERIFY} -eq 1 ] || [ ${INIT} -eq 1 ]; then if [ "${VERIFY}" -eq 1 ] || [ "${INIT}" -eq 1 ]; then
printf "${PRINTF_SUB_BLOCK}" "VERIFY" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "VERIFY" "$(date +'%F %T')" "${MODULE}";
if [ ! -z "${TARGET_SERVER}" ]; then if [ -n "${TARGET_SERVER}" ]; then
if [ ${DEBUG} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY} 2>&1|grep \"Repository ID:\""; echo "${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY} 2>&1|grep \"Repository ID:\"";
fi; fi;
# use borg info and verify if it returns "Repository ID:" in the first line # use borg info and verify if it returns "Repository ID:" in the first line
@@ -305,19 +305,19 @@ if [ ${VERIFY} -eq 1 ] || [ ${INIT} -eq 1 ]; then
INIT_REPOSITORY=1; INIT_REPOSITORY=1;
fi; fi;
# if verrify but no init and repo is there but init file is missing set it # if verrify but no init and repo is there but init file is missing set it
if [ ${VERIFY} -eq 1 ] && [ ${INIT} -eq 0 ] && [ ${INIT_REPOSITORY} -eq 0 ] && if [ "${VERIFY}" -eq 1 ] && [ "${INIT}" -eq 0 ] && [ "${INIT_REPOSITORY}" -eq 0 ] &&
[ ! -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then [ ! -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then
# write init file # write init file
echo "[!] Add missing init verify file"; echo "[!] Add missing init verify file";
echo "$(date +%s)" > "${BASE_FOLDER}${BACKUP_INIT_FILE}"; date +%s > "${BASE_FOLDER}${BACKUP_INIT_FILE}";
fi; fi;
# end if verified but repository is not here # end if verified but repository is not here
if [ ${VERIFY} -eq 1 ] && [ ${INIT} -eq 0 ] && [ ${INIT_REPOSITORY} -eq 1 ]; then if [ "${VERIFY}" -eq 1 ] && [ "${INIT}" -eq 0 ] && [ "${INIT_REPOSITORY}" -eq 1 ]; then
echo "[! $(date +'%F %T')] No repository. Please run with -I flag to initialze repository"; echo "[! $(date +'%F %T')] No repository. Please run with -I flag to initialze repository";
. "${DIR}/borg.backup.functions.close.sh" 1; . "${DIR}/borg.backup.functions.close.sh" 1;
exit 1; exit 1;
fi; fi;
if [ ${EXIT} -eq 1 ] && [ ${VERIFY} -eq 1 ] && [ ${INIT} -eq 0 ]; then if [ "${EXIT}" -eq 1 ] && [ "${VERIFY}" -eq 1 ] && [ "${INIT}" -eq 0 ]; then
echo "Repository exists"; echo "Repository exists";
echo "For more information run:" echo "For more information run:"
echo "${COMMAND_INFO}"; echo "${COMMAND_INFO}";
@@ -325,16 +325,16 @@ if [ ${VERIFY} -eq 1 ] || [ ${INIT} -eq 1 ]; then
exit; exit;
fi; fi;
fi; fi;
if [ ${INIT} -eq 1 ] && [ ${INIT_REPOSITORY} -eq 1 ]; then if [ "${INIT}" -eq 1 ] && [ "${INIT_REPOSITORY}" -eq 1 ]; then
printf "${PRINTF_SUB_BLOCK}" "INIT" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "INIT" "$(date +'%F %T')" "${MODULE}";
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ] || [ "${DRYRUN}" -eq 1 ]; then
echo "${BORG_COMMAND} init ${OPT_REMOTE} -e ${ENCRYPTION} ${OPT_VERBOSE} ${REPOSITORY}"; echo "${BORG_COMMAND} init ${OPT_REMOTE} -e ${ENCRYPTION} ${OPT_VERBOSE} ${REPOSITORY}";
fi fi
if [ ${DRYRUN} -eq 0 ]; then if [ "${DRYRUN}" -eq 0 ]; then
# should trap and exit properly here # should trap and exit properly here
${BORG_COMMAND} init ${OPT_REMOTE} -e ${ENCRYPTION} ${OPT_VERBOSE} ${REPOSITORY}; ${BORG_COMMAND} init ${OPT_REMOTE} -e ${ENCRYPTION} ${OPT_VERBOSE} ${REPOSITORY};
# write init file # write init file
echo "$(date +%s)" > "${BASE_FOLDER}${BACKUP_INIT_FILE}"; date +%s > "${BASE_FOLDER}${BACKUP_INIT_FILE}";
echo "Repository initialized"; echo "Repository initialized";
echo "For more information run:" echo "For more information run:"
echo "${COMMAND_INFO}"; echo "${COMMAND_INFO}";
@@ -342,7 +342,7 @@ if [ ${INIT} -eq 1 ] && [ ${INIT_REPOSITORY} -eq 1 ]; then
. "${DIR}/borg.backup.functions.close.sh"; . "${DIR}/borg.backup.functions.close.sh";
# exit after init # exit after init
exit; exit;
elif [ ${INIT} -eq 1 ] && [ ${INIT_REPOSITORY} -eq 0 ]; then elif [ "${INIT}" -eq 1 ] && [ "${INIT_REPOSITORY}" -eq 0 ]; then
echo "[! $(date +'%F %T')] Repository already initialized"; echo "[! $(date +'%F %T')] Repository already initialized";
echo "For more information run:" echo "For more information run:"
echo "${COMMAND_INFO}"; echo "${COMMAND_INFO}";
@@ -359,18 +359,18 @@ if [ ! -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then
fi; fi;
# PRINT OUT current data, only do this if REPO exists # PRINT OUT current data, only do this if REPO exists
if [ ${PRINT} -eq 1 ]; then if [ "${PRINT}" -eq 1 ]; then
printf "${PRINTF_SUB_BLOCK}" "PRINT" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "PRINT" "$(date +'%F %T')" "${MODULE}";
FORMAT="{archive:<45} {comment:6} {start} - {end} [{id}] ({username}@{hostname}){NL}" FORMAT="{archive:<45} {comment:6} {start} - {end} [{id}] ({username}@{hostname}){NL}"
# show command on debug or dry run # show command on debug or dry run
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ] || [ "${DRYRUN}" -eq 1 ]; then
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} list ${OPT_REMOTE} --format ${FORMAT} ${REPOSITORY}"; echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} list ${OPT_REMOTE} --format ${FORMAT} ${REPOSITORY}";
fi; fi;
# run info command if not a dry drun # run info command if not a dry drun
if [ ${DRYRUN} -eq 0 ]; then if [ "${DRYRUN}" -eq 0 ]; then
${BORG_COMMAND} list ${OPT_REMOTE} --format "${FORMAT}" ${REPOSITORY} ; ${BORG_COMMAND} list ${OPT_REMOTE} --format "${FORMAT}" ${REPOSITORY} ;
fi; fi;
if [ ${VERBOSE} -eq 1 ]; then if [ "${VERBOSE}" -eq 1 ]; then
echo ""; echo "";
echo "Base command info:" echo "Base command info:"
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} [COMMAND] ${OPT_REMOTE} ${REPOSITORY}::[BACKUP] [PATH]"; echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} [COMMAND] ${OPT_REMOTE} ${REPOSITORY}::[BACKUP] [PATH]";
@@ -389,21 +389,21 @@ if [ ${PRINT} -eq 1 ]; then
fi; fi;
# run borg compact command and exit # run borg compact command and exit
if [ ${COMPACT} -eq 1 ]; then if [ "${COMPACT}" -eq 1 ]; then
. "${DIR}/borg.backup.functions.compact.sh"; . "${DIR}/borg.backup.functions.compact.sh";
. "${DIR}/borg.backup.functions.close.sh"; . "${DIR}/borg.backup.functions.close.sh";
exit; exit;
fi; fi;
# run borg check command and exit # run borg check command and exit
if [ ${CHECK} -eq 1 ]; then if [ "${CHECK}" -eq 1 ]; then
. "${DIR}/borg.backup.functions.check.sh"; . "${DIR}/borg.backup.functions.check.sh";
. "${DIR}/borg.backup.functions.close.sh"; . "${DIR}/borg.backup.functions.close.sh";
exit; exit;
fi; fi;
# DELETE ONE TIME TAG # DELETE ONE TIME TAG
if [ ! -z "${DELETE_ONE_TIME_TAG}" ]; then if [ -n "${DELETE_ONE_TIME_TAG}" ]; then
printf "${PRINTF_SUB_BLOCK}" "DELETE" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "DELETE" "$(date +'%F %T')" "${MODULE}";
# if a "*" is inside we don't do ONE archive, but globbing via -a option # if a "*" is inside we don't do ONE archive, but globbing via -a option
DELETE_ARCHIVE="" DELETE_ARCHIVE=""
@@ -415,12 +415,12 @@ if [ ! -z "${DELETE_ONE_TIME_TAG}" ]; then
DELETE_ARCHIVE="::"${DELETE_ONE_TIME_TAG}; DELETE_ARCHIVE="::"${DELETE_ONE_TIME_TAG};
fi fi
# if this is borg <1.2 OPT_LIST does not work # if this is borg <1.2 OPT_LIST does not work
if [ $(version $BORG_VERSION) -lt $(version "1.2.0") ]; then if [ "$(version "$BORG_VERSION")" -lt "$(version "1.2.0")" ]; then
OPT_LIST=""; OPT_LIST="";
fi; fi;
# if exists, delete and exit # if exists, delete and exit
# show command on debug or dry run # show command on debug or dry run
if [ ${DEBUG} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMMAND} delete ${OPT_REMOTE} ${OPT_LIST} -s ${OPT_GLOB} ${REPOSITORY}${DELETE_ARCHIVE}"; echo "${BORG_COMMAND} delete ${OPT_REMOTE} ${OPT_LIST} -s ${OPT_GLOB} ${REPOSITORY}${DELETE_ARCHIVE}";
fi; fi;
# run delete command if not a dry drun # run delete command if not a dry drun
@@ -432,12 +432,12 @@ if [ ! -z "${DELETE_ONE_TIME_TAG}" ]; then
fi; fi;
# if not a dry run, compact repository after delete # if not a dry run, compact repository after delete
# not that compact only works on borg 1.2 # not that compact only works on borg 1.2
if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
if [ ${DRYRUN} -eq 0 ]; then if [ "${DRYRUN}" -eq 0 ]; then
${BORG_COMMAND} compact ${REPOSITORY}; ${BORG_COMMAND} compact ${OPT_REMOTE} ${REPOSITORY};
fi; fi;
if [ ${DEBUG} -eq 1 ]; then if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMMAND} compact ${REPOSITORY}"; echo "${BORG_COMMAND} compact ${OPT_REMOTE} ${REPOSITORY}";
fi; fi;
fi; fi;
. "${DIR}/borg.backup.functions.close.sh"; . "${DIR}/borg.backup.functions.close.sh";

View File

@@ -2,10 +2,8 @@
# rename to borg.backup.gitea.settings to use # rename to borg.backup.gitea.settings to use
# override settings in borg.backup.settings with SUB_ prefix
# valid for BACKUP_FILE, BACKUP_SET, COMPRESSION*, KEEP_*
GIT_USER=""; GIT_USER="";
GITEA_TMP=""; GITEA_WORKING_DIR="";
GITEA_TEMP_DIR="";
GITEA_BIN=""; GITEA_BIN="";
GITEA_CONFIG=""; GITEA_CONFIG="";

View File

@@ -3,7 +3,7 @@
# Backup gitea database, all git folders and gitea settings # Backup gitea database, all git folders and gitea settings
MODULE="gitea" MODULE="gitea"
MODULE_VERSION="1.1.4"; MODULE_VERSION="1.2.1";
DIR="${BASH_SOURCE%/*}" DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
@@ -29,9 +29,13 @@ if [ -z "${GIT_USER}" ]; then
GIT_USER="git"; GIT_USER="git";
fi; fi;
# set GITEA_* if not set # set GITEA_* if not set
if [ -z "${GITEA_TMP}" ]; then if [ -z "${GITEA_WORKING_DIR}" ]; then
# run gitea backup (user mktemp?) # run gitea backup (user mktemp?)
GITEA_TMP="/tmp/gitea/"; GITEA_WORKING_DIR="/var/tmp/gitea/";
fi;
# general temp folder for temporary data storage, this is not working output folder
if [ -z "${GITEA_TEMP_DIR}" ]; then
GITEA_TEMP_DIR="/var/tmp";
fi; fi;
if [ -z "${GITEA_BIN}" ]; then if [ -z "${GITEA_BIN}" ]; then
GITEA_BIN="/usr/local/bin/gitea"; GITEA_BIN="/usr/local/bin/gitea";
@@ -39,6 +43,10 @@ fi;
if [ -z "${GITEA_CONFIG}" ]; then if [ -z "${GITEA_CONFIG}" ]; then
GITEA_CONFIG="/etc/gitea/app.ini" GITEA_CONFIG="/etc/gitea/app.ini"
fi; fi;
# This one is not advertised in the config file as it is not recommended to change
if [ -z "${GITEA_EXPORT_TYPE}" ]; then
GITEA_EXPORT_TYPE="zip";
fi;
if [ ! -f "${GITEA_BIN}" ]; then if [ ! -f "${GITEA_BIN}" ]; then
echo "[! $(date +'%F %T')] Cannot find gitea binary"; echo "[! $(date +'%F %T')] Cannot find gitea binary";
. "${DIR}/borg.backup.functions.close.sh" 1; . "${DIR}/borg.backup.functions.close.sh" 1;
@@ -49,6 +57,16 @@ if [ ! -f "${GITEA_CONFIG}" ]; then
. "${DIR}/borg.backup.functions.close.sh" 1; . "${DIR}/borg.backup.functions.close.sh" 1;
exit 1; exit 1;
fi; fi;
# some basic checks with abort
if [ ! -d "${GITEA_TEMP_DIR}" ]; then
echo "Temp directory does not exist: ${GITEA_TEMP_DIR}";
exit;
fi;
# we should check GITEA_EXPORT_TYPE too at some point for an allow list
# At the moment warn if not zip
if [ "${GITEA_EXPORT_TYPE}" != "zip" ]; then
echo "[!!!!] The gitea export type has been changed from 'zip' to '${GITEA_EXPORT_TYPE}'. This can either break or make exports take very ling";
fi;
# Filename # Filename
FILENAME="gitea.backup.zip"; FILENAME="gitea.backup.zip";
# backup set and prefix # backup set and prefix
@@ -60,7 +78,7 @@ BORG_CALL=$(echo "${_BORG_CALL}" | sed -e "s/##FILENAME##/${FILENAME}/" | sed -e
BORG_PRUNE=$(echo "${_BORG_PRUNE}" | sed -e "s/##BACKUP_SET_PREFIX##/${BACKUP_SET_PREFIX}/"); BORG_PRUNE=$(echo "${_BORG_PRUNE}" | sed -e "s/##BACKUP_SET_PREFIX##/${BACKUP_SET_PREFIX}/");
printf "${PRINTF_SUB_BLOCK}" "BACKUP: git data and database" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "BACKUP: git data and database" "$(date +'%F %T')" "${MODULE}";
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then
echo "sudo -u ${GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_TMP} -L -f - | ${BORG_CALL}"; echo "sudo -u ${GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_WORKING_DIR} -t ${GITEA_TEMP_DIR} --type ${GITEA_EXPORT_TYPE} -L -f - | ${BORG_CALL}";
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "${BORG_PRUNE}"; echo "${BORG_PRUNE}";
fi; fi;
@@ -70,13 +88,13 @@ if [ ${DRYRUN} -eq 0 ]; then
# below was an old workaround # below was an old workaround
#export USER="${LOGNAME}" # workaround for broken gitea EUID check #export USER="${LOGNAME}" # workaround for broken gitea EUID check
# make sure temp folder is there and is set as git. user # make sure temp folder is there and is set as git. user
if [ ! -d "${GITEA_TMP}" ]; then if [ ! -d "${GITEA_WORKING_DIR}" ]; then
mkdir -p "${GITEA_TMP}"; mkdir -p "${GITEA_WORKING_DIR}";
fi; fi;
chown -R ${GIT_USER}. "${GITEA_TMP}"; chown -R ${GIT_USER}: "${GITEA_WORKING_DIR}";
# this needs to be run in a folder that can be stat by git user # this needs to be run in a folder that can be stat by git user
cd "${GITEA_TMP}"; cd "${GITEA_WORKING_DIR}";
sudo -u ${GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_TMP} -L -f - | ${BORG_CALL}; sudo -u ${GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_WORKING_DIR} -t ${GITEA_TEMP_DIR} --type ${GITEA_EXPORT_TYPE} -L -f - | ${BORG_CALL};
) 2>&1 | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g' # remove all ESC strings ) 2>&1 | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g' # remove all ESC strings
fi; fi;
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then

View File

@@ -7,7 +7,7 @@
# set last edit date + time # set last edit date + time
MODULE="mysql" MODULE="mysql"
MODULE_VERSION="1.1.2"; MODULE_VERSION="1.1.4";
DIR="${BASH_SOURCE%/*}" DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
@@ -86,13 +86,14 @@ EVENTDB="mysql"
EVENTS="--events" EVENTS="--events"
# ALL IN ONE FILE or PER DATABASE FLAG # ALL IN ONE FILE or PER DATABASE FLAG
if [ ! -z "${DATABASE_FULL_DUMP}" ]; then if [ -n "${DATABASE_FULL_DUMP}" ]; then
SCHEMA_ONLY=''; SCHEMA_ONLY='';
schema_flag='data'; schema_flag='data';
if [ "${DATABASE_FULL_DUMP}" = "schema" ]; then if [ "${DATABASE_FULL_DUMP}" = "schema" ]; then
SCHEMA_ONLY='--no-data'; SCHEMA_ONLY='--no-data';
schema_flag='schema'; schema_flag='schema';
fi; fi;
LOCAL_START=$(date +'%s');
printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "all databases" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "all databases" "$(date +'%F %T')" "${MODULE}";
# We only do a full backup and not per table backup here # We only do a full backup and not per table backup here
# Filename # Filename
@@ -124,9 +125,12 @@ if [ ! -z "${DATABASE_FULL_DUMP}" ]; then
echo "Prune repository with keep${KEEP_INFO:1}"; echo "Prune repository with keep${KEEP_INFO:1}";
${BORG_PRUNE}; ${BORG_PRUNE};
fi; fi;
DURATION=$[ $(date +'%s')-$LOCAL_START ];
printf "${PRINTF_DB_RUN_TIME_SUB_BLOCK}" "DONE" "all databases" "${MODULE}" "$(convert_time ${DURATION})";
else else
${MYSQL_CMD} ${MYSQL_DB_CONFIG_PARAM} -B -N -e "show databases" | ${MYSQL_CMD} ${MYSQL_DB_CONFIG_PARAM} -B -N -e "show databases" |
while read db; do while read db; do
LOCAL_START=$(date +'%s');
printf "${PRINTF_DB_SUB_BLOCK}" "DB" "${db}" "${MODULE}"; printf "${PRINTF_DB_SUB_BLOCK}" "DB" "${db}" "${MODULE}";
printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "${db}" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "${db}" "$(date +'%F %T')" "${MODULE}";
# exclude checks # exclude checks
@@ -213,6 +217,8 @@ else
else else
echo "- [E] ${db}"; echo "- [E] ${db}";
fi; fi;
DURATION=$[ $(date +'%s')-$LOCAL_START ];
printf "${PRINTF_DB_RUN_TIME_SUB_BLOCK}" "DONE" "${db}" "${MODULE}" "$(convert_time ${DURATION})";
done; done;
fi; fi;
# run compact at the end if not a dry run # run compact at the end if not a dry run

View File

@@ -7,7 +7,7 @@
# set last edit date + time # set last edit date + time
MODULE="pgsql" MODULE="pgsql"
MODULE_VERSION="1.2.2"; MODULE_VERSION="1.2.7";
DIR="${BASH_SOURCE%/*}" DIR="${BASH_SOURCE%/*}"
@@ -32,7 +32,7 @@ BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
# if info print info and then abort run # if info print info and then abort run
. "${DIR}/borg.backup.functions.info.sh"; . "${DIR}/borg.backup.functions.info.sh";
if [ ! -z "${DATABASE_USER}" ]; then if [ -n "${DATABASE_USER}" ]; then
DB_USER=${DATABASE_USER}; DB_USER=${DATABASE_USER};
else else
DB_USER='postgres'; DB_USER='postgres';
@@ -95,16 +95,17 @@ CONN_DB_HOST=''; # -h <host>
CONN_DB_PORT=''; # -p <port> CONN_DB_PORT=''; # -p <port>
# ALL IN ONE FILE or PER DATABASE FLAG # ALL IN ONE FILE or PER DATABASE FLAG
if [ ! -z "${DATABASE_FULL_DUMP}" ]; then if [ -n "${DATABASE_FULL_DUMP}" ]; then
SCHEMA_ONLY=''; SCHEMA_ONLY='';
schema_flag='data'; schema_flag='data';
if [ "${DATABASE_FULL_DUMP}" = "schema" ]; then if [ "${DATABASE_FULL_DUMP}" = "schema" ]; then
SCHEMA_ONLY='-s'; SCHEMA_ONLY='-s';
schema_flag='schema'; schema_flag='schema';
fi; fi;
LOCAL_START=$(date +'%s');
printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "all databases" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "all databases" "$(date +'%F %T')" "${MODULE}";
# Filename # Filename
FILENAME-"all.${DB_USER}.NONE.${schema_flag}-${DB_VERSION}_${DB_HOST}_${DB_PORT}.c.sql" FILENAME="all.${DB_USER}.NONE.${schema_flag}-${DB_VERSION}_${DB_HOST}_${DB_PORT}.c.sql"
# backup set: # backup set:
BACKUP_SET_PREFIX="${MODULE},all-"; BACKUP_SET_PREFIX="${MODULE},all-";
BACKUP_SET_NAME="${ONE_TIME_TAG}${BACKUP_SET_PREFIX}${schema_flag}-${BACKUP_SET}"; BACKUP_SET_NAME="${ONE_TIME_TAG}${BACKUP_SET_PREFIX}${schema_flag}-${BACKUP_SET}";
@@ -132,10 +133,13 @@ if [ ! -z "${DATABASE_FULL_DUMP}" ]; then
echo "Prune repository with keep${KEEP_INFO:1}"; echo "Prune repository with keep${KEEP_INFO:1}";
${BORG_PRUNE}; ${BORG_PRUNE};
fi; fi;
DURATION=$[ $(date +'%s')-$LOCAL_START ];
printf "${PRINTF_DB_RUN_TIME_SUB_BLOCK}" "DONE" "all databases" "${MODULE}" "$(convert_time ${DURATION})";
else else
# dump globals first # dump globals first
db="pg_globals"; db="pg_globals";
schema_flag="data"; schema_flag="data";
LOCAL_START=$(date +'%s');
printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "${db}" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "${db}" "$(date +'%F %T')" "${MODULE}";
# Filename # Filename
FILENAME="${db}.${DB_USER}.NONE.${schema_flag}-${DB_VERSION}_${DB_HOST}_${DB_PORT}.c.sql" FILENAME="${db}.${DB_USER}.NONE.${schema_flag}-${DB_VERSION}_${DB_HOST}_${DB_PORT}.c.sql"
@@ -166,9 +170,12 @@ else
echo "Prune repository with keep${KEEP_INFO:1}"; echo "Prune repository with keep${KEEP_INFO:1}";
${BORG_PRUNE}; ${BORG_PRUNE};
fi; fi;
DURATION=$[ $(date +'%s')-$LOCAL_START ];
printf "${PRINTF_DB_RUN_TIME_SUB_BLOCK}" "DONE" "${db}" "${MODULE}" "$(convert_time ${DURATION})";
# get list of tables # get list of tables
for owner_db in $(${PG_PSQL} -U ${DB_USER} ${CONN_DB_HOST} ${CONN_DB_PORT} -d template1 -t -A -F "," -X -q -c "SELECT pg_catalog.pg_get_userbyid(datdba) AS owner, datname, pg_catalog.pg_encoding_to_char(encoding) AS encoding FROM pg_catalog.pg_database WHERE datname "\!"~ 'template(0|1)' ORDER BY datname;"); do for owner_db in $(${PG_PSQL} -U ${DB_USER} ${CONN_DB_HOST} ${CONN_DB_PORT} -d template1 -t -A -F "," -X -q -c "SELECT pg_catalog.pg_get_userbyid(datdba) AS owner, datname, pg_catalog.pg_encoding_to_char(encoding) AS encoding FROM pg_catalog.pg_database WHERE datname "\!"~ 'template(0|1)' ORDER BY datname;"); do
LOCAL_START=$(date +'%s');
# get the user who owns the DB too # get the user who owns the DB too
owner=$(echo ${owner_db} | cut -d "," -f 1); owner=$(echo ${owner_db} | cut -d "," -f 1);
db=$(echo ${owner_db} | cut -d "," -f 2); db=$(echo ${owner_db} | cut -d "," -f 2);
@@ -265,6 +272,8 @@ else
else else
echo "- [E] ${db}"; echo "- [E] ${db}";
fi; fi;
DURATION=$[ $(date +'%s')-$LOCAL_START ];
printf "${PRINTF_DB_RUN_TIME_SUB_BLOCK}" "DONE" "${db}" "${MODULE}" "$(convert_time ${DURATION})";
done; done;
fi; fi;
# run compact at the end if not a dry run # run compact at the end if not a dry run

View File

@@ -40,12 +40,15 @@ COMPACT_INTERVAL="";
# if set to 1 then every time the script runs # if set to 1 then every time the script runs
# any other value it means ever n days, eg 90 would be every 90 days # any other value it means ever n days, eg 90 would be every 90 days
CHECK_INTERVAL=""; CHECK_INTERVAL="";
# default is %Y-%m-%d # default is {now:%Y-%m-%d}
# todays date, if more than one per day add -%H%M for hour/minute # todays date, if more than one per day add -%H%M for hour/minute
# it can also be "{hostname}-{user}-{now:%Y-%m-%dT%H:%M:%S.%f}" # it can also be "{hostname}-{user}-{now:%Y-%m-%dT%H:%M:%S.%f}"
BACKUP_SET=""; BACKUP_SET="";
# prune times, how many are kept in each time frame # prune times, how many are kept in each time frame
KEEP_LAST="";
KEEP_HOURS="";
KEEP_DAYS=""; KEEP_DAYS="";
KEEP_WEEKS=""; KEEP_WEEKS="";
KEEP_MONTHS=""; KEEP_MONTHS="";
KEEP_YEARS=""; KEEP_YEARS="";
KEEP_WITHIN="";

View File

@@ -15,3 +15,5 @@ ZABBIX_DATABASE="";
ZABBIX_CONFIG=""; ZABBIX_CONFIG="";
# unknown tables, default ignore, is set to true, will force backup them # unknown tables, default ignore, is set to true, will force backup them
ZABBIX_UNKNOWN_TABLES=""; ZABBIX_UNKNOWN_TABLES="";
# overide zabbix db port read from zabbix config, if not set read from zabbix config
ZABBIX_DB_PORT="";

View File

@@ -26,7 +26,7 @@ BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
if [ -z "${ZABBIX_DUMP_BIN}" ]; then if [ -z "${ZABBIX_DUMP_BIN}" ]; then
ZABBIX_DUMP_BIN="/usr/local/bin/zabbix-dump"; ZABBIX_DUMP_BIN="/usr/local/bin/zabbix-dump";
fi; fi;
if [ ! -z "${ZABBIX_CONFIG}" ] && [ ! -f "${ZABBIX_CONFIG}" ]; then if [ -n "${ZABBIX_CONFIG}" ] && [ ! -f "${ZABBIX_CONFIG}" ]; then
echo "[! $(date +'%F %T')] Cannot find zabbix config: ${ZABBIX_CONFIG}"; echo "[! $(date +'%F %T')] Cannot find zabbix config: ${ZABBIX_CONFIG}";
. "${DIR}/borg.backup.functions.close.sh" 1; . "${DIR}/borg.backup.functions.close.sh" 1;
exit 1; exit 1;
@@ -37,6 +37,10 @@ fi;
if [ "${ZABBIX_DATABASE}" = "psql" ]; then if [ "${ZABBIX_DATABASE}" = "psql" ]; then
OPT_ZABBIX_DUMP="-C"; OPT_ZABBIX_DUMP="-C";
fi; fi;
OPT_ZABBIX_DB_PORT="";
if [ -n "${ZABBIX_DB_PORT}" ]; then
OPT_ZABBIX_DB_PORT="-P ${ZABBIX_DB_PORT}";
fi;
if [ "${ZABBIX_DATABASE}" != "psql" ] && [ "${ZABBIX_DATABASE}" != "mysql" ]; then if [ "${ZABBIX_DATABASE}" != "psql" ] && [ "${ZABBIX_DATABASE}" != "mysql" ]; then
echo "[! $(date +'%F %T')] Zabbix dump must have database set to either psql or mysql"; echo "[! $(date +'%F %T')] Zabbix dump must have database set to either psql or mysql";
. "${DIR}/borg.backup.functions.close.sh" 1; . "${DIR}/borg.backup.functions.close.sh" 1;
@@ -48,7 +52,7 @@ if [ ! -f "${ZABBIX_DUMP_BIN}" ]; then
exit 1; exit 1;
fi; fi;
# -i (ignore)/ -f (backup) # -i (ignore)/ -f (backup)
if [ ! -z "${ZABBIX_UNKNOWN_TABLES}" ]; then if [ -n "${ZABBIX_UNKNOWN_TABLES}" ]; then
OPT_ZABBIX_UNKNOWN_TABLES="-f"; OPT_ZABBIX_UNKNOWN_TABLES="-f";
else else
OPT_ZABBIX_UNKNOWN_TABLES="-i"; OPT_ZABBIX_UNKNOWN_TABLES="-i";
@@ -70,13 +74,13 @@ fi;
printf "${PRINTF_SUB_BLOCK}" "BACKUP: zabbix settings" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "BACKUP: zabbix settings" "$(date +'%F %T')" "${MODULE}";
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then
echo "${ZABBIX_DUMP_BIN} -t ${ZABBIX_DATABASE} ${OPT_ZABBIX_UNKNOWN_TABLES} ${OPT_ZABBIX_DUMP} ${OPT_ZABBIX_CONFIG} -o - | ${BORG_CALL}" echo "${ZABBIX_DUMP_BIN} ${OPT_ZABBIX_DB_PORT} -t ${ZABBIX_DATABASE} ${OPT_ZABBIX_UNKNOWN_TABLES} ${OPT_ZABBIX_DUMP} ${OPT_ZABBIX_CONFIG} -o - | ${BORG_CALL}"
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "${BORG_PRUNE}"; echo "${BORG_PRUNE}";
fi; fi;
fi; fi;
if [ ${DRYRUN} -eq 0 ]; then if [ ${DRYRUN} -eq 0 ]; then
${ZABBIX_DUMP_BIN} -t ${ZABBIX_DATABASE} ${OPT_ZABBIX_UNKNOWN_TABLES} ${OPT_ZABBIX_DUMP} ${OPT_ZABBIX_CONFIG} -o - | ${BORG_CALL}; ${ZABBIX_DUMP_BIN} ${OPT_ZABBIX_DB_PORT} -t ${ZABBIX_DATABASE} ${OPT_ZABBIX_UNKNOWN_TABLES} ${OPT_ZABBIX_DUMP} ${OPT_ZABBIX_CONFIG} -o - | ${BORG_CALL};
fi; fi;
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
printf "${PRINTF_SUB_BLOCK}" "PRUNE" "$(date +'%F %T')" "${MODULE}"; printf "${PRINTF_SUB_BLOCK}" "PRUNE" "$(date +'%F %T')" "${MODULE}";

View File

@@ -33,7 +33,7 @@ function usage ()
} }
# set options # set options
while getopts ":c:m:uf:h" opt do while getopts ":c:m:uf:h" opt; do
case "${opt}" in case "${opt}" in
c|config) c|config)
BASE_FOLDER=${OPTARG}; BASE_FOLDER=${OPTARG};
@@ -80,7 +80,7 @@ if [ ${UMOUNT} -eq 0 ]; then
. ${BASE_FOLDER}${SETTINGS_FILE} . ${BASE_FOLDER}${SETTINGS_FILE}
# set the borg backup file base on the settings data # set the borg backup file base on the settings data
# if we have user/host then we build the ssh command # if we have user/host then we build the ssh command
if [ ! -z "${TARGET_USER}" ] && [ ! -z "${TARGET_HOST}" ]; then if [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER=${TARGET_USER}"@"${TARGET_HOST}":"; TARGET_SERVER=${TARGET_USER}"@"${TARGET_HOST}":";
fi; fi;
REPOSITORY=${TARGET_SERVER}${TARGET_FOLDER}${BACKUP_FILE}; REPOSITORY=${TARGET_SERVER}${TARGET_FOLDER}${BACKUP_FILE};
@@ -90,7 +90,7 @@ if [ ${UMOUNT} -eq 0 ]; then
# check that the repostiory exists # check that the repostiory exists
REPOSITORY_OK=0; REPOSITORY_OK=0;
if [ ! -z "${TARGET_SERVER}" ]; then if [ -n "${TARGET_SERVER}" ]; then
# remove trailing : for this # remove trailing : for this
TARGET_SERVER=${TARGET_SERVER/:}; TARGET_SERVER=${TARGET_SERVER/:};
# use ssh command to check remote existense # use ssh command to check remote existense