Compare commits

...

23 Commits

Author SHA1 Message Date
Clemens Schwaighofer
2e5f0648f1 Merge branch 'development' into shellcheck-cleanup 2025-08-21 10:42:20 +09:00
Clemens Schwaighofer
a2bf6b3331 Readme update for zabbix backup settings change 2025-08-21 10:40:56 +09:00
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
18 changed files with 202 additions and 149 deletions

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
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_USER | | overide username to connect to database
| 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 |
### 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
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
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.
| 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. |
### 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
Variable | Default | Description
| Variable | Default | Description |
| - | - | - |
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_BIN | /usr/local/bin/gitea | Where the gitea binary is located |
GITEA_CONFIG | /etc/gitea/app.ini | The configuration file for gitea |
| GIT_USER | git | The user that runs gitea |
| GITEA_WORKING_DIR | /var/tmp/gitea/ | Where the temporary dump files from the backup are stored, as user git |
| GITEA_TEMP_DIR | /var/tmp/ | General temporary folder |
| 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
@@ -272,14 +273,17 @@ There are no control files for gitea backup
## zabbix config backup settings
The `zabbix-dump` dump script must be installed from: <https://github.com/gullevek/zabbix-backup>
### zabbix Config Variables
Variable | Default | Description
| Variable | Default | Description |
| - | - | - |
ZABBIX_DUMP | /usr/local/bin/zabbix-dump |
ZABBIX_DATABASE | '' | Must be set as either psql or mysql
ZABBIX_CONFIG | '' | if not set uses default location
ZABBIX_UNKNOWN_TABLES | '' | if set, changed to -f (force)
| ZABBIX_DUMP | /usr/local/bin/zabbix-dump | |
| ZABBIX_DATABASE | '' | Must be set as either psql or mysql |
| ZABBIX_CONFIG | '' | if not set uses default location |
| ZABBIX_UNKNOWN_TABLES | '' | if set, changed to -f (force) |
| ZABBIX_DB_PORT | '' | if set, sets -P parameter on zabbix backup script to override auto get from zabbix server config |
### zabbix Control files

View File

@@ -31,16 +31,16 @@ MODULE_LIST="file gitea mysql pgsql zabbix"
# -n for dry run test
while getopts ":c:snd" opt; do
case "${opt}" in
c|config)
c) # config
BASE_FOLDER=${OPTARG};
;;
s|nosudo)
s) # nosudo
PGSQL_SUDO=0;
;;
d|debug)
d) # debug
DEBUG=1;
;;
n|dryrun)
n) # dryrun
DRYRUN=1;
;;
:)
@@ -64,9 +64,10 @@ if [ ! -f "${BASE_FOLDER}${SETTINGS_FILE}" ]; then
echo "Could not find: ${BASE_FOLDER}${SETTINGS_FILE}";
exit;
fi;
# shellcheck source="borg.backup.settings"
. "${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}");
fi;
export BORG_BASE_DIR="${BASE_FOLDER}";
@@ -82,16 +83,16 @@ for MODULE in ${MODULE_LIST}; do
TARGET_FOLDER=${TARGET_FOLDER#/}
# and add slash front and back and escape the path
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}/";
# 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}/";
# user/host
elif [ ! -z "${TARGET_USER}" ] && [ ! -z "${TARGET_HOST}" ]; then
elif [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_USER}@${TARGET_HOST}:";
# host
elif [ ! -z "${TARGET_HOST}" ]; then
elif [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_HOST}:";
fi;
# 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 just date, add gitea,
# else rename
if [ ! -z "${i##gitea*}" ]; then
if [ -n "${i##gitea*}" ]; then
target_name="${MODULE},${i}";
else
target_name=$(echo $i | sed -e 's/gitea-/gitea,/');
fi;
elif [ "${MODULE}" = "zabbix" ]; then
# if zabbix is missing, prefix
if [ ! -z "${i##zabbix*}" ]; then
if [ -n "${i##zabbix*}" ]; then
target_name="${MODULE},${i}";
else
target_name=$(echo $i | sed -e 's/zabbix-settings-/zabbix,settings-/');

View File

