Compare commits

...

15 Commits

Author SHA1 Message Date
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
Clemens Schwaighofer
bba8be6a42 Exclude File check is if file is >0 and fix wrong check for tmp file
Exclude file was only checked if it exists, even if it was empty it
would start processing.
In the exclude check there was also a wrong check for the tmp exclude
file, it actually checked if the main exclude file was >0 instead of the
tmp file.
2022-08-30 09:56:20 +09:00
Clemens Schwaighofer
ce3cdc7627 Readme update to fix Marktdown lint issues 2022-08-08 14:51:26 +09:00
Clemens Schwaighofer
67c0b00268 Initialize LAST COMPACT/CHECK date variable 2022-06-07 19:57:36 +09:00
Clemens Schwaighofer
abbcfa883f Add compact auto run in intervals like check archive
Same settings like check archive in days. Auto set to 1 to run after
each prune. Can be controlled per module.
2022-06-06 14:58:36 +09:00
Clemens Schwaighofer
9739436589 Redirect STDERR output from borg backup to STDIN for ANSI code cleanup
gitea dump prints out info/status messages to STDERR. The whole
subprocess then returns this on STDERR and so is not parsed through the
sed regex command.
Redirect STDERR to STDIN
2022-05-31 09:54:56 +09:00
Clemens Schwaighofer
bf0364a0e7 Move lock file clean up to before any exit info is printed
Just try to clean lock file always on exit
2022-04-25 08:57:01 +09:00
Clemens Schwaighofer
8e87503528 Add auto check functionality
CHECK_INTERVAL or SUB_CHECK_INTERVAL in module settings.
If set to 1, will check everytime.
Ever other number is for n days after last check.

FORCE_CHECK for check if repository has been setup os now renamed
FORCE_VERIFY but FORCE_CHECK is currently still honored but deprecated

all *function* shell scripts will abort if run on their own

Print info on last check time if set in info block

Internal updates:
All separator lines are now printf strings for central control.
All module used config/settings file names use $MODULE name
Check functionality is in its own file
2022-04-25 06:49:57 +09:00
16 changed files with 536 additions and 186 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

160
Readme.md
View File

@@ -13,9 +13,11 @@ Version 4.0 introduces default borg repository name with `-file` for the `file`
*Example:* *Example:*
Old backup name Old backup name
```sh ```sh
BACKUP_FILE="some-backup-data.borg" BACKUP_FILE="some-backup-data.borg"
``` ```
Then the file need to be renamed the following way: Then the file need to be renamed the following way:
`mv some-backup-data.borg some-backup-data-file.borg` `mv some-backup-data.borg some-backup-data-file.borg`
@@ -42,57 +44,79 @@ No settings files will be overwritten
## Possible command line options ## Possible command line options
### `-c <config folder>` ### `-c <config folder>`
if this is not given, /usr/local/scripts/borg/ is used if this is not given, /usr/local/scripts/borg/ is used
### `-L <log folder>` ### `-L <log folder>`
override config set and default log folder override config set and default log folder
### `-T <tag>` ### `-T <tag>`
create one time stand alone backup prefixed with tag name create one time stand alone backup prefixed with tag name
### `-D <tag backup set>` ### `-D <tag backup set>`
remove a tagged backup set, full name must be given remove a tagged backup set, full name must be given
### `-b <borg executable>` ### `-b <borg executable>`
override the default borg executable found in path override the default borg executable found in path
### `-P` ### `-P`
print list of archives created print list of archives created
### `-V` ### `-V`
verify if repository exists, if not abort verify if repository exists, if not abort
### `-e` ### `-e`
exit after check
exit after running verify `-V`
### `-I` ### `-I`
init repository (must be run first) init repository (must be run first)
### `-Z`
run `borg compact` over given repository
### `-C` ### `-C`
run `borg check` over given repository run `borg check` over given repository
#### `-y` #### `-y`
Add `--verify-data` to `borg check`. Only works with `-C` Add `--verify-data` to `borg check`. Only works with `-C`
#### `-p <prefix|glob>` #### `-p <prefix|glob>`
Only `borg check` data that has given prefix or glob (with *). Only works with `-C` Only `borg check` data that has given prefix or glob (with *). Only works with `-C`
### `-i` ### `-i`
print out only info print out only info
### `-l` ### `-l`
list files during backup list files during backup
### `-v` ### `-v`
be verbose be verbose
### `-d` ### `-d`
debug output all commands debug output all commands
### `-n` ### `-n`
only do dry run only do dry run
### `-h` ### `-h`
this help page this help page
## Basic Settings ## Basic Settings
@@ -106,7 +130,6 @@ LOG_FOLDER: default `/var/log/borg.backup/`
TARGET_FOLDER: must be set to a path where the backups can be written TARGET_FOLDER: must be set to a path where the backups can be written
BACKUP_FILE: the folder inside the TARGET_FOLDER that is the target for borg. Must end with `.borg` BACKUP_FILE: the folder inside the TARGET_FOLDER that is the target for borg. Must end with `.borg`
Note: BACKUP_FILE is the base name. For all except file (current) a module suffix will be added: Note: BACKUP_FILE is the base name. For all except file (current) a module suffix will be added:
eg: eg:
@@ -115,35 +138,41 @@ eg:
If `FILE_REPOSITORY_COMPATIBLE` is set to `false` in the borg.backup.file.settings then the file borg name will have `-file` added too. Currently this is not added to stay compatible with older scripts If `FILE_REPOSITORY_COMPATIBLE` is set to `false` in the borg.backup.file.settings then the file borg name will have `-file` added too. Currently this is not added to stay compatible with older scripts
All below have default values if not set in the main settings file All below have default values if not set in the main settings file
* COMPRESSION: zstd
* COMPRESSION_LEVEL: 3 * COMPRESSION: zstd
* ENCRYPTION: none * COMPRESSION_LEVEL: 3
* FORCE_CHECK: false * ENCRYPTION: none
* KEEP_LAST: 0 * FORCE_VERIFY: false
* KEEP_HOURS: 0 * COMPACT_INTERVAL: 1
* KEEP_DAYS: 7 * CHECK_INTERVAL: none
* KEEP_WEEKS: 4 * KEEP_LAST: 0
* KEEP_MONTHS: 6 * KEEP_HOURS: 0
* KEEP_YEARS: 1 * KEEP_DAYS: 7
* KEEP_WEEKS: 4
* KEEP_MONTHS: 6
* KEEP_YEARS: 1
All module settings files can have the following prefixed with `SUB_` to override master settings: All module settings files can have the following prefixed with `SUB_` to override master settings:
* SUB_BACKUP_FILE
* SUB_COMPRESSION * SUB_BACKUP_FILE
* SUB_COMPRESSION_LEVEL * SUB_COMPRESSION
* SUB_BACKUP_SET * SUB_COMPRESSION_LEVEL
* SUB_KEEP_LAST * SUB_COMPACT_INTERVAL
* SUB_KEEP_HOURS * SUB_CHECK_INTERVAL
* SUB_KEEP_DAYS * SUB_BACKUP_SET
* SUB_KEEP_WEEKS * SUB_KEEP_LAST
* SUB_KEEP_MONTHS * SUB_KEEP_HOURS
* SUB_KEEP_YEARS * SUB_KEEP_DAYS
* SUB_KEEP_WITHIN * SUB_KEEP_WEEKS
* SUB_KEEP_MONTHS
* SUB_KEEP_YEARS
* SUB_KEEP_WITHIN
## Setup backup via SSH to remote host on `borg.backup.settings` ## Setup backup via SSH to remote host on `borg.backup.settings`
For this the following settings are from interest For this the following settings are from interest
``` ```sh
TARGET_USER=""; TARGET_USER="";
TARGET_HOST=""; TARGET_HOST="";
TARGET_PORT=""; TARGET_PORT="";
@@ -157,6 +186,14 @@ and `TARGET_BORG_PATH="";` if the target borg is in a non default path
`BORG_EXECUTABLE="<full path to borg>"` `BORG_EXECUTABLE="<full path to borg>"`
## Note on CHECK_INTERVAL and SUB_CHECK_INTERVAL
If set to empty or 0 it will not run an automatic check. If set to 1 it will run a check after each backup. Any other value means days differente to the last check.
Running check manually (`-C`) will not reset the last check timestamp.
Automatic checks always add `--verify-data`, with manual `-C` the option `-y` has to be set.
## File backup settings ## File backup settings
On new setups it is recommended to use the `borg.backup.file.setings` and set On new setups it is recommended to use the `borg.backup.file.setings` and set
@@ -165,10 +202,9 @@ to `true`
### Config variables ### Config variables
### Control files ### Control files
``` ```sh
backup.borg.file.include backup.borg.file.include
backup.borg.file.exclude backup.borg.file.exclude
``` ```
@@ -182,16 +218,16 @@ backup.borg.file.exclude
This script must be run as the postgres user, normaly `postgres`. This script must be run as the postgres user, normaly `postgres`.
The postgres user must be added to the backup group for this, so that the basic init file can be created in the borg base folder. The postgres user must be added to the backup group for this, so that the basic init file can be created in the borg base folder.
### 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 |
### Control files ### PostgreSQL Control files
``` ```sh
backup.borg.pgsql.include backup.borg.pgsql.include
backup.borg.pgsql.exclude backup.borg.pgsql.exclude
backup.borg.pgsql.schema-only backup.borg.pgsql.schema-only
@@ -201,16 +237,16 @@ backup.borg.pgsql.schema-only
If non root ident authentication run is used, be sure that the `mysql` user is in the backup group. If non root ident authentication run is used, be sure that the `mysql` user is in the backup group.
### 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. |
### Control files ### MySQLControl files
``` ```sh
backup.borg.mysql.include backup.borg.mysql.include
backup.borg.mysql.exclude backup.borg.mysql.exclude
backup.borg.mysql.schema-only backup.borg.mysql.schema-only
@@ -221,31 +257,49 @@ backup.borg.mysql.schema-only
Note that the backup needs the GIT_USER set that runs gitea. Note that the backup needs the GIT_USER set that runs gitea.
This user is neede to create the temporary dump folder and access for the git files and database. This user is neede to create the temporary dump folder and access for the git files and database.
### 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
### Control files
There are no control files for gitea backup There are no control files for gitea backup
## zabbix config backup settings ## zabbix config backup settings
### 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) |
### Control files ### zabbix Control files
There are no control files for zabbix settings backup There are no control files for zabbix settings backup
## File connection
Running any of the commands below
* borg.backup.file.sh
* borg.backup.gitea.sh
* borg.backup.mysql.sh
* borg.backup.pgsql.sh
* borg.backup.zabbix.sh
1) Run `borg.backup.functions.init.sh` (always)
2) Run `borg.backup.functions.verify.sh` (always)
3) (other code in "file" module)
4) Run `borg.backup.functions.info.sh` (always)
5) Run `borg.backup.functions.compact.sh` (not if one time tag)
6) Run `borg.backup.functions.check.sh` (not if one time tag)
7) Run `borg.backup.functions.close.sh` (always, can be called on error too)

View File

@@ -4,17 +4,21 @@
# set last edit date + time # set last edit date + time
MODULE="file"; MODULE="file";
MODULE_VERSION="1.2.1"; 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
. "${DIR}/borg.backup.functions.init.sh"; . "${DIR}/borg.backup.functions.init.sh";
# include and exclude file # include and exclude file
INCLUDE_FILE="borg.backup.file.include"; INCLUDE_FILE="borg.backup.${MODULE}.include";
EXCLUDE_FILE="borg.backup.file.exclude"; EXCLUDE_FILE="borg.backup.${MODULE}.exclude";
# init verify file # init verify, compact and check file
BACKUP_INIT_VERIFY="borg.backup.file.init"; BACKUP_INIT_FILE="borg.backup.${MODULE}.init";
BACKUP_COMPACT_FILE="borg.backup.${MODULE}.compact";
BACKUP_CHECK_FILE="borg.backup.${MODULE}.check";
# lock file
BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
# verify valid data # verify valid data
. "${DIR}/borg.backup.functions.verify.sh"; . "${DIR}/borg.backup.functions.verify.sh";
@@ -25,7 +29,7 @@ if [ ! -f "${BASE_FOLDER}${INCLUDE_FILE}" ]; then
. "${DIR}/borg.backup.functions.close.sh" 1; . "${DIR}/borg.backup.functions.close.sh" 1;
exit 1; exit 1;
fi; fi;
echo "--- [INCLUDE: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUB_BLOCK}" "INCLUDE" "$(date +'%F %T')" "${MODULE}";
# folders to backup # folders to backup
FOLDERS=(); FOLDERS=();
# this if for debug output with quoted folders # this if for debug output with quoted folders
@@ -88,9 +92,9 @@ while read include_folder; do
fi; fi;
done<"${BASE_FOLDER}${INCLUDE_FILE}"; done<"${BASE_FOLDER}${INCLUDE_FILE}";
# exclude list # exclude list, only if file exists and is larger than zero
if [ -f "${BASE_FOLDER}${EXCLUDE_FILE}" ]; then if [ -s "${BASE_FOLDER}${EXCLUDE_FILE}" ]; then
echo "--- [EXCLUDE: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUB_BLOCK}" "EXCLUDE" "$(date +'%F %T')" "${MODULE}";
# check that the folders in that exclude file are actually valid, # check that the folders in that exclude file are actually valid,
# 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
@@ -143,7 +147,7 @@ if [ -f "${BASE_FOLDER}${EXCLUDE_FILE}" ]; then
fi; fi;
done<"${BASE_FOLDER}${EXCLUDE_FILE}"; done<"${BASE_FOLDER}${EXCLUDE_FILE}";
# avoid blank file add by checking if the tmp file has a size >0 # avoid blank file add by checking if the tmp file has a size >0
if [ -s "${BASE_FOLDER}${EXCLUDE_FILE}" ]; then if [ -s "${TMP_EXCLUDE_FILE}" ]; then
OPT_EXCLUDE="--exclude-from=${TMP_EXCLUDE_FILE}"; OPT_EXCLUDE="--exclude-from=${TMP_EXCLUDE_FILE}";
fi; fi;
fi; fi;
@@ -159,7 +163,7 @@ COMMAND=${COMMAND}${REPOSITORY}::${ONE_TIME_TAG}${BACKUP_SET_PREFIX}${BACKUP_SET
. "${DIR}/borg.backup.functions.info.sh"; . "${DIR}/borg.backup.functions.info.sh";
if [ $FOLDER_OK -eq 1 ]; then if [ $FOLDER_OK -eq 1 ]; then
echo "--- [BACKUP: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUB_BLOCK}" "BACKUP" "$(date +'%F %T')" "${MODULE}";
# show command # show command
if [ ${DEBUG} -eq 1 ]; then if [ ${DEBUG} -eq 1 ]; then
echo $(echo ${COMMAND} | sed -e 's/[ ][ ]*/ /g') ${FOLDERS_Q[*]}; echo $(echo ${COMMAND} | sed -e 's/[ ][ ]*/ /g') ${FOLDERS_Q[*]};
@@ -182,7 +186,7 @@ fi;
# clean up, always verbose, but only if we do not run one time tag # clean up, always verbose, but only if we do not run one time tag
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "--- [PRUNE : $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUB_BLOCK}" "PRUNE" "$(date +'%F %T')" "${MODULE}";
# build command # build command
COMMAND="${BORG_COMMAND} prune ${OPT_REMOTE} -v --list ${OPT_PROGRESS} ${DRY_RUN_STATS} -P ${BACKUP_SET_PREFIX} ${KEEP_OPTIONS[*]} ${REPOSITORY}"; COMMAND="${BORG_COMMAND} prune ${OPT_REMOTE} -v --list ${OPT_PROGRESS} ${DRY_RUN_STATS} -P ${BACKUP_SET_PREFIX} ${KEEP_OPTIONS[*]} ${REPOSITORY}";
echo "Prune repository with keep${KEEP_INFO:1}"; echo "Prune repository with keep${KEEP_INFO:1}";
@@ -192,7 +196,9 @@ if [ -z "${ONE_TIME_TAG}" ]; then
# for the IFS="#" to work we need to replace options spaces with exactly ONE # # for the IFS="#" to work we need to replace options spaces with exactly ONE #
$(echo "${COMMAND}" | sed -e 's/[ ][ ]*/#/g') 2>&1 || echo "[!] Borg prune aborted"; $(echo "${COMMAND}" | sed -e 's/[ ][ ]*/#/g') 2>&1 || echo "[!] Borg prune aborted";
# if this is borg version >1.2 we need to run compact after prune # if this is borg version >1.2 we need to run compact after prune
. "${DIR}/borg.backup.functions.compact.sh"; . "${DIR}/borg.backup.functions.compact.sh" "auto";
# check in auto mode
. "${DIR}/borg.backup.functions.check.sh" "auto";
else else
echo "[#] No prune with tagged backup"; echo "[#] No prune with tagged backup";
fi; fi;

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env bash
if [ -z "${MODULE}" ]; then
echo "Script cannot be run on its own";
exit 1;
fi;
# run borg check (NOT REPAIR)
RUN_CHECK=0;
if [ $# -ge 1 ] && [ "$1" = "auto" ]; then
# strip any spaces and convert to int
CHECK_INTERVAL=$(echo "${CHECK_INTERVAL}" | sed -e 's/ //g');
# not a valid check interval, do no check
if [ -z "${CHECK_INTERVAL##*[!0-9]*}" ]; then
CHECK_INTERVAL=0;
fi;
# get current date timestmap
CURRENT_DATE=$(date +%s);
# if =1 always ok
if [ ${CHECK_INTERVAL} -eq 1 ]; then
RUN_CHECK=1;
# always add verify data for automatic check
OPT_CHECK_VERIFY_DATA="--verify-data";
# set new check time here
echo ${CURRENT_DATE} > "${BASE_FOLDER}${BACKUP_CHECK_FILE}";
elif [ ${CHECK_INTERVAL} -gt 1 ]; then
# else load last timestamp and check if today - last time stamp > days
if [ -z "${LAST_CHECK_DATE}" ]; then
LAST_CHECK_DATE=$(cat "${BASE_FOLDER}${BACKUP_CHECK_FILE}" 2>/dev/null | sed -e 's/ //g');
fi;
# file date is not a timestamp
if [ -z "${LAST_CHECK_DATE##*[!0-9]*}" ]; then
LAST_CHECK_DATE=0;
fi;
# if the difference greate than check date, run. CHECK INTERVAL is in days
if [ $(($CURRENT_DATE-$LAST_CHECK_DATE)) -ge $((${CHECK_INTERVAL}*86400)) ]; then
RUN_CHECK=1;
# always add verify data for automatic check
OPT_CHECK_VERIFY_DATA="--verify-data";
# set new check time here
echo ${CURRENT_DATE} > "${BASE_FOLDER}${BACKUP_CHECK_FILE}";
fi;
fi;
elif [ ${CHECK} -eq 1 ]; then
RUN_CHECK=1;
fi;
if [ ${RUN_CHECK} -eq 1 ]; then
# run borg check command
IFS=${_IFS};
printf "${PRINTF_SUB_BLOCK}" "CHECK" "$(date +'%F %T')" "${MODULE}";
# repare command
OPT_GLOB="";
if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then
OPT_GLOB="-a '${CHECK_PREFIX}'"
elif [ ! -z "${CHECK_PREFIX}" ]; then
OPT_GLOB="-P ${CHECK_PREFIX}";
fi;
# debug/dryrun
if [ ${DEBUG} -eq 1 ] || [ ${DRYRUN} -eq 1 ]; then
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} check ${OPT_REMOTE} ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} ${OPT_GLOB} ${REPOSITORY}";
fi;
# run info command if not a dry drun
if [ ${DRYRUN} -eq 0 ]; then
# if glob add glob command directly
if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then
${BORG_COMMAND} check ${OPT_REMOTE} ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} -a "${CHECK_PREFIX}" ${REPOSITORY};
else
${BORG_COMMAND} check ${OPT_REMOTE} ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} ${OPT_GLOB} ${REPOSITORY};
fi;
fi;
# print additional info for use --repair command
# but only for manual checks
if [ ${VERBOSE} -eq 1 ] && [ ${CHECK} -eq 1 ]; then
echo "";
echo "In case of needed repair: "
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"
fi;
fi;
# __END__