@@ -45,7 +45,7 @@ while read include_folder; do
echo "# [C] Comment: '${include_folder}'";
else
# 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 [[ "${include_folder}" =~ $REGEX_GLOB ]]; then
# if this is */ then allow it
@@ -99,7 +99,7 @@ if [ -s "${BASE_FOLDER}${EXCLUDE_FILE}" ]; then
# remove non valid ones and warn
#TMP_EXCLUDE_FILE=$(mktemp --tmpdir ${EXCLUDE_FILE}.XXXXXXXX); # non mac
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
exclude_folder=$(echo "${exclude_folder}" | sed -e 's/^[ \t]*//');
# folder or any type of file is ok
@@ -108,7 +108,7 @@ if [ -s "${BASE_FOLDER}${EXCLUDE_FILE}" ]; then
echo "# [C] Comment: '${exclude_folder}'";
else
# 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 [[ "${exclude_folder}" != /* ]]; then
echo "${exclude_folder}" >> ${TMP_EXCLUDE_FILE};

View File

@@ -54,7 +54,7 @@ if [ ${RUN_CHECK} -eq 1 ]; then
OPT_GLOB="";
if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then
OPT_GLOB="-a '${CHECK_PREFIX}'"
elif [ ! -z "${CHECK_PREFIX}" ]; then
elif [ -n "${CHECK_PREFIX}" ]; then
OPT_GLOB="-P ${CHECK_PREFIX}";
fi;
# debug/dryrun

View File

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

View File

@@ -7,7 +7,7 @@ fi;
# compact (only if BORG COMPACT is set)
# 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;
if [ $# -ge 1 ] && [ "$1" = "auto" ]; then
# strip any spaces and convert to int
@@ -18,11 +18,11 @@ if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then
fi;
# get current date timestmap
CURRENT_DATE=$(date +%s);
if [ ${COMPACT_INTERVAL} -eq 1 ]; then
if [ "${COMPACT_INTERVAL}" -eq 1 ]; then
RUN_COMPACT=1;
# set new compact time here
echo ${CURRENT_DATE} > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
elif [ ${COMPACT_INTERVAL} -gt 1 ]; then
echo "${CURRENT_DATE}" > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
elif [ "${COMPACT_INTERVAL}" -gt 1 ]; then
# else load last timestamp and check if today - last time stamp > days
if [ -z "${LAST_COMPACT_DATE}" ]; then
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;
fi;
# 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;
# set new compact time here
echo ${CURRENT_DATE} > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
echo "${CURRENT_DATE}" > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
fi;
fi;
elif [ ${COMPACT} -eq 1 ]; then
elif [ "${COMPACT}" -eq 1 ]; then
RUN_COMPACT=1;
fi;
if [ ${RUN_COMPACT} -eq 1 ]; then
# reset to normal IFS, so command works here
IFS=${_IFS};
# shellcheck disable=SC2059
printf "${PRINTF_SUB_BLOCK}" "COMPACT" "$(date +'%F %T')" "${MODULE}";
BORG_COMPACT="${BORG_COMMAND} compact ${OPT_REMOTE} -v ${OPT_PROGRESS} ${REPOSITORY}";
if [ ${DEBUG} -eq 1 ]; then
if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMPACT}";
fi;
if [ ${DRYRUN} -eq 0 ]; then
if [ "${DRYRUN}" -eq 0 ]; then
${BORG_COMPACT};
fi;
fi;

View File

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

View File

@@ -24,7 +24,7 @@ function version {
}
# version for all general files
VERSION="4.4.0";
VERSION="4.5.4";
# borg version and borg comamnd
BORG_VERSION="";
@@ -95,7 +95,8 @@ PRINTF_INFO_STRING="%-23s: %s\n";
PRINTF_MASTER_BLOCK="=== [%-8s: %19s] ==[%s]====================================>\n";
PRINTF_SUB_BLOCK="|-- [%-8s: %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_VERBOSE="";
OPT_PROGRESS="";
@@ -152,17 +153,21 @@ MYSQL_DB_CONFIG="";
MYSQL_DB_CONFIG_PARAM="";
# gitea module
GIT_USER="";
GITEA_TMP="";
GITEA_WORKING_DIR="";
GITEA_TEMP_DIR="";
GITEA_BIN="";
GITEA_CONFIG="";
GITEA_EXPORT_TYPE="";
# zabbix module
ZABBIX_DUMP_BIN="";
ZABBIX_CONFIG="";
ZABBIX_DATABASE="";
ZABBIX_UNKNOWN_TABLES="";
ZABBIX_DB_PORT="";
OPT_ZABBIX_DUMP="";
OPT_ZABBIX_CONFIG="";
OPT_ZABBIX_UNKNOWN_TABLES="";
OPT_ZABBIX_DB_PORT="";
# default keep 7 days, 4 weeks, 6 months, 1 year
# if set 0, ignore/off
# 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;
fi;
# 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";
exit 1;
fi;
# 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.";
exit 1;
elif [ ! -z "${ONE_TIME_TAG}" ]; then
elif [ -n "${ONE_TIME_TAG}" ]; then
# all ok, attach . at the end
ONE_TIME_TAG=${ONE_TIME_TAG}".";
fi;
# 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";
exit 1;
fi;
# -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\*$ ]]
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 "Please verify existing tags with -P option."
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;
fi;
# -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";
exit 1;
fi;
@@ -399,14 +404,14 @@ fi;
. "${BASE_FOLDER}${SETTINGS_FILE}";
# if OPTION SET overrides ALL others
if [ ! -z "${OPT_BORG_EXECUTEABLE}" ]; then
if [ -n "${OPT_BORG_EXECUTEABLE}" ]; then
BORG_COMMAND="${OPT_BORG_EXECUTEABLE}";
if [ ! -f "${BORG_COMMAND}" ]; then
echo "borg command not found with option -b: ${BORG_COMMAND}";
exit;
fi;
# if in setting file, use this
elif [ ! -z "${BORG_EXECUTEABLE}" ]; then
elif [ -n "${BORG_EXECUTEABLE}" ]; then
BORG_COMMAND="${BORG_EXECUTEABLE}";
if [ ! -f "${BORG_COMMAND}" ]; then
echo "borg command not found with setting: ${BORG_COMMAND}";
@@ -446,7 +451,7 @@ if [ -z "${CHECK_INTERVAL}" ]; then
CHECK_INTERVAL="${DEFAULT_CHECK_INTERVAL}";
fi;
# deprecated name FORCE_CHECK, use FORCE_VERIFY instead
if [ ! -z "${FORCE_CHECK}" ]; then
if [ -n "${FORCE_CHECK}" ]; then
FORCE_VERIFY="${FORCE_CHECK}";
fi;
if [ -z "${FORCE_VERIFY}" ]; then
@@ -477,48 +482,48 @@ SETTINGS_FILE_SUB=$(echo "${SETTINGS_FILE}" | sed -e "s/\.settings/\.${MODULE,,}
if [ -f "${BASE_FOLDER}${SETTINGS_FILE_SUB}" ]; then
. "${BASE_FOLDER}${SETTINGS_FILE_SUB}";
# if SUB_ set override master
if [ ! -z "${SUB_BACKUP_FILE}" ]; then
if [ -n "${SUB_BACKUP_FILE}" ]; then
BACKUP_FILE=${SUB_BACKUP_FILE}
fi;
# 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};
fi;
# ovrride compression
if [ ! -z "${SUB_COMPRESSION}" ]; then
if [ -n "${SUB_COMPRESSION}" ]; then
COMPRESSION=${SUB_COMPRESSION};
fi;
if [ ! -z "${SUB_COMPRESSION_LEVEL}" ]; then
if [ -n "${SUB_COMPRESSION_LEVEL}" ]; then
COMPRESSION_LEVEL=${SUB_COMPRESSION_LEVEL};
fi;
# compact interval override
if [ ! -z "${SUB_COMPACT_INTERVAL}" ]; then
if [ -n "${SUB_COMPACT_INTERVAL}" ]; then
COMPACT_INTERVAL="${SUB_COMPACT_INTERVAL}";
fi;
# override check interval
if [ ! -z "${SUB_CHECK_INTERVAL}" ]; then
if [ -n "${SUB_CHECK_INTERVAL}" ]; then
CHECK_INTERVAL="${SUB_CHECK_INTERVAL}";
fi;
# check override for keep time
if [ ! -z "${SUB_KEEP_LAST}" ]; then
if [ -n "${SUB_KEEP_LAST}" ]; then
KEEP_LAST=${SUB_KEEP_LAST};
fi;
if [ ! -z "${SUB_KEEP_HOURS}" ]; then
if [ -n "${SUB_KEEP_HOURS}" ]; then
KEEP_HOURS=${SUB_KEEP_HOURS};
fi;
if [ ! -z "${SUB_KEEP_DAYS}" ]; then
if [ -n "${SUB_KEEP_DAYS}" ]; then
KEEP_DAYS=${SUB_KEEP_DAYS};
fi;
if [ ! -z "${SUB_KEEP_WEEKS}" ]; then
if [ -n "${SUB_KEEP_WEEKS}" ]; then
KEEP_WEEKS=${SUB_KEEP_WEEKS};
fi;
if [ ! -z "${SUB_KEEP_MONTHS}" ]; then
if [ -n "${SUB_KEEP_MONTHS}" ]; then
KEEP_MONTHS=${SUB_KEEP_MONTHS};
fi;
if [ ! -z "${SUB_KEEP_YEARS}" ]; then
if [ -n "${SUB_KEEP_YEARS}" ]; then
KEEP_YEARS=${SUB_KEEP_YEARS};
fi;
if [ ! -z "${SUB_KEEP_WITHIN}" ]; then
if [ -n "${SUB_KEEP_WITHIN}" ]; then
KEEP_WITHIN=${SUB_KEEP_WITHIN};
fi;
fi;
@@ -566,7 +571,7 @@ fi
# log file set and check
# option folder overrides all other folders
if [ ! -z "${OPT_LOG_FOLDER}" ]; then
if [ -n "${OPT_LOG_FOLDER}" ]; then
LOG_FOLDER="${OPT_LOG_FOLDER}";
fi;
# if empty folder set to default folder
@@ -628,15 +633,15 @@ function convert_time
done;
for ((i=0; i<${#output[@]}; i++)); do
if [ ${output[$i]} -gt 0 ] || [ ! -z "$time_string" ]; then
if [ ! -z "${time_string}" ]; then
if [ ${output[$i]} -gt 0 ] || [ -n "$time_string" ]; then
if [ -n "${time_string}" ]; then
time_string=${time_string}" ";
fi;
time_string=${time_string}${output[$i]}${timenames[$i]};
fi;
done;
if [ ! -z ${ms} ] && [ "${ms}" != "nan" ] && [ ${ms} -gt 0 ]; then
time_string=${time_string}" "${ms}"ms";
if [ -n "${ms}" ] && [ "${ms}" != "nan" ] && [ "${ms}" -gt 0 ]; then
time_string="${time_string} ${ms}ms";
fi;
# just in case the time is 0
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}";
# print last compact date if positive integer
# 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
printf "${PRINTF_INFO_STRING}" "Module compact interval" "${COMPACT_INTERVAL}";
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
# 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;
if [ ${DEBUG} -eq 1 ]; then
if [ "${DEBUG}" -eq 1 ]; then
echo "Force repository verify";
fi;
fi;
# remote borg path
if [ ! -z "${TARGET_BORG_PATH}" ]; then
if [ -n "${TARGET_BORG_PATH}" ]; then
if [[ "${TARGET_BORG_PATH}" =~ \ |\' ]]; then
echo "Space found in ${TARGET_BORG_PATH}. Aborting";
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)
# user@host OR ssh://user@host:port/ IF TARGET_PORT is set
# 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}/";
# 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}/";
# user/host
elif [ ! -z "${TARGET_USER}" ] && [ ! -z "${TARGET_HOST}" ]; then
elif [ -n "${TARGET_USER}" ] && [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_USER}@${TARGET_HOST}:";
# host
elif [ ! -z "${TARGET_HOST}" ]; then
elif [ -n "${TARGET_HOST}" ]; then
TARGET_SERVER="${TARGET_HOST}:";
fi;
# 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
OPT_COMPRESSION='';
if [ ! -z "${COMPRESSION}" ]; then
if [ -n "${COMPRESSION}" ]; then
# valid compression
if [ "${COMPRESSION}" = "lz4" ] || [ "${COMPRESSION}" = "zlib" ] || [ "${COMPRESSION}" = "lzma" ] || [ "${COMPRESSION}" = "zstd" ]; then
OPT_COMPRESSION="-C=${COMPRESSION}";
# if COMPRESSION_LEVEL, check it is a valid regex
# 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;
MAX_COMPRESSION=0;
case "${COMPRESSION}" in
@@ -177,7 +177,7 @@ KEEP_OPTIONS=();
# keep info string (for files)
KEEP_INFO="";
# 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}";
# set empty to avoid problems
KEEP_OPTIONS=("");
@@ -185,32 +185,32 @@ else
# build options and info string,
# also flag BACKUP_SET check if hourly is set
BACKUP_SET_VERIFY=0;
if [ ${KEEP_LAST} -gt 0 ]; then
if [ "${KEEP_LAST}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-last=${KEEP_LAST}");
KEEP_INFO="${KEEP_INFO}, last: ${KEEP_LAST}";
fi;
if [ ${KEEP_HOURS} -gt 0 ]; then
if [ "${KEEP_HOURS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-hourly=${KEEP_HOURS}");
KEEP_INFO="${KEEP_INFO}, hourly: ${KEEP_HOURS}";
BACKUP_SET_VERIFY=1;
fi;
if [ ${KEEP_DAYS} -gt 0 ]; then
if [ "${KEEP_DAYS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-daily=${KEEP_DAYS}");
KEEP_INFO="${KEEP_INFO}, daily: ${KEEP_DAYS}";
fi;
if [ ${KEEP_WEEKS} -gt 0 ]; then
if [ "${KEEP_WEEKS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-weekly=${KEEP_WEEKS}");
KEEP_INFO="${KEEP_INFO}, weekly: ${KEEP_WEEKS}";
fi;
if [ ${KEEP_MONTHS} -gt 0 ]; then
if [ "${KEEP_MONTHS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-monthly=${KEEP_MONTHS}");
KEEP_INFO="${KEEP_INFO}, monthly: ${KEEP_MONTHS}";
fi;
if [ ${KEEP_YEARS} -gt 0 ]; then
if [ "${KEEP_YEARS}" -gt 0 ]; then
KEEP_OPTIONS+=("--keep-yearly=${KEEP_YEARS}");
KEEP_INFO="${KEEP_INFO}, yearly: ${KEEP_YEARS}";
fi;
if [ ! -z "${KEEP_WITHIN}" ]; then
if [ -n "${KEEP_WITHIN}" ]; then
# check for invalid string. can only be number + H|d|w|m|y
if [[ "${KEEP_WITHIN}" =~ ^[0-9]+[Hdwmy]{1}$ ]]; then
KEEP_OPTIONS+=("--keep-within=${KEEP_WITHIN}");
@@ -244,7 +244,7 @@ fi;
if [ -f "${BASE_FOLDER}${BACKUP_LOCK_FILE}" ]; then
LOCK_PID=$(cat "${BASE_FOLDER}${BACKUP_LOCK_FILE}" 2>/dev/null);
# 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: ${$}";
. "${DIR}/borg.backup.functions.close.sh" 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
export BORG_BASE_DIR="${BASE_FOLDER}";
# 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
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
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_RELOCATED_REPO_ACCESS_IS_OK=${_BORG_RELOCATED_REPO_ACCESS_IS_OK};";
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
# else a normal verify is ok
# 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}";
if [ ! -z "${TARGET_SERVER}" ]; then
if [ ${DEBUG} -eq 1 ]; then
if [ -n "${TARGET_SERVER}" ]; then
if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY} 2>&1|grep \"Repository ID:\"";
fi;
# 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;
fi;
# 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
# write init file
echo "[!] Add missing init verify file";
echo "$(date +%s)" > "${BASE_FOLDER}${BACKUP_INIT_FILE}";
date +%s > "${BASE_FOLDER}${BACKUP_INIT_FILE}";
fi;
# 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";
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
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 "For more information run:"
echo "${COMMAND_INFO}";
@@ -325,16 +325,16 @@ if [ ${VERIFY} -eq 1 ] || [ ${INIT} -eq 1 ]; then
exit;
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}";
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}";
fi
if [ ${DRYRUN} -eq 0 ]; then
if [ "${DRYRUN}" -eq 0 ]; then
# should trap and exit properly here
${BORG_COMMAND} init ${OPT_REMOTE} -e ${ENCRYPTION} ${OPT_VERBOSE} ${REPOSITORY};
# write init file
echo "$(date +%s)" > "${BASE_FOLDER}${BACKUP_INIT_FILE}";
date +%s > "${BASE_FOLDER}${BACKUP_INIT_FILE}";
echo "Repository initialized";
echo "For more information run:"
echo "${COMMAND_INFO}";
@@ -342,7 +342,7 @@ if [ ${INIT} -eq 1 ] && [ ${INIT_REPOSITORY} -eq 1 ]; then
. "${DIR}/borg.backup.functions.close.sh";
# exit after init
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 "For more information run:"
echo "${COMMAND_INFO}";
@@ -359,18 +359,18 @@ if [ ! -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then
fi;
# 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}";
FORMAT="{archive:<45} {comment:6} {start} - {end} [{id}] ({username}@{hostname}){NL}"
# 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}";
fi;
# 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} ;
fi;
if [ ${VERBOSE} -eq 1 ]; then
if [ "${VERBOSE}" -eq 1 ]; then
echo "";
echo "Base command info:"
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;
# 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.close.sh";
exit;
fi;
# 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.close.sh";
exit;
fi;
# 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}";
# if a "*" is inside we don't do ONE archive, but globbing via -a option
DELETE_ARCHIVE=""
@@ -415,12 +415,12 @@ if [ ! -z "${DELETE_ONE_TIME_TAG}" ]; then
DELETE_ARCHIVE="::"${DELETE_ONE_TIME_TAG};
fi
# 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="";
fi;
# if exists, delete and exit
# 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}";
fi;
# run delete command if not a dry drun
@@ -432,11 +432,11 @@ if [ ! -z "${DELETE_ONE_TIME_TAG}" ]; then
fi;
# if not a dry run, compact repository after delete
# not that compact only works on borg 1.2
if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then
if [ ${DRYRUN} -eq 0 ]; then
if [ "$(version "$BORG_VERSION")" -ge "$(version "1.2.0")" ]; then
if [ "${DRYRUN}" -eq 0 ]; then
${BORG_COMMAND} compact ${OPT_REMOTE} ${REPOSITORY};
fi;
if [ ${DEBUG} -eq 1 ]; then
if [ "${DEBUG}" -eq 1 ]; then
echo "${BORG_COMMAND} compact ${OPT_REMOTE} ${REPOSITORY}";
fi;
fi;

View File

@@ -2,10 +2,8 @@
# 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="";
GITEA_TMP="";
GITEA_WORKING_DIR="";
GITEA_TEMP_DIR="";
GITEA_BIN="";
GITEA_CONFIG="";

View File

@@ -3,7 +3,7 @@
# Backup gitea database, all git folders and gitea settings
MODULE="gitea"
MODULE_VERSION="1.1.4";
MODULE_VERSION="1.2.1";
DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
@@ -29,9 +29,13 @@ if [ -z "${GIT_USER}" ]; then
GIT_USER="git";
fi;
# set GITEA_* if not set
if [ -z "${GITEA_TMP}" ]; then
if [ -z "${GITEA_WORKING_DIR}" ]; then
# 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;
if [ -z "${GITEA_BIN}" ]; then
GITEA_BIN="/usr/local/bin/gitea";
@@ -39,6 +43,10 @@ fi;
if [ -z "${GITEA_CONFIG}" ]; then
GITEA_CONFIG="/etc/gitea/app.ini"
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
echo "[! $(date +'%F %T')] Cannot find gitea binary";
. "${DIR}/borg.backup.functions.close.sh" 1;
@@ -49,6 +57,16 @@ if [ ! -f "${GITEA_CONFIG}" ]; then
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
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="gitea.backup.zip";
# 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}/");
printf "${PRINTF_SUB_BLOCK}" "BACKUP: git data and database" "$(date +'%F %T')" "${MODULE}";
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
echo "${BORG_PRUNE}";
fi;
@@ -70,13 +88,13 @@ if [ ${DRYRUN} -eq 0 ]; then
# below was an old workaround
#export USER="${LOGNAME}" # workaround for broken gitea EUID check
# make sure temp folder is there and is set as git. user
if [ ! -d "${GITEA_TMP}" ]; then
mkdir -p "${GITEA_TMP}";
if [ ! -d "${GITEA_WORKING_DIR}" ]; then
mkdir -p "${GITEA_WORKING_DIR}";
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
cd "${GITEA_TMP}";
sudo -u ${GIT_USER} ${GITEA_BIN} dump -c ${GITEA_CONFIG} -w ${GITEA_TMP} -L -f - | ${BORG_CALL};
cd "${GITEA_WORKING_DIR}";
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
fi;
if [ -z "${ONE_TIME_TAG}" ]; then

View File

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

View File

@@ -7,7 +7,7 @@
# set last edit date + time
MODULE="pgsql"
MODULE_VERSION="1.2.2";
MODULE_VERSION="1.2.7";
DIR="${BASH_SOURCE%/*}"
@@ -32,7 +32,7 @@ BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
# if info print info and then abort run
. "${DIR}/borg.backup.functions.info.sh";
if [ ! -z "${DATABASE_USER}" ]; then
if [ -n "${DATABASE_USER}" ]; then
DB_USER=${DATABASE_USER};
else
DB_USER='postgres';
@@ -95,16 +95,17 @@ CONN_DB_HOST=''; # -h <host>
CONN_DB_PORT=''; # -p <port>
# ALL IN ONE FILE or PER DATABASE FLAG
if [ ! -z "${DATABASE_FULL_DUMP}" ]; then
if [ -n "${DATABASE_FULL_DUMP}" ]; then
SCHEMA_ONLY='';
schema_flag='data';
if [ "${DATABASE_FULL_DUMP}" = "schema" ]; then
SCHEMA_ONLY='-s';
schema_flag='schema';
fi;
LOCAL_START=$(date +'%s');
printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "all databases" "$(date +'%F %T')" "${MODULE}";
# 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_PREFIX="${MODULE},all-";
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}";
${BORG_PRUNE};
fi;
DURATION=$[ $(date +'%s')-$LOCAL_START ];
printf "${PRINTF_DB_RUN_TIME_SUB_BLOCK}" "DONE" "all databases" "${MODULE}" "$(convert_time ${DURATION})";
else
# dump globals first
db="pg_globals";
schema_flag="data";
LOCAL_START=$(date +'%s');
printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "${db}" "$(date +'%F %T')" "${MODULE}";
# Filename
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}";
${BORG_PRUNE};
fi;
DURATION=$[ $(date +'%s')-$LOCAL_START ];
printf "${PRINTF_DB_RUN_TIME_SUB_BLOCK}" "DONE" "${db}" "${MODULE}" "$(convert_time ${DURATION})";
# 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
LOCAL_START=$(date +'%s');
# get the user who owns the DB too
owner=$(echo ${owner_db} | cut -d "," -f 1);
db=$(echo ${owner_db} | cut -d "," -f 2);
@@ -265,6 +272,8 @@ else
else
echo "- [E] ${db}";
fi;
DURATION=$[ $(date +'%s')-$LOCAL_START ];
printf "${PRINTF_DB_RUN_TIME_SUB_BLOCK}" "DONE" "${db}" "${MODULE}" "$(convert_time ${DURATION})";
done;
fi;
# 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
# any other value it means ever n days, eg 90 would be every 90 days
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
# it can also be "{hostname}-{user}-{now:%Y-%m-%dT%H:%M:%S.%f}"
BACKUP_SET="";
# prune times, how many are kept in each time frame
KEEP_LAST="";
KEEP_HOURS="";
KEEP_DAYS="";
KEEP_WEEKS="";
KEEP_MONTHS="";
KEEP_YEARS="";
KEEP_WITHIN="";