View File

@@ -1,14 +1,24 @@
#!/usr/bin/env bash #!/usr/bin/env bash
if [ -z "${MODULE}" ]; then
echo "Script cannot be run on its own";
exit 1;
fi;
# unset borg settings # unset borg settings
unset BORG_BASE_DIR BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK BORG_RELOCATED_REPO_ACCESS_IS_OK unset BORG_BASE_DIR BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK BORG_RELOCATED_REPO_ACCESS_IS_OK
# delete lock file if it exists
if [ -f "${BASE_FOLDER}${BACKUP_LOCK_FILE}" ]; then
rm "${BASE_FOLDER}${BACKUP_LOCK_FILE}";
fi;
# error abort without duration and error notice # error abort without duration and error notice
if [ $# -ge 1 ] && [ "$1" = "1" ]; then if [ $# -ge 1 ] && [ "$1" = "1" ]; then
echo "=== [ERROR: $(date +'%F %T')] ==[${MODULE}]====================================>"; printf "${PRINTF_MASTER_BLOCK}" "ERROR" "$(date +'%F %T')" "${MODULE}";
else else
# running time calculation
DURATION=$[ $(date +'%s')-$START ]; DURATION=$[ $(date +'%s')-$START ];
echo "=== [Run time: $(convert_time ${DURATION})]"; echo "=== [Run time: $(convert_time ${DURATION})]";
echo "=== [END : $(date +'%F %T')] ==[${MODULE}]====================================>"; printf "${PRINTF_MASTER_BLOCK}" "END" "$(date +'%F %T')" "${MODULE}";
fi; fi;
# __END__ # __END__

View File

@@ -1,18 +1,58 @@
#!/usr/bin/env bash #!/usr/bin/env bash
if [ -z "${MODULE}" ]; then
echo "Script cannot be run on its own";
exit 1;
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
# reset to normal IFS, so command works here
IFS=${_IFS};
if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then if [ $(version $BORG_VERSION) -ge $(version "1.2.0") ]; then
echo "--- [COMPACT:$(date +'%F %T')] --[${MODULE}]------------------------------------>"; RUN_COMPACT=0;
BORG_COMPACT="${BORG_COMMAND} compact -v ${OPT_PROGRESS} ${REPOSITORY}"; if [ $# -ge 1 ] && [ "$1" = "auto" ]; then
if [ ${DEBUG} -eq 1 ]; then # strip any spaces and convert to int
echo "${BORG_COMPACT}"; COMPACT_INTERVAL=$(echo "${COMPACT_INTERVAL}" | sed -e 's/ //g');
# not a valid compact interval, do no compact
if [ -z "${COMPACT_INTERVAL##*[!0-9]*}" ]; then
COMPACT_INTERVAL=0;
fi;
# get current date timestmap
CURRENT_DATE=$(date +%s);
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
# 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');
fi;
# file date is not a timestamp
if [ -z "${LAST_COMPACT_DATE##*[!0-9]*}" ]; 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
RUN_COMPACT=1;
# set new compact time here
echo ${CURRENT_DATE} > "${BASE_FOLDER}${BACKUP_COMPACT_FILE}";
fi;
fi;
elif [ ${COMPACT} -eq 1 ]; then
RUN_COMPACT=1;
fi; fi;
if [ ${DRYRUN} -eq 0 ]; then
${BORG_COMPACT}; if [ ${RUN_COMPACT} -eq 1 ]; then
# reset to normal IFS, so command works here
IFS=${_IFS};
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
echo "${BORG_COMPACT}";
fi;
if [ ${DRYRUN} -eq 0 ]; then
${BORG_COMPACT};
fi;
fi; fi;
fi; fi;

View File

@@ -1,7 +1,12 @@
#!/usr/bin/env bash #!/usr/bin/env bash
if [ -z "${MODULE}" ]; then
echo "Script cannot be run on its own";
exit 1;
fi;
if [ ${INFO} -eq 1 ]; then if [ ${INFO} -eq 1 ]; then
echo "--- [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}";

View File

@@ -1,5 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
if [ -z "${MODULE}" ]; then
echo "Script cannot be run on its own";
exit 1;
fi;
set -ETu #-e -o pipefail set -ETu #-e -o pipefail
trap cleanup SIGINT SIGTERM ERR trap cleanup SIGINT SIGTERM ERR
@@ -19,7 +24,7 @@ function version {
} }
# version for all general files # version for all general files
VERSION="4.3.0"; VERSION="4.4.0";
# borg version and borg comamnd # borg version and borg comamnd
BORG_VERSION=""; BORG_VERSION="";
@@ -42,8 +47,12 @@ SETTINGS_FILE="borg.backup.settings";
INCLUDE_FILE=""; INCLUDE_FILE="";
EXCLUDE_FILE=""; EXCLUDE_FILE="";
# backup folder initialzed verify # backup folder initialzed verify
BACKUP_INIT_VERIFY=""; BACKUP_INIT_FILE="";
BACKUP_INIT_DATE=""; BACKUP_INIT_DATE="";
# file with last compact date
BACKUP_COMPACT_FILE="";
# file with last check timestamp
BACKUP_CHECK_FILE="";
# one time backup prefix tag, if set will use <tag>.<prefix>-Y-M-DTh:m:s type backup prefix # one time backup prefix tag, if set will use <tag>.<prefix>-Y-M-DTh:m:s type backup prefix
ONE_TIME_TAG=""; ONE_TIME_TAG="";
DELETE_ONE_TIME_TAG=""; DELETE_ONE_TIME_TAG="";
@@ -58,6 +67,7 @@ INFO=0;
VERIFY=0; VERIFY=0;
CHECK=0; CHECK=0;
CHECK_VERIFY_DATA=0; CHECK_VERIFY_DATA=0;
COMPACT=0;
INIT=0; INIT=0;
EXIT=0; EXIT=0;
PRINT=0; PRINT=0;
@@ -80,6 +90,13 @@ PRUNE_DEBUG="";
INIT_REPOSITORY=0; INIT_REPOSITORY=0;
FOLDER_OK=0; FOLDER_OK=0;
TMP_EXCLUDE_FILE=""; TMP_EXCLUDE_FILE="";
# printf strings
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_RUN_TIME_SUB_BLOCK=">>- [%-8s: %s] ==[%s]==[Run time: %s:]=======================>\n";
# opt flags # opt flags
OPT_VERBOSE=""; OPT_VERBOSE="";
OPT_PROGRESS=""; OPT_PROGRESS="";
@@ -114,6 +131,18 @@ ENCRYPTION="";
DEFAULT_FORCE_VERIFY="false"; DEFAULT_FORCE_VERIFY="false";
FORCE_VERIFY=""; FORCE_VERIFY="";
FORCE_CHECK=""; # Deprecated name, use FORCE_VERIFY FORCE_CHECK=""; # Deprecated name, use FORCE_VERIFY
# compact
DEFAULT_COMPACT_INTERVAL="1";
LAST_COMPACT_DATE="";
COMPACT_INTERVAL="";
SUB_COMPACT_INTERVAL="";
# check
# default interval is none
DEFAULT_CHECK_INTERVAL="";
LAST_CHECK_DATE="";
CHECK_INTERVAL="";
SUB_CHECK_INTERVAL="";
# backup set names
BACKUP_SET=""; BACKUP_SET="";
SUB_BACKUP_SET=""; SUB_BACKUP_SET="";
# for database backup only # for database backup only
@@ -124,9 +153,11 @@ 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="";
@@ -174,6 +205,7 @@ function usage()
-T <tag>: create one time stand alone backup prefixed with tag name -T <tag>: create one time stand alone backup prefixed with tag name
-D <tag backup set>: remove a tagged backup set, full name must be given -D <tag backup set>: remove a tagged backup set, full name must be given
-b <borg executable>: override default path -b <borg executable>: override default path
-Z: run compress after prune/backup. Only for borg 1.2 or newer
-C: run borg check if repository is ok -C: run borg check if repository is ok
-y: in combination with -C: add --verify-data -y: in combination with -C: add --verify-data
-p <archive prefix|glob>: in combinatio with -C: only check archives with prefix or glob -p <archive prefix|glob>: in combinatio with -C: only check archives with prefix or glob
@@ -195,7 +227,7 @@ function usage()
} }
# set options # set options
while getopts ":c:L:T:D:b:p:vldniCVeIPyh" opt; do while getopts ":c:L:T:D:b:p:vldniCVeIPyZh" opt; do
case "${opt}" in case "${opt}" in
c|config) c|config)
BASE_FOLDER=${OPTARG}; BASE_FOLDER=${OPTARG};
@@ -212,6 +244,10 @@ while getopts ":c:L:T:D:b:p:vldniCVeIPyh" opt; do
b|borg) b|borg)
OPT_BORG_EXECUTEABLE=${OPTARG}; OPT_BORG_EXECUTEABLE=${OPTARG};
;; ;;
Z|Compact)
# will run compact alone
COMPACT=1;
;;
C|Check) C|Check)
# will run borg check # will run borg check
# alt modes --repository-only, --archives-only, # alt modes --repository-only, --archives-only,
@@ -380,6 +416,7 @@ elif [ ! -z "${BORG_EXECUTEABLE}" ]; then
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;
@@ -404,6 +441,13 @@ fi;
if [ -z "${ENCRYPTION}" ]; then if [ -z "${ENCRYPTION}" ]; then
ENCRYPTION="${DEFAULT_ENCRYPTION}"; ENCRYPTION="${DEFAULT_ENCRYPTION}";
fi; fi;
# check interval override
if [ -z "${COMPACT_INTERVAL}" ]; then
COMPACT_INTERVAL="${DEFAULT_COMPACT_INTERVAL}";
fi;
if [ -z "${CHECK_INTERVAL}" ]; then
CHECK_INTERVAL="${DEFAULT_CHECK_INTERVAL}";
fi;
# deprecated name FORCE_CHECK, use FORCE_VERIFY instead # deprecated name FORCE_CHECK, use FORCE_VERIFY instead
if [ ! -z "${FORCE_CHECK}" ]; then if [ ! -z "${FORCE_CHECK}" ]; then
FORCE_VERIFY="${FORCE_CHECK}"; FORCE_VERIFY="${FORCE_CHECK}";
@@ -450,6 +494,14 @@ if [ -f "${BASE_FOLDER}${SETTINGS_FILE_SUB}" ]; then
if [ ! -z "${SUB_COMPRESSION_LEVEL}" ]; then if [ ! -z "${SUB_COMPRESSION_LEVEL}" ]; then
COMPRESSION_LEVEL=${SUB_COMPRESSION_LEVEL}; COMPRESSION_LEVEL=${SUB_COMPRESSION_LEVEL};
fi; fi;
# compact interval override
if [ ! -z "${SUB_COMPACT_INTERVAL}" ]; then
COMPACT_INTERVAL="${SUB_COMPACT_INTERVAL}";
fi;
# override check interval
if [ ! -z "${SUB_CHECK_INTERVAL}" ]; then
CHECK_INTERVAL="${SUB_CHECK_INTERVAL}";
fi;
# check override for keep time # check override for keep time
if [ ! -z "${SUB_KEEP_LAST}" ]; then if [ ! -z "${SUB_KEEP_LAST}" ]; then
KEEP_LAST=${SUB_KEEP_LAST}; KEEP_LAST=${SUB_KEEP_LAST};
@@ -512,6 +564,9 @@ if [[ ${TARGET_FOLDER} =~ ^~\/ ]]; then
exit 1; exit 1;
fi fi
# COMPACT_INTERVAL must be a number from -1 to 365
# CHECK_INTERVAL must be a number from -1 to 365
# 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 [ ! -z "${OPT_LOG_FOLDER}" ]; then

View File

@@ -1,25 +1,59 @@
#!/usr/bin/env bash #!/usr/bin/env bash
if [ -z "${MODULE}" ]; then
echo "Script cannot be run on its own";
exit 1;
fi;
# start time in seconds # start time in seconds
START=$(date +'%s'); START=$(date +'%s');
# set init date, or today if not file is set # set init date, or today if not file is set
BACKUP_INIT_DATE=$(printf '%(%c)T' $(cat "${BASE_FOLDER}${BACKUP_INIT_VERIFY}" 2>/dev/null)); BACKUP_INIT_DATE='';
if [ -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then
BACKUP_INIT_DATE=$(printf '%(%c)T' $(cat "${BASE_FOLDER}${BACKUP_INIT_FILE}" 2>/dev/null));
fi;
# start logging from here # start logging from here
exec &> >(tee -a "${LOG}"); exec &> >(tee -a "${LOG}");
echo "=== [START : $(date +'%F %T')] ==[${MODULE}]====================================>"; printf "${PRINTF_MASTER_BLOCK}" "START" "$(date +'%F %T')" "${MODULE}";
# show info for version always # show info for version always
echo "Script version : ${VERSION}"; printf "${PRINTF_INFO_STRING}" "Script version" "${VERSION}";
# show type # show type
echo "Backup module : ${MODULE}"; printf "${PRINTF_INFO_STRING}" "Backup module" "${MODULE}";
echo "Module version : ${MODULE_VERSION}"; printf "${PRINTF_INFO_STRING}" "Module version" "${MODULE_VERSION}";
# borg version # borg version
echo "Borg version : ${BORG_VERSION}"; printf "${PRINTF_INFO_STRING}" "Borg version" "${BORG_VERSION}";
# host name # host name
echo "Hostname : ${HOSTNAME}"; printf "${PRINTF_INFO_STRING}" "Hostname" "${HOSTNAME}";
# show base folder always # show base folder always
echo "Base folder : ${BASE_FOLDER}"; printf "${PRINTF_INFO_STRING}" "Base folder" "${BASE_FOLDER}";
# Module init date (when init file was writen) # Module init date (when init file was writen)
echo "Module init date: ${BACKUP_INIT_DATE}"; 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 [ "${COMPACT_INTERVAL##*[!0-9]*}" ]; then
printf "${PRINTF_INFO_STRING}" "Module compact interval" "${COMPACT_INTERVAL}";
if [ -f "${BASE_FOLDER}${BACKUP_COMPACT_FILE}" ]; then
LAST_COMPACT_DATE=$(cat "${BASE_FOLDER}${BACKUP_COMPACT_FILE}" 2>/dev/null);
printf "${PRINTF_INFO_STRING}" "Module last compact" \
"$(printf '%(%c)T' ${LAST_COMPACT_DATE}) ($(convert_time $(($(date +%s)-${LAST_COMPACT_DATE}))) ago)";
else
printf "${PRINTF_INFO_STRING}" "Module last compact" "No compact run yet"
fi;
fi;
fi;
# print last check date if positive integer
if [ "${CHECK_INTERVAL##*[!0-9]*}" ]; then
printf "${PRINTF_INFO_STRING}" "Module check interval" "${CHECK_INTERVAL}";
# get last check date
if [ -f "${BASE_FOLDER}${BACKUP_CHECK_FILE}" ]; then
LAST_CHECK_DATE=$(cat "${BASE_FOLDER}${BACKUP_CHECK_FILE}" 2>/dev/null);
printf "${PRINTF_INFO_STRING}" "Module last check" \
"$(printf '%(%c)T' ${LAST_CHECK_DATE}) ($(convert_time $(($(date +%s)-${LAST_CHECK_DATE}))) ago)";
else
printf "${PRINTF_INFO_STRING}" "Module last check" "No check run yet";
fi;
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
@@ -82,7 +116,7 @@ elif [ ! -z "${TARGET_HOST}" ]; then
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
REPOSITORY="${TARGET_SERVER}${TARGET_FOLDER}${BACKUP_FILE}"; REPOSITORY="${TARGET_SERVER}${TARGET_FOLDER}${BACKUP_FILE}";
echo "Repository : ${REPOSITORY}"; 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='';
@@ -205,6 +239,22 @@ else
fi; fi;
fi; fi;
# check if we have lock file, check pid in lock file, if no matching pid found
# running remove lock file
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
echo "Script is already running on PID: ${$}";
. "${DIR}/borg.backup.functions.close.sh" 1;
exit 1;
else
echo "[#] Clean up stale lock file for PID: ${LOCK_PID}";
rm "${BASE_FOLDER}${BACKUP_LOCK_FILE}";
fi;
fi;
echo "${$}" > "${BASE_FOLDER}${BACKUP_LOCK_FILE}";
# for folders list split set to "#" and keep the old setting as is # for folders list split set to "#" and keep the old setting as is
_IFS=${IFS}; _IFS=${IFS};
IFS="#"; IFS="#";
@@ -239,7 +289,7 @@ COMMAND_INFO="${COMMAND_EXPORT}${BORG_COMMAND} info ${OPT_REMOTE} ${REPOSITORY}"
# 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
echo "--- [VERIFY: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUB_BLOCK}" "VERIFY" "$(date +'%F %T')" "${MODULE}";
if [ ! -z "${TARGET_SERVER}" ]; then if [ ! -z "${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:\"";
@@ -256,10 +306,10 @@ if [ ${VERIFY} -eq 1 ] || [ ${INIT} -eq 1 ]; then
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_VERIFY}" ]; 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_VERIFY}"; echo "$(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
@@ -276,7 +326,7 @@ if [ ${VERIFY} -eq 1 ] || [ ${INIT} -eq 1 ]; then
fi; fi;
fi; fi;
if [ ${INIT} -eq 1 ] && [ ${INIT_REPOSITORY} -eq 1 ]; then if [ ${INIT} -eq 1 ] && [ ${INIT_REPOSITORY} -eq 1 ]; then
echo "--- [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
@@ -284,7 +334,7 @@ if [ ${INIT} -eq 1 ] && [ ${INIT_REPOSITORY} -eq 1 ]; 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_VERIFY}"; echo "$(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}";
@@ -301,7 +351,7 @@ elif [ ${INIT} -eq 1 ] && [ ${INIT_REPOSITORY} -eq 0 ]; then
fi; fi;
# verify for init file # verify for init file
if [ ! -f "${BASE_FOLDER}${BACKUP_INIT_VERIFY}" ]; then if [ ! -f "${BASE_FOLDER}${BACKUP_INIT_FILE}" ]; then
echo "[! $(date +'%F %T')] It seems the repository has never been initialized." echo "[! $(date +'%F %T')] It seems the repository has never been initialized."
echo "Please run -I to initialize or if already initialzed run with -C for init update." echo "Please run -I to initialize or if already initialzed run with -C for init update."
. "${DIR}/borg.backup.functions.close.sh" 1; . "${DIR}/borg.backup.functions.close.sh" 1;
@@ -310,7 +360,7 @@ 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
echo "--- [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
@@ -338,43 +388,23 @@ if [ ${PRINT} -eq 1 ]; then
exit; exit;
fi; fi;
# run borg check command # run borg compact command and exit
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
echo "--- [CHECK : $(date +'%F %T')] --[${MODULE}]------------------------------------>"; . "${DIR}/borg.backup.functions.check.sh";
# repare command
OPT_GLOB="";
if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then
OPT_GLOB="-a '${CHECK_PREFIX}'"
elif [ ! -z "${CHECK_PREFIX}" ]; then
OPT_GLOB="-P ${CHECK_PREFIX}";
fi;
# debug/dryrun
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}";
fi;
# run info command if not a dry drun
if [ ${DRYRUN} -eq 0 ]; then
# if glob add glob command directly
if [[ "${CHECK_PREFIX}" =~ $REGEX_GLOB ]]; then
${BORG_COMMAND} check ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} -a "${CHECK_PREFIX}" ${REPOSITORY};
else
${BORG_COMMAND} check ${OPT_PROGRESS} ${OPT_CHECK_VERIFY_DATA} ${OPT_GLOB} ${REPOSITORY};
fi;
fi;
# print additional info for use --repair command
if [ ${VERBOSE} -eq 1 ]; then
echo "";
echo "In case of needed repair: "
echo "export BORG_BASE_DIR=\"${BASE_FOLDER}\";${BORG_COMMAND} check ${OPT_PROGRESS} --repair ${OPT_GLOB} ${REPOSITORY}";
echo "Before running repair, a copy from the backup should be made because repair might damage a backup"
fi;
. "${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 [ ! -z "${DELETE_ONE_TIME_TAG}" ]; then
echo "--- [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=""
OPT_GLOB=""; OPT_GLOB="";
@@ -404,10 +434,10 @@ if [ ! -z "${DELETE_ONE_TIME_TAG}" ]; then
# 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,15 +3,19 @@
# 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.2"; MODULE_VERSION="1.2.0";
DIR="${BASH_SOURCE%/*}" DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
# init system # init system
. "${DIR}/borg.backup.functions.init.sh"; . "${DIR}/borg.backup.functions.init.sh";
# init verify file # init verify, compact and check file
BACKUP_INIT_VERIFY="borg.backup.gitea.init"; BACKUP_INIT_FILE="borg.backup.${MODULE}.init";
BACKUP_COMPACT_FILE="borg.backup.${MODULE}.compact";
BACKUP_CHECK_FILE="borg.backup.${MODULE}.check";
# lock file
BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
# verify valid data # verify valid data
. "${DIR}/borg.backup.functions.verify.sh"; . "${DIR}/borg.backup.functions.verify.sh";
@@ -25,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";
@@ -35,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;
@@ -45,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
@@ -54,9 +76,9 @@ BACKUP_SET_NAME="${ONE_TIME_TAG}${BACKUP_SET_PREFIX}${BACKUP_SET}";
# borg call # borg call
BORG_CALL=$(echo "${_BORG_CALL}" | sed -e "s/##FILENAME##/${FILENAME}/" | sed -e "s/##BACKUP_SET##/${BACKUP_SET_NAME}/"); BORG_CALL=$(echo "${_BORG_CALL}" | sed -e "s/##FILENAME##/${FILENAME}/" | sed -e "s/##BACKUP_SET##/${BACKUP_SET_NAME}/");
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}/");
echo "--- [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;
@@ -66,21 +88,23 @@ 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};
) | 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
echo "--- [PRUNE : $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUB_BLOCK}" "PRUNE" "$(date +'%F %T')" "${MODULE}";
echo "Prune repository with keep${KEEP_INFO:1}"; echo "Prune repository with keep${KEEP_INFO:1}";
${BORG_PRUNE}; ${BORG_PRUNE};
# if this is borg version >1.2 we need to run compact after prune # if this is borg version >1.2 we need to run compact after prune
. "${DIR}/borg.backup.functions.compact.sh"; . "${DIR}/borg.backup.functions.compact.sh" "auto";
# check in auto mode
. "${DIR}/borg.backup.functions.check.sh" "auto";
fi; fi;
. "${DIR}/borg.backup.functions.close.sh"; . "${DIR}/borg.backup.functions.close.sh";