View File

@@ -15,3 +15,5 @@ ZABBIX_DATABASE="";
ZABBIX_CONFIG="";
# unknown tables, default ignore, is set to true, will force backup them
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
ZABBIX_DUMP_BIN="/usr/local/bin/zabbix-dump";
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}";
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
@@ -37,6 +37,10 @@ fi;
if [ "${ZABBIX_DATABASE}" = "psql" ]; then
OPT_ZABBIX_DUMP="-C";
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
echo "[! $(date +'%F %T')] Zabbix dump must have database set to either psql or mysql";
. "${DIR}/borg.backup.functions.close.sh" 1;
@@ -48,7 +52,7 @@ if [ ! -f "${ZABBIX_DUMP_BIN}" ]; then
exit 1;
fi;
# -i (ignore)/ -f (backup)
if [ ! -z "${ZABBIX_UNKNOWN_TABLES}" ]; then
if [ -n "${ZABBIX_UNKNOWN_TABLES}" ]; then
OPT_ZABBIX_UNKNOWN_TABLES="-f";
else
OPT_ZABBIX_UNKNOWN_TABLES="-i";
@@ -70,13 +74,13 @@ fi;
printf "${PRINTF_SUB_BLOCK}" "BACKUP: zabbix settings" "$(date +'%F %T')" "${MODULE}";
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
echo "${BORG_PRUNE}";
fi;
fi;
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;
if [ -z "${ONE_TIME_TAG}" ]; then
printf "${PRINTF_SUB_BLOCK}" "PRUNE" "$(date +'%F %T')" "${MODULE}";

View File

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