View File

@@ -7,7 +7,7 @@
# set last edit date + time # set last edit date + time
MODULE="mysql" MODULE="mysql"
MODULE_VERSION="1.1.1"; MODULE_VERSION="1.1.3";
DIR="${BASH_SOURCE%/*}" DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
@@ -15,11 +15,15 @@ if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "${DIR}/borg.backup.functions.init.sh"; . "${DIR}/borg.backup.functions.init.sh";
# include and exclude file # include and exclude file
INCLUDE_FILE="borg.backup.mysql.include"; INCLUDE_FILE="borg.backup.${MODULE}.include";
EXCLUDE_FILE="borg.backup.mysql.exclude"; EXCLUDE_FILE="borg.backup.${MODULE}.exclude";
SCHEMA_ONLY_FILE="borg.backup.mysql.schema-only"; SCHEMA_ONLY_FILE="borg.backup.${MODULE}.schema-only";
# init verify file # init verify, compact and check file
BACKUP_INIT_VERIFY="borg.backup.mysql.init"; BACKUP_INIT_FILE="borg.backup.${MODULE}.init";
BACKUP_COMPACT_FILE="borg.backup.${MODULE}.compact";
BACKUP_CHECK_FILE="borg.backup.${MODULE}.check";
# lock file
BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
# verify valid data # verify valid data
. "${DIR}/borg.backup.functions.verify.sh"; . "${DIR}/borg.backup.functions.verify.sh";
@@ -89,7 +93,8 @@ if [ ! -z "${DATABASE_FULL_DUMP}" ]; then
SCHEMA_ONLY='--no-data'; SCHEMA_ONLY='--no-data';
schema_flag='schema'; schema_flag='schema';
fi; fi;
echo "---[BACKUP: all databases: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; 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 # We only do a full backup and not per table backup here
# Filename # Filename
FILENAME="all-${schema_flag}-${DB_TYPE}_${DB_VERSION}_${DB_HOST}_${DB_PORT}.sql" FILENAME="all-${schema_flag}-${DB_TYPE}_${DB_VERSION}_${DB_HOST}_${DB_PORT}.sql"
@@ -116,15 +121,18 @@ if [ ! -z "${DATABASE_FULL_DUMP}" ]; then
fi; fi;
fi; fi;
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "--- [PRUNE : all databases: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUBEXT_BLOCK}" "PRUNE" "all databases" "$(date +'%F %T')" "${MODULE}";
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" "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
echo "========[DB: ${db}]========================[${MODULE}]====================================>"; LOCAL_START=$(date +'%s');
echo "--- [BACKUP: ${db}: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_DB_SUB_BLOCK}" "DB" "${db}" "${MODULE}";
printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "${db}" "$(date +'%F %T')" "${MODULE}";
# exclude checks # exclude checks
include=0; include=0;
if [ -s "${BASE_FOLDER}${INCLUDE_FILE}" ]; then if [ -s "${BASE_FOLDER}${INCLUDE_FILE}" ]; then
@@ -202,19 +210,23 @@ else
fi; fi;
fi; fi;
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "--- [PRUNE : ${db}: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUBEXT_BLOCK}" "PRUNE" "${db}" "$(date +'%F %T')" "${MODULE}";
echo "Prune repository prefixed ${BACKUP_SET_PREFIX} with keep${KEEP_INFO:1}"; echo "Prune repository prefixed ${BACKUP_SET_PREFIX} with keep${KEEP_INFO:1}";
${BORG_PRUNE}; ${BORG_PRUNE};
fi; fi;
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
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
# if this is borg version >1.2 we need to run compact after prune # if this is borg version >1.2 we need to run compact after prune
. "${DIR}/borg.backup.functions.compact.sh"; . "${DIR}/borg.backup.functions.compact.sh" "auto";
# check in auto mode
. "${DIR}/borg.backup.functions.check.sh" "auto";
fi; fi;
. "${DIR}/borg.backup.functions.close.sh"; . "${DIR}/borg.backup.functions.close.sh";

View File

@@ -7,7 +7,7 @@
# set last edit date + time # set last edit date + time
MODULE="pgsql" MODULE="pgsql"
MODULE_VERSION="1.2.1"; MODULE_VERSION="1.2.4";
DIR="${BASH_SOURCE%/*}" DIR="${BASH_SOURCE%/*}"
@@ -16,12 +16,16 @@ if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "${DIR}/borg.backup.functions.init.sh"; . "${DIR}/borg.backup.functions.init.sh";
# include and exclude file # include and exclude file
INCLUDE_FILE="borg.backup.pgsql.include"; INCLUDE_FILE="borg.backup.${MODULE}.include";
EXCLUDE_FILE="borg.backup.pgsql.exclude"; EXCLUDE_FILE="borg.backup.${MODULE}.exclude";
SCHEMA_ONLY_FILE="borg.backup.pgsql.schema-only"; SCHEMA_ONLY_FILE="borg.backup.${MODULE}.schema-only";
DATA_ONLY_FILE="borg.backup.pgsql.data-only"; DATA_ONLY_FILE="borg.backup.${MODULE}.data-only";
# init verify file # init verify, compact and check file
BACKUP_INIT_VERIFY="borg.backup.pgsql.init"; BACKUP_INIT_FILE="borg.backup.${MODULE}.init";
BACKUP_COMPACT_FILE="borg.backup.${MODULE}.compact";
BACKUP_CHECK_FILE="borg.backup.${MODULE}.check";
# lock file
BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
# verify valid data # verify valid data
. "${DIR}/borg.backup.functions.verify.sh"; . "${DIR}/borg.backup.functions.verify.sh";
@@ -98,7 +102,8 @@ if [ ! -z "${DATABASE_FULL_DUMP}" ]; then
SCHEMA_ONLY='-s'; SCHEMA_ONLY='-s';
schema_flag='schema'; schema_flag='schema';
fi; fi;
echo "--- [BACKUP: all databases: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; LOCAL_START=$(date +'%s');
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:
@@ -124,15 +129,18 @@ if [ ! -z "${DATABASE_FULL_DUMP}" ]; then
fi; fi;
fi; fi;
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "--- [PRUNE : all databases: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUBEXT_BLOCK}" "PRUNE" "all databases" "$(date +'%F %T')" "${MODULE}";
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" "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";
echo "--- [BACKUP: ${db}: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; LOCAL_START=$(date +'%s');
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"
# backup set: # backup set:
@@ -158,19 +166,22 @@ else
fi; fi;
fi; fi;
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "--- [PRUNE : ${db}: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUBEXT_BLOCK}" "PRUNE" "${db}" "$(date +'%F %T')" "${MODULE}";
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}" "BACKUP" "${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);
encoding=$(echo ${owner_db} | cut -d "," -f 3); encoding=$(echo ${owner_db} | cut -d "," -f 3);
echo "========[DB: ${db}]========================[${MODULE}]====================================>"; printf "${PRINTF_DB_SUB_BLOCK}" "DB" "${db}" "${MODULE}";
echo "--- [BACKUP: ${db}: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUBEXT_BLOCK}" "BACKUP" "${db}" "$(date +'%F %T')" "${MODULE}";
include=0; include=0;
if [ -s "${BASE_FOLDER}${INCLUDE_FILE}" ]; then if [ -s "${BASE_FOLDER}${INCLUDE_FILE}" ]; then
while read incl_db; do while read incl_db; do
@@ -254,19 +265,23 @@ else
fi; fi;
fi; fi;
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
echo "--- [PRUNE : ${db}: $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUBEXT_BLOCK}" "PRUNE" "${db}" "$(date +'%F %T')" "${MODULE}";
echo "Prune repository prefixed ${BACKUP_SET_PREFIX} with keep${KEEP_INFO:1}"; echo "Prune repository prefixed ${BACKUP_SET_PREFIX} with keep${KEEP_INFO:1}";
${BORG_PRUNE}; ${BORG_PRUNE};
fi; fi;
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
if [ -z "${ONE_TIME_TAG}" ]; then if [ -z "${ONE_TIME_TAG}" ]; then
# if this is borg version >1.2 we need to run compact after prune # if this is borg version >1.2 we need to run compact after prune
. "${DIR}/borg.backup.functions.compact.sh"; . "${DIR}/borg.backup.functions.compact.sh" "auto";
# check in auto mode
. "${DIR}/borg.backup.functions.check.sh" "auto";
fi; fi;
. "${DIR}/borg.backup.functions.close.sh"; . "${DIR}/borg.backup.functions.close.sh";

View File

@@ -27,8 +27,19 @@ COMPRESSION_LEVEL="";
# Blank passwords allowed for only key (if used, use keyfile) # Blank passwords allowed for only key (if used, use keyfile)
# See: http://borgbackup.readthedocs.io/en/stable/faq.html#how-can-i-specify-the-encryption-passphrase-programmatically # See: http://borgbackup.readthedocs.io/en/stable/faq.html#how-can-i-specify-the-encryption-passphrase-programmatically
ENCRYPTION=""; ENCRYPTION="";
# force repository check, default is off, set to true for check # force repository verify, default is off, set to true for verify on every run
FORCE_CHECK=""; FORCE_VERIFY="";
# compact interval, only if using borg 1.2 or higher
# after how many days to run compress on data
# default is 1 for run after each prune
# set to 0 or negative to turn off
# or any other value for every n days
COMPACT_INTERVAL="";
# check interval, if 0 or negative number, no check will ever run
# if empty fall back to default set
# 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 %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}"

View File

@@ -3,15 +3,19 @@
# Backup zabbix config and settings only # Backup zabbix config and settings only
MODULE="zabbix" MODULE="zabbix"
MODULE_VERSION="1.1.2"; MODULE_VERSION="1.1.3";
DIR="${BASH_SOURCE%/*}" DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
# init system # init system
. "${DIR}/borg.backup.functions.init.sh"; . "${DIR}/borg.backup.functions.init.sh";
# init verify file # init verify, compact and check file
BACKUP_INIT_VERIFY="borg.backup.zabbix.init"; BACKUP_INIT_FILE="borg.backup.${MODULE}.init";
BACKUP_COMPACT_FILE="borg.backup.${MODULE}.compact";
BACKUP_CHECK_FILE="borg.backup.${MODULE}.check";
# lock file
BACKUP_LOCK_FILE="borg.backup.${MODULE}.lock";
# verify valid data # verify valid data
. "${DIR}/borg.backup.functions.verify.sh"; . "${DIR}/borg.backup.functions.verify.sh";
@@ -64,7 +68,7 @@ if [ -z "${BACKUP_SET_PREFIX}" ]; then
BORG_PRUNE=$(echo "${BORG_PRUNE}" | sed -e 's/-P //'); BORG_PRUNE=$(echo "${BORG_PRUNE}" | sed -e 's/-P //');
fi; fi;
echo "--- [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} -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
@@ -75,10 +79,12 @@ 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} -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
echo "--- [PRUNE : $(date +'%F %T')] --[${MODULE}]------------------------------------>"; printf "${PRINTF_SUB_BLOCK}" "PRUNE" "$(date +'%F %T')" "${MODULE}";
${BORG_PRUNE}; ${BORG_PRUNE};
# if this is borg version >1.2 we need to run compact after prune # if this is borg version >1.2 we need to run compact after prune
. "${DIR}/borg.backup.functions.compact.sh"; . "${DIR}/borg.backup.functions.compact.sh" "auto";
# check in auto mode
. "${DIR}/borg.backup.functions.check.sh" "auto";
fi; fi;
. "${DIR}/borg.backup.functions.close.sh"; . "${DIR}/borg.backup.functions.close.sh";

View File

@@ -115,4 +115,4 @@ else
borg umount "${MOUNT_PATH}"; borg umount "${MOUNT_PATH}";
fi; fi;
## END # __END__