1
0
mirror of https://github.com/deajan/obackup.git synced 2026-02-11 17:40:57 +01:00

32 Commits

Author SHA1 Message Date
deajan
884fcf7eff Rebuilt targets for v2.1-beta3 2017-06-21 15:01:28 +02:00
deajan
92da7e68de Bumped version to v2.1-beta3 2017-06-21 15:01:03 +02:00
deajan
c02d301a45 Rebuilt targets 2017-06-20 19:02:22 +02:00
deajan
a48c55ef69 Updated changelog 2017-06-20 18:59:45 +02:00
deajan
83fdc5ee22 Moved rsync code before init 2017-06-20 16:23:14 +02:00
deajan
f097999bd3 Fixed missing rsync args 2017-06-20 16:20:44 +02:00
deajan
9a9a7ac8a3 Better cmdline option management 2017-06-20 15:56:07 +02:00
deajan
c60ac3784d Rebuilt targets 2017-06-20 15:23:29 +02:00
deajan
02fcf746ef Updated merge syntax 2017-06-20 15:22:57 +02:00
deajan
bd06dfe397 Made merge and bootstrap program agonstic 2017-06-20 15:22:37 +02:00
deajan
c7eb51f8a3 Fixed missing fi 2017-06-20 14:53:12 +02:00
deajan
ee689da7f3 Allow --partial, --delete and --dontgetsize to override config files 2017-06-20 14:50:50 +02:00
deajan
27a2b26473 Rebuilt targets 2017-06-09 11:50:10 +02:00
deajan
c2b14377c3 Update ofunctions 2017-06-09 11:49:53 +02:00
deajan
f15f216989 Rebuilt targets 2017-06-09 09:58:51 +02:00
deajan
0ee0bf52fd Updated ofunctions 2017-06-09 09:58:30 +02:00
deajan
8cd3ac6a50 Merge branch 'master' of https://github.com/deajan/obackup 2017-05-30 09:54:08 +02:00
deajan
e916df3e87 Update readme 2017-05-30 09:54:04 +02:00
deajan
be4ba9f366 Update ofunctions 2017-05-30 09:53:30 +02:00
Orsiris de Jong
cbdd836ddd Added BSD license badge 2017-05-22 14:57:55 +02:00
deajan
fbd5317010 Updated ofunctions 2017-05-22 12:05:50 +02:00
deajan
64c32bca07 Update ofunctions 2017-04-20 21:24:04 +02:00
deajan
644346316c Check program type for service files 2017-04-17 20:26:40 +02:00
deajan
304dace821 Added VerComp Subset 2017-04-11 13:28:32 +02:00
deajan
d311ef0574 Update ofunctions 2017-04-11 13:28:08 +02:00
deajan
56010d3a0d Update installer from pmocr 2017-04-11 13:27:58 +02:00
deajan
fefc01983d Added default umask 2017-04-08 22:11:27 +02:00
deajan
faafa81d10 Added umask for log & run dir files 2017-04-08 21:11:53 +02:00
deajan
5302c8c5f0 Updated common_batch from osync project 2017-03-30 22:19:41 +02:00
deajan
e2e4f4b563 Added --remove option to doc 2017-03-30 22:18:52 +02:00
deajan
67ecf9ea0a Update ofunctions from osync project 2017-03-30 22:18:36 +02:00
deajan
6f51b472c5 Updated installer from pmocr 2017-03-14 22:42:01 +01:00
13 changed files with 797 additions and 406 deletions

View File

@@ -9,7 +9,14 @@ KNOWN ISSUES
CHANGELOG
---------
20 Jun 2017: obackup v2.1 beta3 released
----------------------------------------
- Fixed regression where some commandline arguments weren't honored anymore since 2.1 beta1 (--delete, --stats, --dontgetsize)
- Fixed commandline arguments aren't checked against valid list
14 Mar 2017: obackup v2.1 beta2 released
----------------------------------------
- Fixed remote commands can be run on local runs and obviously fail
- Uninstall leaves ssh_filter if needed by other programs

View File

@@ -1,7 +1,8 @@
# obackup [![Build Status](https://travis-ci.org/deajan/obackup.svg?branch=master)](https://travis-ci.org/deajan/obackup) [![GitHub Release](https://img.shields.io/github/release/deajan/obackup.svg?label=Latest)](https://github.com/deajan/obackup/releases/latest)
# obackup [![Build Status](https://travis-ci.org/deajan/obackup.svg?branch=master)](https://travis-ci.org/deajan/obackup) [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![GitHub Release](https://img.shields.io/github/release/deajan/obackup.svg?label=Latest)](https://github.com/deajan/obackup/releases/latest)
A robust file & database backup script that works for local and remote push or pull backups via ssh.
Designed to backup multiple subdirectories with a timeslot for each.
Supports encryption while still using rsync to lower transfered data (see advantages and caveats below).
## About
@@ -34,7 +35,7 @@ You may disable this behavior in the config file.
You can download the latest obackup script from authors website.
You may also clone the following git which will maybe have some more recent builds.
$ git clone -b "v2.0-maint" git://github.com/deajan/obackup.git
$ git clone -b "v2.1-maint" git://github.com/deajan/obackup.git
$ cd obackup
$ ./install.sh

View File

@@ -1,30 +1,64 @@
#!/usr/bin/env bash
## dev pre-processor bootstrap rev 2016121302
## dev pre-processor bootstrap rev 2017062001
## Yeah !!! A really tech sounding name... In fact it's just include emulation in bash
function Usage {
echo "$0 - Quick and dirty preprocessor for including ofunctions into programs"
echo "Creates and executes $0.tmp.sh"
echo "Usage:"
echo ""
echo "$0 --program=osync|osync_target_helper|obackup|pmocr [options to pass to program]"
}
if [ ! -f "./merge.sh" ]; then
echo "Plrase run bootstrap.sh from osync/dev directory."
exit 1
fi
bootstrapProgram=""
opts=""
outputFileName="$0"
source "merge.sh"
__PREPROCESSOR_PROGRAM=obackup
__PREPROCESSOR_Constants
for i in "$@"; do
case $i in
--program=*)
bootstrapProgram="${i##*=}"
;;
*)
opts=$opts" $i"
;;
esac
done
cp "n_$__PREPROCESSOR_PROGRAM.sh" "$outputFileName.tmp.sh"
if [ "$bootstrapProgram" == "" ]; then
Usage
exit 128
else
source "merge.sh"
__PREPROCESSOR_PROGRAM=$bootstrapProgram
__PREPROCESSOR_PROGRAM_EXEC="n_$bootstrapProgram.sh"
__PREPROCESSOR_Constants
if [ ! -f "$__PREPROCESSOR_PROGRAM_EXEC" ]; then
echo "Cannot find file [n_$bootstrapProgram.sh]."
exit 1
fi
fi
cp "$__PREPROCESSOR_PROGRAM_EXEC" "$outputFileName.tmp.sh"
if [ $? != 0 ]; then
echo "Cannot copy original file [n_$__PREPROCESSOR_PROGRAM.sh] to [$outputFileName.tmp.sh]."
echo "Cannot copy original file [$__PREPROCESSOR_PROGRAM_EXEC] to [$outputFileName.tmp.sh]."
exit 1
fi
for subset in "${__PREPROCESSOR_SUBSETS[@]}"; do
__PREPROCESSOR_MergeSubset "$subset" "${subset//SUBSET/SUBSET END}" "ofunctions.sh" "$outputFileName.tmp.sh"
done
chmod +x "$0.tmp.sh"
chmod +x "$outputFileName.tmp.sh"
if [ $? != 0 ]; then
echo "Cannot make [$outputFileName] executable.."
echo "Cannot make [$outputFileName] executable."
exit 1
fi
@@ -33,4 +67,4 @@ if type termux-fix-shebang > /dev/null 2>&1; then
termux-fix-shebang "$outputFileName.tmp.sh"
fi
"$outputFileName.tmp.sh" "$@"
"$outputFileName.tmp.sh" $opts

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
SUBPROGRAM=[prgname]
PROGRAM="$SUBPROGRAM-batch" # Batch program to run osync / obackup instances sequentially and rerun failed ones
AUTHOR="(L) 2013-2016 by Orsiris de Jong"
AUTHOR="(L) 2013-2017 by Orsiris de Jong"
CONTACT="http://www.netpower.fr - ozy@netpower.fr"
PROGRAM_BUILD=2016120401
@@ -119,15 +119,15 @@ function Batch {
fi
done
runList=("${runAgainList[@]}")
runs=$(($runs + 1))
runs=$((runs + 1))
done
fi
}
function Usage {
echo "$PROGRAM $PROGRAM_BUILD"
echo $AUTHOR
echo $CONTACT
echo "$AUTHOR"
echo "$CONTACT"
echo ""
echo "Batch script to sequentially run osync or obackup instances and rerun failed ones."
echo "Usage: $PROGRAM.sh [OPTIONS] [$SUBPROGRAM OPTIONS]"

View File

@@ -12,7 +12,7 @@ PROGRAM_BINARY=$PROGRAM".sh"
PROGRAM_BATCH=$PROGRAM"-batch.sh"
SSH_FILTER="ssh_filter.sh"
SCRIPT_BUILD=2017031402
SCRIPT_BUILD=2017041701
## osync / obackup / pmocr / zsnap install script
## Tested on RHEL / CentOS 6 & 7, Fedora 23, Debian 7 & 8, Mint 17 and FreeBSD 8, 10 and 11
@@ -210,7 +210,9 @@ function CopyProgram {
function CopyServiceFiles {
if ([ "$init" == "systemd" ] && [ -f "$SCRIPT_PATH/$SERVICE_FILE_SYSTEMD_SYSTEM" ]); then
CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_SYSTEMD_SYSTEM" "$SERVICE_FILE_SYSTEMD_SYSTEM" "" "" "" true
CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_SYSTEMD_USER" "$SERVICE_FILE_SYSTEMD_USER" "" "" "" true
if [ -f "$SCRIPT_PATH/$SERVICE_FILE_SYSTEMD_SYSTEM_USER" ]; then
CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_SYSTEMD_USER" "$SERVICE_FILE_SYSTEMD_USER" "" "" "" true
fi
QuickLogger "Created [$SERVICE_NAME] service in [$SERVICE_DIR_SYSTEMD_SYSTEM] and [$SERVICE_DIR_SYSTEMD_USER]."
QuickLogger "Can be activated with [systemctl start SERVICE_NAME@instance.conf] where instance.conf is the name of the config file in $CONF_DIR."
@@ -219,9 +221,9 @@ function CopyServiceFiles {
elif ([ "$init" == "initV" ] && [ -f "$SCRIPT_PATH/$SERVICE_FILE_INIT" ] && [ -d "$SERVICE_DIR_INIT" ]); then
CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_INIT" "$SERVICE_FILE_INIT" "755" "" "" true
QuickLogger "Created osync-srv service in [$SERVICE_DIR_INIT]."
QuickLogger "Can be activated with [service $OSYNC_SERVICE_FILE_INIT start]."
QuickLogger "Can be enabled on boot with [chkconfig $OSYNC_SERVICE_FILE_INIT on]."
QuickLogger "Created [$SERVICE_NAME] service in [$SERVICE_DIR_INIT]."
QuickLogger "Can be activated with [service $SERVICE_FILE_INIT start]."
QuickLogger "Can be enabled on boot with [chkconfig $SERVICE_FILE_INIT on]."
else
QuickLogger "Cannot define what init style is in use on this system. Skipping service file installation."
fi
@@ -263,7 +265,11 @@ function RemoveFile {
function RemoveAll {
RemoveFile "$BIN_DIR/$PROGRAM_BINARY"
RemoveFile "$BIN_DIR/$PROGRAM_BATCH"
if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then
RemoveFile "$BIN_DIR/$PROGRAM_BATCH"
fi
if [ ! -f "$BIN_DIR/osync.sh" ] && [ ! -f "$BIN_DIR/obackup.sh" ]; then # Check if any other program requiring ssh filter is present before removal
RemoveFile "$BIN_DIR/$SSH_FILTER"
else
@@ -281,6 +287,7 @@ function Usage {
echo "options:"
echo "--silent Will log and bypass user interaction."
echo "--no-stats Used with --silent in order to refuse sending anonymous install stats."
echo "--remove Remove the program."
exit 127
}
@@ -323,7 +330,9 @@ else
CreateDir "$BIN_DIR"
CopyExampleFiles
CopyProgram
CopyServiceFiles
if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "pmocr" ]; then
CopyServiceFiles
fi
QuickLogger "$PROGRAM installed. Use with $BIN_DIR/$PROGRAM"
if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then
QuickLogger ""

View File

@@ -6,8 +6,8 @@
PROGRAM="obackup"
AUTHOR="(C) 2013-2017 by Orsiris de Jong"
CONTACT="http://www.netpower.fr/obackup - ozy@netpower.fr"
PROGRAM_VERSION=2.1-beta2
PROGRAM_BUILD=2017021001
PROGRAM_VERSION=2.1-beta3
PROGRAM_BUILD=2017062004
IS_STABLE=no
#### Execution order #__WITH_PARANOIA_DEBUG
@@ -35,8 +35,8 @@ IS_STABLE=no
# FilesBackup #__WITH_PARANOIA_DEBUG
_OFUNCTIONS_VERSION=2.1-RC3+dev
_OFUNCTIONS_BUILD=2017031401
_OFUNCTIONS_VERSION=2.1.4-rc1
_OFUNCTIONS_BUILD=2017060903
_OFUNCTIONS_BOOTSTRAP=true
## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
@@ -61,6 +61,9 @@ fi
## Correct output of sort command (language agnostic sorting)
export LC_ALL=C
## Default umask for file creation
umask 0077
# Standard alert mail body
MAIL_ALERT_MSG="Execution of $PROGRAM instance $INSTANCE_ID on $(date) has warnings/errors."
@@ -97,6 +100,8 @@ if [ "$SLEEP_TIME" == "" ]; then # Leave the possibity to set SLEEP_TIME as envi
fi
SCRIPT_PID=$$
# TODO: Check if %N works on MacOS
TSTAMP=$(date '+%Y%m%dT%H%M%S.%N')
LOCAL_USER=$(whoami)
@@ -288,7 +293,7 @@ function Logger {
return
elif [ "$level" == "VERBOSE" ]; then
if [ $_LOGGER_VERBOSE == true ]; then
_Logger "$prefix:$value" "$prefix$value"
_Logger "$prefix($level):$value" "$prefix$value"
fi
return
elif [ "$level" == "ALWAYS" ]; then
@@ -339,15 +344,29 @@ function KillChilds {
local pid="${1}" # Parent pid to kill childs
local self="${2:-false}" # Should parent be killed too ?
# Warning: pgrep does not exist in cygwin, have this checked in CheckEnvironment
if children="$(pgrep -P "$pid")"; then
for child in $children; do
Logger "Launching KillChilds \"$child\" true" "DEBUG" #__WITH_PARANOIA_DEBUG
KillChilds "$child" true
done
# Paranoid checks, we can safely assume that $pid shouldn't be 0 nor 1
if [ $(IsNumeric "$pid") -eq 0 ] || [ "$pid" == "" ] || [ "$pid" == "0" ] || [ "$pid" == "1" ]; then
Logger "Bogus pid given [$pid]." "CRITICAL"
return 1
fi
# Try to kill nicely, if not, wait 15 seconds to let Trap actions happen before killing
if kill -0 "$pid" > /dev/null 2>&1; then
# Warning: pgrep is not native on cygwin, have this checked in CheckEnvironment
if children="$(pgrep -P "$pid")"; then
if [[ "$pid" == *"$children"* ]]; then
Logger "Bogus pgrep implementation." "CRITICAL"
children="${children/$pid/}"
fi
for child in $children; do
Logger "Launching KillChilds \"$child\" true" "DEBUG" #__WITH_PARANOIA_DEBUG
KillChilds "$child" true
done
fi
fi
# Try to kill nicely, if not, wait 15 seconds to let Trap actions happen before killing
if [ "$self" == true ]; then
# We need to check for pid again because it may have disappeared after recursive function call
if kill -0 "$pid" > /dev/null 2>&1; then
kill -s TERM "$pid"
Logger "Sent SIGTERM to process [$pid]." "DEBUG"
@@ -410,7 +429,6 @@ function SendAlert {
eval "cat \"$LOG_FILE\" $COMPRESSION_PROGRAM > $ALERT_LOG_FILE"
if [ $? != 0 ]; then
Logger "Cannot create [$ALERT_LOG_FILE]" "WARN"
attachment=false
else
attachment=true
@@ -657,6 +675,22 @@ function Spinner {
fi
}
function _PerfProfiler { #__WITH_PARANOIA_DEBUG
local perfString #__WITH_PARANOIA_DEBUG
#__WITH_PARANOIA_DEBUG
perfString=$(ps -p $$ -o args,pid,ppid,%cpu,%mem,time,etime,state,wchan) #__WITH_PARANOIA_DEBUG
#__WITH_PARANOIA_DEBUG
for i in $(pgrep -P $$); do #__WITH_PARANOIA_DEBUG
perfString="$perfString\n"$(ps -p $i -o args,pid,ppid,%cpu,%mem,time,etime,state,wchan | tail -1) #__WITH_PARANOIA_DEBUG
done #__WITH_PARANOIA_DEBUG
#__WITH_PARANOIA_DEBUG
if type iostat > /dev/null 2>&1; then #__WITH_PARANOIA_DEBUG
perfString="$perfString\n"$(iostat) #__WITH_PARANOIA_DEBUG
fi #__WITH_PARANOIA_DEBUG
#__WITH_PARANOIA_DEBUG
Logger "PerfProfiler:\n$perfString" "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG
} #__WITH_PARANOIA_DEBUG
# Time control function for background processes, suitable for multiple synchronous processes
# Fills a global variable called WAIT_FOR_TASK_COMPLETION_$callerName that contains list of failed pids in format pid1:result1;pid2:result2
@@ -789,6 +823,11 @@ function WaitForTaskCompletion {
pidsArray=("${newPidsArray[@]}")
# Trivial wait time for bash to not eat up all CPU
sleep $sleepTime
if [ "$_PERF_PROFILER" == "yes" ]; then ##__WITH_PARANOIA_DEBUG
_PerfProfiler ##__WITH_PARANOIA_DEBUG
fi ##__WITH_PARANOIA_DEBUG
done
Logger "${FUNCNAME[0]} ended for [$callerName] using [$pidCount] subprocesses with [$errorcount] errors." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG
@@ -954,6 +993,10 @@ function ParallelExec {
# Trivial wait time for bash to not eat up all CPU
sleep $sleepTime
if [ "$_PERF_PROFILER" == "yes" ]; then ##__WITH_PARANOIA_DEBUG
_PerfProfiler ##__WITH_PARANOIA_DEBUG
fi ##__WITH_PARANOIA_DEBUG
done
return $errorCount
@@ -1139,7 +1182,7 @@ function GetLocalOS {
*"BSD"*)
LOCAL_OS="BSD"
;;
*"MINGW32"*|*"MSYS"*)
*"MINGW32"*|*"MINGW64"*|*"MSYS"*)
LOCAL_OS="msys"
;;
*"CYGWIN"*)
@@ -1165,9 +1208,6 @@ function GetLocalOS {
exit 1
;;
esac
if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$localOsVar]." "DEBUG"
fi
# Get linux versions
if [ -f "/etc/os-release" ]; then
@@ -1177,8 +1217,68 @@ function GetLocalOS {
# Add a global variable for statistics in installer
LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer)"
if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$LOCAL_OS_FULL]." "DEBUG"
fi
}
#__BEGIN_WITH_PARANOIA_DEBUG
function __CheckArguments {
# Checks the number of arguments of a function and raises an error if some are missing
if [ "$_DEBUG" == "yes" ]; then
local numberOfArguments="${1}" # Number of arguments the tested function should have, can be a number of a range, eg 0-2 for zero to two arguments
local numberOfGivenArguments="${2}" # Number of arguments that have been passed
local minArgs
local maxArgs
# All arguments of the function to check are passed as array in ${3} (the function call waits for $@)
# If any of the arguments contains spaces, bash things there are two aguments
# In order to avoid this, we need to iterate over ${3} and count
callerName="${FUNCNAME[1]}"
local iterate=3
local fetchArguments=true
local argList=""
local countedArguments
while [ $fetchArguments == true ]; do
cmd='argument=${'$iterate'}'
eval $cmd
if [ "$argument" == "" ]; then
fetchArguments=false
else
argList="$argList[Argument $((iterate-2)): $argument] "
iterate=$((iterate+1))
fi
done
countedArguments=$((iterate-3))
if [ $(IsInteger "$numberOfArguments") -eq 1 ]; then
minArgs=$numberOfArguments
maxArgs=$numberOfArguments
else
IFS='-' read minArgs maxArgs <<< "$numberOfArguments"
fi
Logger "Entering function [$callerName]." "PARANOIA_DEBUG"
if ! ([ $countedArguments -ge $minArgs ] && [ $countedArguments -le $maxArgs ]); then
Logger "Function $callerName may have inconsistent number of arguments. Expected min: $minArgs, max: $maxArgs, count: $countedArguments, bash seen: $numberOfGivenArguments." "ERROR"
Logger "$callerName arguments: $argList" "ERROR"
else
if [ ! -z "$argList" ]; then
Logger "$callerName arguments: $argList" "PARANOIA_DEBUG"
fi
fi
fi
}
#__END_WITH_PARANOIA_DEBUG
function GetRemoteOS {
__CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG
@@ -1189,13 +1289,16 @@ function GetRemoteOS {
local remoteOsVar
$SSH_CMD env _REMOTE_TOKEN="$_REMOTE_TOKEN" bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1
$SSH_CMD env LC_ALL=C env _REMOTE_TOKEN="$_REMOTE_TOKEN" bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1
function GetOs {
local localOsVar
local localOsName
local localOsVer
local osInfo="/etc/os-release"
# There's no good way to tell if currently running in BusyBox shell. Using sluggish way.
if ls --help 2>&1 | grep -i "BusyBox" > /dev/null; then
localOsVar="BusyBox"
@@ -1214,9 +1317,11 @@ function GetOs {
fi
fi
# Get linux versions
if [ -f "/etc/os-release" ]; then
localOsName=$(GetConfFileValue "/etc/os-release" "NAME")
localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION")
if [ -f "$osInfo" ]; then
localOsName=$(grep "^NAME=" "$osInfo")
localOsName="${localOsName##*=}"
localOsVer=$(grep "^VERSION=" "$osInfo")
localOsVer="${localOsVer##*=}"
fi
echo "$localOsVar ($localOsName $localOsVer)"
@@ -1238,7 +1343,7 @@ ENDSSH
*"BSD"*)
REMOTE_OS="BSD"
;;
*"MINGW32"*|*"MSYS"*)
*"MINGW32"*|*"MINGW64"*|*"MSYS"*)
REMOTE_OS="msys"
;;
*"CYGWIN"*)
@@ -1323,7 +1428,7 @@ function RunRemoteCommand {
fi
Logger "Running command [$command] on remote host." "NOTICE"
cmd=$SSH_CMD' "env _REMOTE_TOKEN="'$_REMOTE_TOKEN'" $command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1'
cmd=$SSH_CMD' "env LC_ALL=C env _REMOTE_TOKEN="'$_REMOTE_TOKEN'" $command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1'
Logger "cmd: $cmd" "DEBUG"
eval "$cmd" &
WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false
@@ -1434,62 +1539,6 @@ function CheckConnectivity3rdPartyHosts {
fi #__WITH_PARANOIA_DEBUG
}
#__BEGIN_WITH_PARANOIA_DEBUG
function __CheckArguments {
# Checks the number of arguments of a function and raises an error if some are missing
if [ "$_DEBUG" == "yes" ]; then
local numberOfArguments="${1}" # Number of arguments the tested function should have, can be a number of a range, eg 0-2 for zero to two arguments
local numberOfGivenArguments="${2}" # Number of arguments that have been passed
local minArgs
local maxArgs
# All arguments of the function to check are passed as array in ${3} (the function call waits for $@)
# If any of the arguments contains spaces, bash things there are two aguments
# In order to avoid this, we need to iterate over ${3} and count
callerName="${FUNCNAME[1]}"
local iterate=3
local fetchArguments=true
local argList=""
local countedArguments
while [ $fetchArguments == true ]; do
cmd='argument=${'$iterate'}'
eval $cmd
if [ "$argument" == "" ]; then
fetchArguments=false
else
argList="$argList[Argument $((iterate-2)): $argument] "
iterate=$((iterate+1))
fi
done
countedArguments=$((iterate-3))
if [ $(IsInteger "$numberOfArguments") -eq 1 ]; then
minArgs=$numberOfArguments
maxArgs=$numberOfArguments
else
IFS='-' read minArgs maxArgs <<< "$numberOfArguments"
fi
Logger "Entering function [$callerName]." "PARANOIA_DEBUG"
if ! ([ $countedArguments -ge $minArgs ] && [ $countedArguments -le $maxArgs ]); then
Logger "Function $callerName may have inconsistent number of arguments. Expected min: $minArgs, max: $maxArgs, count: $countedArguments, bash seen: $numberOfGivenArguments." "ERROR"
Logger "$callerName arguments: $argList" "ERROR"
else
if [ ! -z "$argList" ]; then
Logger "$callerName arguments: $argList" "PARANOIA_DEBUG"
fi
fi
fi
}
#__END_WITH_PARANOIA_DEBUG
function RsyncPatternsAdd {
local patternType="${1}" # exclude or include
local pattern="${2}"
@@ -1620,13 +1669,13 @@ function PostInit {
# Define remote commands
if [ -f "$SSH_RSA_PRIVATE_KEY" ]; then
SSH_CMD="$(type -p ssh) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p scp) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p ssh) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS -p $REMOTE_PORT"
SSH_CMD="$(type -p ssh) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p scp) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p ssh) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS -p $REMOTE_PORT"
elif [ -f "$SSH_PASSWORD_FILE" ]; then
SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p scp) $SSH_COMP -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP $SSH_OPTS -p $REMOTE_PORT"
SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP -q $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p scp) $SSH_COMP -q -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP -q $SSH_OPTS -p $REMOTE_PORT"
else
SSH_PASSWORD=""
SSH_CMD=""
@@ -1664,23 +1713,22 @@ function SetCompression {
COMPRESSION_PROGRAM="| pigz -c$compressionString"
COMPRESSION_EXTENSION=.gz
# obackup specific
if [ "$LOCAL_OS" != "MacOSX" ]; then
COMPRESSION_OPTIONS=--rsyncable
fi
COMPRESSION_OPTIONS=--rsyncable
elif type gzip > /dev/null 2>&1
then
COMPRESSION_PROGRAM="| gzip -c$compressionString"
COMPRESSION_EXTENSION=.gz
# obackup specific
if [ "$LOCAL_OS" != "MacOSX" ]; then
COMPRESSION_OPTIONS=--rsyncable
fi
COMPRESSION_OPTIONS=--rsyncable
else
COMPRESSION_PROGRAM=
COMPRESSION_EXTENSION=
fi
fi
ALERT_LOG_FILE="$ALERT_LOG_FILE$COMPRESSION_EXTENSION"
if [ ".${ALERT_LOG_FILE##*.}" != "$COMPRESSION_EXTENSION" ]; then
ALERT_LOG_FILE="$ALERT_LOG_FILE$COMPRESSION_EXTENSION"
fi
}
function InitLocalOSDependingSettings {
@@ -1844,35 +1892,46 @@ function ParentPid {
# Neat version compare function found at http://stackoverflow.com/a/4025065/2635443
# Returns 0 if equal, 1 if $1 > $2 and 2 if $1 < $2
vercomp () {
if [[ $1 == $2 ]]
then
return 0
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
function VerComp () {
if [ "$1" == "" ] || [ "$2" == "" ]; then
Logger "Bogus Vercomp values [$1] and [$2]." "WARN"
return 1
fi
if [[ $1 == $2 ]]
then
echo 0
return
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
echo 1
return
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
echo 2
return
fi
done
echo 0
return
}
function GetConfFileValue () {
@@ -1905,6 +1964,29 @@ function SetConfFileValue () {
fi
}
# Function can replace [ -f /some/file* ] tests
# Modified version of http://stackoverflow.com/a/6364244/2635443
function WildcardFileExists () {
local file="${1}"
local exists=0
for f in $file; do
## Check if the glob gets expanded to existing files.
## If not, f here will be exactly the pattern above
## and the exists test will evaluate to false.
if [ -e "$f" ]; then
exists=1
break
fi
done
if [ $exists -eq 1 ]; then
echo 1
else
echo 0
fi
}
# If using "include" statements, make sure the script does not get executed unless it's loaded by bootstrap
_OFUNCTIONS_BOOTSTRAP=true
[ "$_OFUNCTIONS_BOOTSTRAP" != true ] && echo "Please use bootstrap.sh to load this dev version of $(basename $0)" && exit 1
@@ -4219,23 +4301,23 @@ function Init {
REMOTE_HOST=${hosturi%%:*}
fi
## Add update to default RSYNC_ARGS
RSYNC_ARGS=$RSYNC_ARGS" -u"
## Add update to default RSYNC_TYPE_ARGS
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" -u"
if [ $_LOGGER_VERBOSE == true ]; then
RSYNC_ARGS=$RSYNC_ARGS" -i"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" -i"
fi
if [ "$DELETE_VANISHED_FILES" == "yes" ]; then
RSYNC_ARGS=$RSYNC_ARGS" --delete"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --delete"
fi
if [ $stats == true ]; then
RSYNC_ARGS=$RSYNC_ARGS" --stats"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --stats"
fi
## Fix for symlink to directories on target cannot get updated
RSYNC_ARGS=$RSYNC_ARGS" --force"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --force"
}
function Main {
@@ -4324,12 +4406,16 @@ function Usage {
_DRYRUN=false
no_maxtime=false
stats=false
PARTIAL=no
partial_transfers=false
delete_vanished=false
dont_get_backup_size=false
_DECRYPT_MODE=false
DECRYPT_PATH=""
_ENCRYPT_MODE=false
function GetCommandlineArguments {
local isFirstArgument=true
if [ $# -eq 0 ]; then
Usage
fi
@@ -4349,16 +4435,16 @@ function GetCommandlineArguments {
stats=false
;;
--partial)
PARTIAL="yes"
partial_transfers=true
;;
--no-maxtime)
no_maxtime=true
;;
--delete)
DELETE_VANISHED_FILES="yes"
delete_vanished=true
;;
--dontgetsize)
GET_BACKUP_SIZE="no"
dont_get_backup_size=true
;;
--help|-h|--version|-v)
Usage
@@ -4394,7 +4480,15 @@ function GetCommandlineArguments {
if [ $(IsNumeric $PARALLEL_ENCRYPTION_PROCESSES) -ne 1 ]; then
Logger "Bogus --parallel value. Using only one CPU." "WARN"
fi
;;
*)
if [ $isFirstArgument == false ]; then
Logger "Unknown option '$i'" "CRITICAL"
Usage
fi
;;
esac
isFirstArgument=false
done
}
@@ -4436,6 +4530,27 @@ else
Logger "Script begin, logging to [$LOG_FILE]." "DEBUG"
fi
if [ $no_maxtime == true ]; then
SOFT_MAX_EXEC_TIME_DB_TASK=0
SOFT_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_DB_TASK=0
HARD_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_TOTAL=0
fi
if [ $partial_transfers == true ]; then
PARTIAL="yes"
fi
if [ $delete_vanished == true ]; then
DELETE_VANISHED_FILES="yes"
fi
if [ $dont_get_backup_size == true ]; then
GET_BACKUP_SIZE="no"
fi
if [ "$IS_STABLE" != "yes" ]; then
Logger "This is an unstable dev build [$PROGRAM_BUILD]. Please use with caution." "WARN"
fi
@@ -4456,13 +4571,5 @@ PostInit
CheckCurrentConfig
GetRemoteOS
InitRemoteOSDependingSettings
if [ $no_maxtime == true ]; then
SOFT_MAX_EXEC_TIME_DB_TASK=0
SOFT_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_DB_TASK=0
HARD_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_TOTAL=0
fi
RunBeforeHook
Main

View File

@@ -1,12 +1,18 @@
#!/usr/bin/env bash
## MERGE 2017031301
## MERGE 2017061901
## Merges ofunctions.sh and n_program.sh into program.sh
## Adds installer
function Usage {
echo "Merges ofunctions.sh and n_program.sh into debug_program.sh and ../program.sh"
echo "Usage"
echo "$0 osync|obackup|pmocr"
}
function __PREPROCESSOR_Merge {
PROGRAM=obackup
local PROGRAM="$1"
VERSION=$(grep "PROGRAM_VERSION=" n_$PROGRAM.sh)
VERSION=${VERSION#*=}
@@ -24,8 +30,7 @@ function __PREPROCESSOR_Merge {
__PREPROCESSOR_MergeSubset "$subset" "${subset//SUBSET/SUBSET END}" "ofunctions.sh" "debug_$PROGRAM.sh"
done
__PREPROCESSOR_CleanDebug
__PREPROCESSOR_CopyCommons
__PREPROCESSOR_CleanDebug "$PROGRAM"
rm -f tmp_$PROGRAM.sh
if [ $? != 0 ]; then
QuickLogger "Cannot remove tmp_$PROGRAM.sh"
@@ -51,6 +56,7 @@ function __PREPROCESSOR_Constants {
'#### UrlEncode SUBSET ####'
'#### HumanToNumeric SUBSET ####'
'#### ArrayContains SUBSET ####'
'#### VerComp SUBSET ####'
'#### GetConfFileValue SUBSET ####'
'#### SetConfFileValue SUBSET ####'
)
@@ -103,6 +109,8 @@ function __PREPROCESSOR_MergeSubset {
}
function __PREPROCESSOR_CleanDebug {
local PROGRAM="$1"
sed '/'$PARANOIA_DEBUG_BEGIN'/,/'$PARANOIA_DEBUG_END'/d' debug_$PROGRAM.sh | grep -v "$PARANOIA_DEBUG_LINE" > ../$PROGRAM.sh
if [ $? != 0 ]; then
QuickLogger "Cannot remove PARANOIA_DEBUG code from standard build."
@@ -126,6 +134,8 @@ function __PREPROCESSOR_CleanDebug {
}
function __PREPROCESSOR_CopyCommons {
local PROGRAM="$1"
sed "s/\[prgname\]/$PROGRAM/g" common_install.sh > ../install.sh
if [ $? != 0 ]; then
QuickLogger "Cannot assemble install."
@@ -171,5 +181,19 @@ function __PREPROCESSOR_CopyCommons {
# If sourced don't do anything
if [ "$(basename $0)" == "merge.sh" ]; then
__PREPROCESSOR_Merge
if [ "$1" == "osync" ]; then
__PREPROCESSOR_Merge osync
__PREPROCESSOR_Merge osync_target_helper
__PREPROCESSOR_CopyCommons osync
elif [ "$1" == "obackup" ]; then
__PREPROCESSOR_Merge obackup
__PREPROCESSOR_CopyCommons obackup
elif [ "$1" == "pmocr" ]; then
__PREPROCESSOR_Merge pmocr
__PREPROCESSOR_CopyCommons pmocr
else
echo "No valid program given."
exit 1
fi
fi

View File

@@ -6,8 +6,8 @@
PROGRAM="obackup"
AUTHOR="(C) 2013-2017 by Orsiris de Jong"
CONTACT="http://www.netpower.fr/obackup - ozy@netpower.fr"
PROGRAM_VERSION=2.1-beta2
PROGRAM_BUILD=2017021001
PROGRAM_VERSION=2.1-beta3
PROGRAM_BUILD=2017062004
IS_STABLE=no
#### Execution order #__WITH_PARANOIA_DEBUG
@@ -1784,23 +1784,23 @@ function Init {
REMOTE_HOST=${hosturi%%:*}
fi
## Add update to default RSYNC_ARGS
RSYNC_ARGS=$RSYNC_ARGS" -u"
## Add update to default RSYNC_TYPE_ARGS
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" -u"
if [ $_LOGGER_VERBOSE == true ]; then
RSYNC_ARGS=$RSYNC_ARGS" -i"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" -i"
fi
if [ "$DELETE_VANISHED_FILES" == "yes" ]; then
RSYNC_ARGS=$RSYNC_ARGS" --delete"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --delete"
fi
if [ $stats == true ]; then
RSYNC_ARGS=$RSYNC_ARGS" --stats"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --stats"
fi
## Fix for symlink to directories on target cannot get updated
RSYNC_ARGS=$RSYNC_ARGS" --force"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --force"
}
function Main {
@@ -1889,12 +1889,16 @@ function Usage {
_DRYRUN=false
no_maxtime=false
stats=false
PARTIAL=no
partial_transfers=false
delete_vanished=false
dont_get_backup_size=false
_DECRYPT_MODE=false
DECRYPT_PATH=""
_ENCRYPT_MODE=false
function GetCommandlineArguments {
local isFirstArgument=true
if [ $# -eq 0 ]; then
Usage
fi
@@ -1914,16 +1918,16 @@ function GetCommandlineArguments {
stats=false
;;
--partial)
PARTIAL="yes"
partial_transfers=true
;;
--no-maxtime)
no_maxtime=true
;;
--delete)
DELETE_VANISHED_FILES="yes"
delete_vanished=true
;;
--dontgetsize)
GET_BACKUP_SIZE="no"
dont_get_backup_size=true
;;
--help|-h|--version|-v)
Usage
@@ -1959,7 +1963,15 @@ function GetCommandlineArguments {
if [ $(IsNumeric $PARALLEL_ENCRYPTION_PROCESSES) -ne 1 ]; then
Logger "Bogus --parallel value. Using only one CPU." "WARN"
fi
;;
*)
if [ $isFirstArgument == false ]; then
Logger "Unknown option '$i'" "CRITICAL"
Usage
fi
;;
esac
isFirstArgument=false
done
}
@@ -2001,6 +2013,27 @@ else
Logger "Script begin, logging to [$LOG_FILE]." "DEBUG"
fi
if [ $no_maxtime == true ]; then
SOFT_MAX_EXEC_TIME_DB_TASK=0
SOFT_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_DB_TASK=0
HARD_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_TOTAL=0
fi
if [ $partial_transfers == true ]; then
PARTIAL="yes"
fi
if [ $delete_vanished == true ]; then
DELETE_VANISHED_FILES="yes"
fi
if [ $dont_get_backup_size == true ]; then
GET_BACKUP_SIZE="no"
fi
if [ "$IS_STABLE" != "yes" ]; then
Logger "This is an unstable dev build [$PROGRAM_BUILD]. Please use with caution." "WARN"
fi
@@ -2021,13 +2054,5 @@ PostInit
CheckCurrentConfig
GetRemoteOS
InitRemoteOSDependingSettings
if [ $no_maxtime == true ]; then
SOFT_MAX_EXEC_TIME_DB_TASK=0
SOFT_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_DB_TASK=0
HARD_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_TOTAL=0
fi
RunBeforeHook
Main

View File

@@ -2,8 +2,8 @@
#### OFUNCTIONS FULL SUBSET ####
#### OFUNCTIONS MINI SUBSET ####
_OFUNCTIONS_VERSION=2.1-RC3+dev
_OFUNCTIONS_BUILD=2017031401
_OFUNCTIONS_VERSION=2.1.4-rc1
_OFUNCTIONS_BUILD=2017060903
#### _OFUNCTIONS_BOOTSTRAP SUBSET ####
_OFUNCTIONS_BOOTSTRAP=true
#### _OFUNCTIONS_BOOTSTRAP SUBSET END ####
@@ -30,6 +30,9 @@ fi
## Correct output of sort command (language agnostic sorting)
export LC_ALL=C
## Default umask for file creation
umask 0077
# Standard alert mail body
MAIL_ALERT_MSG="Execution of $PROGRAM instance $INSTANCE_ID on $(date) has warnings/errors."
@@ -68,6 +71,8 @@ fi
#### DEBUG SUBSET END ####
SCRIPT_PID=$$
# TODO: Check if %N works on MacOS
TSTAMP=$(date '+%Y%m%dT%H%M%S.%N')
LOCAL_USER=$(whoami)
@@ -261,7 +266,7 @@ function Logger {
return
elif [ "$level" == "VERBOSE" ]; then
if [ $_LOGGER_VERBOSE == true ]; then
_Logger "$prefix:$value" "$prefix$value"
_Logger "$prefix($level):$value" "$prefix$value"
fi
return
elif [ "$level" == "ALWAYS" ]; then
@@ -314,15 +319,29 @@ function KillChilds {
local pid="${1}" # Parent pid to kill childs
local self="${2:-false}" # Should parent be killed too ?
# Warning: pgrep does not exist in cygwin, have this checked in CheckEnvironment
if children="$(pgrep -P "$pid")"; then
for child in $children; do
Logger "Launching KillChilds \"$child\" true" "DEBUG" #__WITH_PARANOIA_DEBUG
KillChilds "$child" true
done
# Paranoid checks, we can safely assume that $pid shouldn't be 0 nor 1
if [ $(IsNumeric "$pid") -eq 0 ] || [ "$pid" == "" ] || [ "$pid" == "0" ] || [ "$pid" == "1" ]; then
Logger "Bogus pid given [$pid]." "CRITICAL"
return 1
fi
# Try to kill nicely, if not, wait 15 seconds to let Trap actions happen before killing
if kill -0 "$pid" > /dev/null 2>&1; then
# Warning: pgrep is not native on cygwin, have this checked in CheckEnvironment
if children="$(pgrep -P "$pid")"; then
if [[ "$pid" == *"$children"* ]]; then
Logger "Bogus pgrep implementation." "CRITICAL"
children="${children/$pid/}"
fi
for child in $children; do
Logger "Launching KillChilds \"$child\" true" "DEBUG" #__WITH_PARANOIA_DEBUG
KillChilds "$child" true
done
fi
fi
# Try to kill nicely, if not, wait 15 seconds to let Trap actions happen before killing
if [ "$self" == true ]; then
# We need to check for pid again because it may have disappeared after recursive function call
if kill -0 "$pid" > /dev/null 2>&1; then
kill -s TERM "$pid"
Logger "Sent SIGTERM to process [$pid]." "DEBUG"
@@ -385,7 +404,6 @@ function SendAlert {
eval "cat \"$LOG_FILE\" $COMPRESSION_PROGRAM > $ALERT_LOG_FILE"
if [ $? != 0 ]; then
Logger "Cannot create [$ALERT_LOG_FILE]" "WARN"
attachment=false
else
attachment=true
@@ -634,6 +652,22 @@ function Spinner {
fi
}
function _PerfProfiler { #__WITH_PARANOIA_DEBUG
local perfString #__WITH_PARANOIA_DEBUG
#__WITH_PARANOIA_DEBUG
perfString=$(ps -p $$ -o args,pid,ppid,%cpu,%mem,time,etime,state,wchan) #__WITH_PARANOIA_DEBUG
#__WITH_PARANOIA_DEBUG
for i in $(pgrep -P $$); do #__WITH_PARANOIA_DEBUG
perfString="$perfString\n"$(ps -p $i -o args,pid,ppid,%cpu,%mem,time,etime,state,wchan | tail -1) #__WITH_PARANOIA_DEBUG
done #__WITH_PARANOIA_DEBUG
#__WITH_PARANOIA_DEBUG
if type iostat > /dev/null 2>&1; then #__WITH_PARANOIA_DEBUG
perfString="$perfString\n"$(iostat) #__WITH_PARANOIA_DEBUG
fi #__WITH_PARANOIA_DEBUG
#__WITH_PARANOIA_DEBUG
Logger "PerfProfiler:\n$perfString" "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG
} #__WITH_PARANOIA_DEBUG
# Time control function for background processes, suitable for multiple synchronous processes
# Fills a global variable called WAIT_FOR_TASK_COMPLETION_$callerName that contains list of failed pids in format pid1:result1;pid2:result2
@@ -766,6 +800,11 @@ function WaitForTaskCompletion {
pidsArray=("${newPidsArray[@]}")
# Trivial wait time for bash to not eat up all CPU
sleep $sleepTime
if [ "$_PERF_PROFILER" == "yes" ]; then ##__WITH_PARANOIA_DEBUG
_PerfProfiler ##__WITH_PARANOIA_DEBUG
fi ##__WITH_PARANOIA_DEBUG
done
Logger "${FUNCNAME[0]} ended for [$callerName] using [$pidCount] subprocesses with [$errorcount] errors." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG
@@ -931,6 +970,10 @@ function ParallelExec {
# Trivial wait time for bash to not eat up all CPU
sleep $sleepTime
if [ "$_PERF_PROFILER" == "yes" ]; then ##__WITH_PARANOIA_DEBUG
_PerfProfiler ##__WITH_PARANOIA_DEBUG
fi ##__WITH_PARANOIA_DEBUG
done
return $errorCount
@@ -1125,7 +1168,7 @@ function GetLocalOS {
*"BSD"*)
LOCAL_OS="BSD"
;;
*"MINGW32"*|*"MSYS"*)
*"MINGW32"*|*"MINGW64"*|*"MSYS"*)
LOCAL_OS="msys"
;;
*"CYGWIN"*)
@@ -1151,9 +1194,6 @@ function GetLocalOS {
exit 1
;;
esac
if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$localOsVar]." "DEBUG"
fi
# Get linux versions
if [ -f "/etc/os-release" ]; then
@@ -1163,9 +1203,69 @@ function GetLocalOS {
# Add a global variable for statistics in installer
LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer)"
if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$LOCAL_OS_FULL]." "DEBUG"
fi
}
#### GetLocalOS SUBSET END ####
#__BEGIN_WITH_PARANOIA_DEBUG
function __CheckArguments {
# Checks the number of arguments of a function and raises an error if some are missing
if [ "$_DEBUG" == "yes" ]; then
local numberOfArguments="${1}" # Number of arguments the tested function should have, can be a number of a range, eg 0-2 for zero to two arguments
local numberOfGivenArguments="${2}" # Number of arguments that have been passed
local minArgs
local maxArgs
# All arguments of the function to check are passed as array in ${3} (the function call waits for $@)
# If any of the arguments contains spaces, bash things there are two aguments
# In order to avoid this, we need to iterate over ${3} and count
callerName="${FUNCNAME[1]}"
local iterate=3
local fetchArguments=true
local argList=""
local countedArguments
while [ $fetchArguments == true ]; do
cmd='argument=${'$iterate'}'
eval $cmd
if [ "$argument" == "" ]; then
fetchArguments=false
else
argList="$argList[Argument $((iterate-2)): $argument] "
iterate=$((iterate+1))
fi
done
countedArguments=$((iterate-3))
if [ $(IsInteger "$numberOfArguments") -eq 1 ]; then
minArgs=$numberOfArguments
maxArgs=$numberOfArguments
else
IFS='-' read minArgs maxArgs <<< "$numberOfArguments"
fi
Logger "Entering function [$callerName]." "PARANOIA_DEBUG"
if ! ([ $countedArguments -ge $minArgs ] && [ $countedArguments -le $maxArgs ]); then
Logger "Function $callerName may have inconsistent number of arguments. Expected min: $minArgs, max: $maxArgs, count: $countedArguments, bash seen: $numberOfGivenArguments." "ERROR"
Logger "$callerName arguments: $argList" "ERROR"
else
if [ ! -z "$argList" ]; then
Logger "$callerName arguments: $argList" "PARANOIA_DEBUG"
fi
fi
fi
}
#__END_WITH_PARANOIA_DEBUG
#### OFUNCTIONS MINI SUBSET END ####
function GetRemoteOS {
@@ -1177,13 +1277,16 @@ function GetRemoteOS {
local remoteOsVar
$SSH_CMD env _REMOTE_TOKEN="$_REMOTE_TOKEN" bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1
$SSH_CMD env LC_ALL=C env _REMOTE_TOKEN="$_REMOTE_TOKEN" bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1
function GetOs {
local localOsVar
local localOsName
local localOsVer
local osInfo="/etc/os-release"
# There's no good way to tell if currently running in BusyBox shell. Using sluggish way.
if ls --help 2>&1 | grep -i "BusyBox" > /dev/null; then
localOsVar="BusyBox"
@@ -1202,9 +1305,11 @@ function GetOs {
fi
fi
# Get linux versions
if [ -f "/etc/os-release" ]; then
localOsName=$(GetConfFileValue "/etc/os-release" "NAME")
localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION")
if [ -f "$osInfo" ]; then
localOsName=$(grep "^NAME=" "$osInfo")
localOsName="${localOsName##*=}"
localOsVer=$(grep "^VERSION=" "$osInfo")
localOsVer="${localOsVer##*=}"
fi
echo "$localOsVar ($localOsName $localOsVer)"
@@ -1226,7 +1331,7 @@ ENDSSH
*"BSD"*)
REMOTE_OS="BSD"
;;
*"MINGW32"*|*"MSYS"*)
*"MINGW32"*|*"MINGW64"*|*"MSYS"*)
REMOTE_OS="msys"
;;
*"CYGWIN"*)
@@ -1311,7 +1416,7 @@ function RunRemoteCommand {
fi
Logger "Running command [$command] on remote host." "NOTICE"
cmd=$SSH_CMD' "env _REMOTE_TOKEN="'$_REMOTE_TOKEN'" $command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1'
cmd=$SSH_CMD' "env LC_ALL=C env _REMOTE_TOKEN="'$_REMOTE_TOKEN'" $command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1'
Logger "cmd: $cmd" "DEBUG"
eval "$cmd" &
WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false
@@ -1422,62 +1527,6 @@ function CheckConnectivity3rdPartyHosts {
fi #__WITH_PARANOIA_DEBUG
}
#__BEGIN_WITH_PARANOIA_DEBUG
function __CheckArguments {
# Checks the number of arguments of a function and raises an error if some are missing
if [ "$_DEBUG" == "yes" ]; then
local numberOfArguments="${1}" # Number of arguments the tested function should have, can be a number of a range, eg 0-2 for zero to two arguments
local numberOfGivenArguments="${2}" # Number of arguments that have been passed
local minArgs
local maxArgs
# All arguments of the function to check are passed as array in ${3} (the function call waits for $@)
# If any of the arguments contains spaces, bash things there are two aguments
# In order to avoid this, we need to iterate over ${3} and count
callerName="${FUNCNAME[1]}"
local iterate=3
local fetchArguments=true
local argList=""
local countedArguments
while [ $fetchArguments == true ]; do
cmd='argument=${'$iterate'}'
eval $cmd
if [ "$argument" == "" ]; then
fetchArguments=false
else
argList="$argList[Argument $((iterate-2)): $argument] "
iterate=$((iterate+1))
fi
done
countedArguments=$((iterate-3))
if [ $(IsInteger "$numberOfArguments") -eq 1 ]; then
minArgs=$numberOfArguments
maxArgs=$numberOfArguments
else
IFS='-' read minArgs maxArgs <<< "$numberOfArguments"
fi
Logger "Entering function [$callerName]." "PARANOIA_DEBUG"
if ! ([ $countedArguments -ge $minArgs ] && [ $countedArguments -le $maxArgs ]); then
Logger "Function $callerName may have inconsistent number of arguments. Expected min: $minArgs, max: $maxArgs, count: $countedArguments, bash seen: $numberOfGivenArguments." "ERROR"
Logger "$callerName arguments: $argList" "ERROR"
else
if [ ! -z "$argList" ]; then
Logger "$callerName arguments: $argList" "PARANOIA_DEBUG"
fi
fi
fi
}
#__END_WITH_PARANOIA_DEBUG
function RsyncPatternsAdd {
local patternType="${1}" # exclude or include
local pattern="${2}"
@@ -1608,13 +1657,13 @@ function PostInit {
# Define remote commands
if [ -f "$SSH_RSA_PRIVATE_KEY" ]; then
SSH_CMD="$(type -p ssh) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p scp) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p ssh) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS -p $REMOTE_PORT"
SSH_CMD="$(type -p ssh) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p scp) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p ssh) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS -p $REMOTE_PORT"
elif [ -f "$SSH_PASSWORD_FILE" ]; then
SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p scp) $SSH_COMP -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP $SSH_OPTS -p $REMOTE_PORT"
SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP -q $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p scp) $SSH_COMP -q -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP -q $SSH_OPTS -p $REMOTE_PORT"
else
SSH_PASSWORD=""
SSH_CMD=""
@@ -1652,23 +1701,22 @@ function SetCompression {
COMPRESSION_PROGRAM="| pigz -c$compressionString"
COMPRESSION_EXTENSION=.gz
# obackup specific
if [ "$LOCAL_OS" != "MacOSX" ]; then
COMPRESSION_OPTIONS=--rsyncable
fi
COMPRESSION_OPTIONS=--rsyncable
elif type gzip > /dev/null 2>&1
then
COMPRESSION_PROGRAM="| gzip -c$compressionString"
COMPRESSION_EXTENSION=.gz
# obackup specific
if [ "$LOCAL_OS" != "MacOSX" ]; then
COMPRESSION_OPTIONS=--rsyncable
fi
COMPRESSION_OPTIONS=--rsyncable
else
COMPRESSION_PROGRAM=
COMPRESSION_EXTENSION=
fi
fi
ALERT_LOG_FILE="$ALERT_LOG_FILE$COMPRESSION_EXTENSION"
if [ ".${ALERT_LOG_FILE##*.}" != "$COMPRESSION_EXTENSION" ]; then
ALERT_LOG_FILE="$ALERT_LOG_FILE$COMPRESSION_EXTENSION"
fi
}
function InitLocalOSDependingSettings {
@@ -1830,38 +1878,51 @@ function ParentPid {
fi
}
#### VerComp SUBSET ####
# Neat version compare function found at http://stackoverflow.com/a/4025065/2635443
# Returns 0 if equal, 1 if $1 > $2 and 2 if $1 < $2
vercomp () {
if [[ $1 == $2 ]]
then
return 0
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
function VerComp () {
if [ "$1" == "" ] || [ "$2" == "" ]; then
Logger "Bogus Vercomp values [$1] and [$2]." "WARN"
return 1
fi
if [[ $1 == $2 ]]
then
echo 0
return
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
echo 1
return
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
echo 2
return
fi
done
echo 0
return
}
#### VerComp SUBSET END ####
#### GetConfFileValue SUBSET ####
function GetConfFileValue () {
@@ -1897,4 +1958,27 @@ function SetConfFileValue () {
}
#### SetConfFileValue SUBSET END ####
# Function can replace [ -f /some/file* ] tests
# Modified version of http://stackoverflow.com/a/6364244/2635443
function WildcardFileExists () {
local file="${1}"
local exists=0
for f in $file; do
## Check if the glob gets expanded to existing files.
## If not, f here will be exactly the pattern above
## and the exists test will evaluate to false.
if [ -e "$f" ]; then
exists=1
break
fi
done
if [ $exists -eq 1 ]; then
echo 1
else
echo 0
fi
}
#### OFUNCTIONS FULL SUBSET END ####

View File

@@ -2,7 +2,7 @@
#TODO Encrypted Pull runs on F25 fail for decryption
## obackup basic tests suite 2017020903
## obackup basic tests suite 2017040801
OBACKUP_DIR="$(pwd)"
OBACKUP_DIR=${OBACKUP_DIR%%/dev*}
@@ -153,6 +153,10 @@ function oneTimeSetUp () {
START_TIME=$SECONDS
source "$DEV_DIR/ofunctions.sh"
# Set default umask because ofunctions set 0077
umask 0022
GetLocalOS
echo "Detected OS: $LOCAL_OS"
@@ -293,7 +297,7 @@ function setUp () {
function test_Merge () {
cd "$DEV_DIR"
./merge.sh
./merge.sh obackup
assertEquals "Merging code" "0" $?
cd "$OBACKUP_DIR"

View File

@@ -12,7 +12,7 @@ PROGRAM_BINARY=$PROGRAM".sh"
PROGRAM_BATCH=$PROGRAM"-batch.sh"
SSH_FILTER="ssh_filter.sh"
SCRIPT_BUILD=2017031402
SCRIPT_BUILD=2017041701
## osync / obackup / pmocr / zsnap install script
## Tested on RHEL / CentOS 6 & 7, Fedora 23, Debian 7 & 8, Mint 17 and FreeBSD 8, 10 and 11
@@ -122,7 +122,7 @@ function GetLocalOS {
*"BSD"*)
LOCAL_OS="BSD"
;;
*"MINGW32"*|*"MSYS"*)
*"MINGW32"*|*"MINGW64"*|*"MSYS"*)
LOCAL_OS="msys"
;;
*"CYGWIN"*)
@@ -148,9 +148,6 @@ function GetLocalOS {
exit 1
;;
esac
if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$localOsVar]." "DEBUG"
fi
# Get linux versions
if [ -f "/etc/os-release" ]; then
@@ -160,6 +157,10 @@ function GetLocalOS {
# Add a global variable for statistics in installer
LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer)"
if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$LOCAL_OS_FULL]." "DEBUG"
fi
}
function GetConfFileValue () {
local file="${1}"
@@ -331,7 +332,9 @@ function CopyProgram {
function CopyServiceFiles {
if ([ "$init" == "systemd" ] && [ -f "$SCRIPT_PATH/$SERVICE_FILE_SYSTEMD_SYSTEM" ]); then
CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_SYSTEMD_SYSTEM" "$SERVICE_FILE_SYSTEMD_SYSTEM" "" "" "" true
CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_SYSTEMD_USER" "$SERVICE_FILE_SYSTEMD_USER" "" "" "" true
if [ -f "$SCRIPT_PATH/$SERVICE_FILE_SYSTEMD_SYSTEM_USER" ]; then
CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_SYSTEMD_USER" "$SERVICE_FILE_SYSTEMD_USER" "" "" "" true
fi
QuickLogger "Created [$SERVICE_NAME] service in [$SERVICE_DIR_SYSTEMD_SYSTEM] and [$SERVICE_DIR_SYSTEMD_USER]."
QuickLogger "Can be activated with [systemctl start SERVICE_NAME@instance.conf] where instance.conf is the name of the config file in $CONF_DIR."
@@ -340,9 +343,9 @@ function CopyServiceFiles {
elif ([ "$init" == "initV" ] && [ -f "$SCRIPT_PATH/$SERVICE_FILE_INIT" ] && [ -d "$SERVICE_DIR_INIT" ]); then
CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_INIT" "$SERVICE_FILE_INIT" "755" "" "" true
QuickLogger "Created osync-srv service in [$SERVICE_DIR_INIT]."
QuickLogger "Can be activated with [service $OSYNC_SERVICE_FILE_INIT start]."
QuickLogger "Can be enabled on boot with [chkconfig $OSYNC_SERVICE_FILE_INIT on]."
QuickLogger "Created [$SERVICE_NAME] service in [$SERVICE_DIR_INIT]."
QuickLogger "Can be activated with [service $SERVICE_FILE_INIT start]."
QuickLogger "Can be enabled on boot with [chkconfig $SERVICE_FILE_INIT on]."
else
QuickLogger "Cannot define what init style is in use on this system. Skipping service file installation."
fi
@@ -384,7 +387,11 @@ function RemoveFile {
function RemoveAll {
RemoveFile "$BIN_DIR/$PROGRAM_BINARY"
RemoveFile "$BIN_DIR/$PROGRAM_BATCH"
if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then
RemoveFile "$BIN_DIR/$PROGRAM_BATCH"
fi
if [ ! -f "$BIN_DIR/osync.sh" ] && [ ! -f "$BIN_DIR/obackup.sh" ]; then # Check if any other program requiring ssh filter is present before removal
RemoveFile "$BIN_DIR/$SSH_FILTER"
else
@@ -402,6 +409,7 @@ function Usage {
echo "options:"
echo "--silent Will log and bypass user interaction."
echo "--no-stats Used with --silent in order to refuse sending anonymous install stats."
echo "--remove Remove the program."
exit 127
}
@@ -444,7 +452,9 @@ else
CreateDir "$BIN_DIR"
CopyExampleFiles
CopyProgram
CopyServiceFiles
if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "pmocr" ]; then
CopyServiceFiles
fi
QuickLogger "$PROGRAM installed. Use with $BIN_DIR/$PROGRAM"
if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then
QuickLogger ""

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
SUBPROGRAM=obackup
PROGRAM="$SUBPROGRAM-batch" # Batch program to run osync / obackup instances sequentially and rerun failed ones
AUTHOR="(L) 2013-2016 by Orsiris de Jong"
AUTHOR="(L) 2013-2017 by Orsiris de Jong"
CONTACT="http://www.netpower.fr - ozy@netpower.fr"
PROGRAM_BUILD=2016120401
@@ -119,15 +119,15 @@ function Batch {
fi
done
runList=("${runAgainList[@]}")
runs=$(($runs + 1))
runs=$((runs + 1))
done
fi
}
function Usage {
echo "$PROGRAM $PROGRAM_BUILD"
echo $AUTHOR
echo $CONTACT
echo "$AUTHOR"
echo "$CONTACT"
echo ""
echo "Batch script to sequentially run osync or obackup instances and rerun failed ones."
echo "Usage: $PROGRAM.sh [OPTIONS] [$SUBPROGRAM OPTIONS]"

View File

@@ -6,14 +6,14 @@
PROGRAM="obackup"
AUTHOR="(C) 2013-2017 by Orsiris de Jong"
CONTACT="http://www.netpower.fr/obackup - ozy@netpower.fr"
PROGRAM_VERSION=2.1-beta2
PROGRAM_BUILD=2017021001
PROGRAM_VERSION=2.1-beta3
PROGRAM_BUILD=2017062004
IS_STABLE=no
_OFUNCTIONS_VERSION=2.1-RC3+dev
_OFUNCTIONS_BUILD=2017031401
_OFUNCTIONS_VERSION=2.1.4-rc1
_OFUNCTIONS_BUILD=2017060903
_OFUNCTIONS_BOOTSTRAP=true
## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
@@ -38,6 +38,9 @@ fi
## Correct output of sort command (language agnostic sorting)
export LC_ALL=C
## Default umask for file creation
umask 0077
# Standard alert mail body
MAIL_ALERT_MSG="Execution of $PROGRAM instance $INSTANCE_ID on $(date) has warnings/errors."
@@ -70,6 +73,8 @@ if [ "$SLEEP_TIME" == "" ]; then # Leave the possibity to set SLEEP_TIME as envi
fi
SCRIPT_PID=$$
# TODO: Check if %N works on MacOS
TSTAMP=$(date '+%Y%m%dT%H%M%S.%N')
LOCAL_USER=$(whoami)
@@ -255,7 +260,7 @@ function Logger {
return
elif [ "$level" == "VERBOSE" ]; then
if [ $_LOGGER_VERBOSE == true ]; then
_Logger "$prefix:$value" "$prefix$value"
_Logger "$prefix($level):$value" "$prefix$value"
fi
return
elif [ "$level" == "ALWAYS" ]; then
@@ -301,14 +306,28 @@ function KillChilds {
local pid="${1}" # Parent pid to kill childs
local self="${2:-false}" # Should parent be killed too ?
# Warning: pgrep does not exist in cygwin, have this checked in CheckEnvironment
if children="$(pgrep -P "$pid")"; then
for child in $children; do
KillChilds "$child" true
done
# Paranoid checks, we can safely assume that $pid shouldn't be 0 nor 1
if [ $(IsNumeric "$pid") -eq 0 ] || [ "$pid" == "" ] || [ "$pid" == "0" ] || [ "$pid" == "1" ]; then
Logger "Bogus pid given [$pid]." "CRITICAL"
return 1
fi
# Try to kill nicely, if not, wait 15 seconds to let Trap actions happen before killing
if kill -0 "$pid" > /dev/null 2>&1; then
# Warning: pgrep is not native on cygwin, have this checked in CheckEnvironment
if children="$(pgrep -P "$pid")"; then
if [[ "$pid" == *"$children"* ]]; then
Logger "Bogus pgrep implementation." "CRITICAL"
children="${children/$pid/}"
fi
for child in $children; do
KillChilds "$child" true
done
fi
fi
# Try to kill nicely, if not, wait 15 seconds to let Trap actions happen before killing
if [ "$self" == true ]; then
# We need to check for pid again because it may have disappeared after recursive function call
if kill -0 "$pid" > /dev/null 2>&1; then
kill -s TERM "$pid"
Logger "Sent SIGTERM to process [$pid]." "DEBUG"
@@ -369,7 +388,6 @@ function SendAlert {
eval "cat \"$LOG_FILE\" $COMPRESSION_PROGRAM > $ALERT_LOG_FILE"
if [ $? != 0 ]; then
Logger "Cannot create [$ALERT_LOG_FILE]" "WARN"
attachment=false
else
attachment=true
@@ -615,6 +633,7 @@ function Spinner {
}
# Time control function for background processes, suitable for multiple synchronous processes
# Fills a global variable called WAIT_FOR_TASK_COMPLETION_$callerName that contains list of failed pids in format pid1:result1;pid2:result2
# Also sets a global variable called HARD_MAX_EXEC_TIME_REACHED_$callerName to true if hardMaxTime is reached
@@ -739,6 +758,8 @@ function WaitForTaskCompletion {
pidsArray=("${newPidsArray[@]}")
# Trivial wait time for bash to not eat up all CPU
sleep $sleepTime
done
@@ -897,6 +918,7 @@ function ParallelExec {
# Trivial wait time for bash to not eat up all CPU
sleep $sleepTime
done
return $errorCount
@@ -1081,7 +1103,7 @@ function GetLocalOS {
*"BSD"*)
LOCAL_OS="BSD"
;;
*"MINGW32"*|*"MSYS"*)
*"MINGW32"*|*"MINGW64"*|*"MSYS"*)
LOCAL_OS="msys"
;;
*"CYGWIN"*)
@@ -1107,9 +1129,6 @@ function GetLocalOS {
exit 1
;;
esac
if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$localOsVar]." "DEBUG"
fi
# Get linux versions
if [ -f "/etc/os-release" ]; then
@@ -1119,9 +1138,14 @@ function GetLocalOS {
# Add a global variable for statistics in installer
LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer)"
if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$LOCAL_OS_FULL]." "DEBUG"
fi
}
function GetRemoteOS {
if [ "$REMOTE_OPERATION" != "yes" ]; then
@@ -1130,13 +1154,16 @@ function GetRemoteOS {
local remoteOsVar
$SSH_CMD env _REMOTE_TOKEN="$_REMOTE_TOKEN" bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1
$SSH_CMD env LC_ALL=C env _REMOTE_TOKEN="$_REMOTE_TOKEN" bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1
function GetOs {
local localOsVar
local localOsName
local localOsVer
local osInfo="/etc/os-release"
# There's no good way to tell if currently running in BusyBox shell. Using sluggish way.
if ls --help 2>&1 | grep -i "BusyBox" > /dev/null; then
localOsVar="BusyBox"
@@ -1155,9 +1182,11 @@ function GetOs {
fi
fi
# Get linux versions
if [ -f "/etc/os-release" ]; then
localOsName=$(GetConfFileValue "/etc/os-release" "NAME")
localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION")
if [ -f "$osInfo" ]; then
localOsName=$(grep "^NAME=" "$osInfo")
localOsName="${localOsName##*=}"
localOsVer=$(grep "^VERSION=" "$osInfo")
localOsVer="${localOsVer##*=}"
fi
echo "$localOsVar ($localOsName $localOsVer)"
@@ -1179,7 +1208,7 @@ ENDSSH
*"BSD"*)
REMOTE_OS="BSD"
;;
*"MINGW32"*|*"MSYS"*)
*"MINGW32"*|*"MINGW64"*|*"MSYS"*)
REMOTE_OS="msys"
;;
*"CYGWIN"*)
@@ -1262,7 +1291,7 @@ function RunRemoteCommand {
fi
Logger "Running command [$command] on remote host." "NOTICE"
cmd=$SSH_CMD' "env _REMOTE_TOKEN="'$_REMOTE_TOKEN'" $command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1'
cmd=$SSH_CMD' "env LC_ALL=C env _REMOTE_TOKEN="'$_REMOTE_TOKEN'" $command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1'
Logger "cmd: $cmd" "DEBUG"
eval "$cmd" &
WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false
@@ -1365,7 +1394,6 @@ function CheckConnectivity3rdPartyHosts {
fi
}
function RsyncPatternsAdd {
local patternType="${1}" # exclude or include
local pattern="${2}"
@@ -1491,13 +1519,13 @@ function PostInit {
# Define remote commands
if [ -f "$SSH_RSA_PRIVATE_KEY" ]; then
SSH_CMD="$(type -p ssh) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p scp) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p ssh) $SSH_COMP -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS -p $REMOTE_PORT"
SSH_CMD="$(type -p ssh) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p scp) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p ssh) $SSH_COMP -q -i $SSH_RSA_PRIVATE_KEY $SSH_OPTS -p $REMOTE_PORT"
elif [ -f "$SSH_PASSWORD_FILE" ]; then
SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p scp) $SSH_COMP -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP $SSH_OPTS -p $REMOTE_PORT"
SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP -q $SSH_OPTS $REMOTE_USER@$REMOTE_HOST -p $REMOTE_PORT"
SCP_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p scp) $SSH_COMP -q -P $REMOTE_PORT"
RSYNC_SSH_CMD="$(type -p sshpass) -f $SSH_PASSWORD_FILE $(type -p ssh) $SSH_COMP -q $SSH_OPTS -p $REMOTE_PORT"
else
SSH_PASSWORD=""
SSH_CMD=""
@@ -1535,23 +1563,22 @@ function SetCompression {
COMPRESSION_PROGRAM="| pigz -c$compressionString"
COMPRESSION_EXTENSION=.gz
# obackup specific
if [ "$LOCAL_OS" != "MacOSX" ]; then
COMPRESSION_OPTIONS=--rsyncable
fi
COMPRESSION_OPTIONS=--rsyncable
elif type gzip > /dev/null 2>&1
then
COMPRESSION_PROGRAM="| gzip -c$compressionString"
COMPRESSION_EXTENSION=.gz
# obackup specific
if [ "$LOCAL_OS" != "MacOSX" ]; then
COMPRESSION_OPTIONS=--rsyncable
fi
COMPRESSION_OPTIONS=--rsyncable
else
COMPRESSION_PROGRAM=
COMPRESSION_EXTENSION=
fi
fi
ALERT_LOG_FILE="$ALERT_LOG_FILE$COMPRESSION_EXTENSION"
if [ ".${ALERT_LOG_FILE##*.}" != "$COMPRESSION_EXTENSION" ]; then
ALERT_LOG_FILE="$ALERT_LOG_FILE$COMPRESSION_EXTENSION"
fi
}
function InitLocalOSDependingSettings {
@@ -1713,35 +1740,46 @@ function ParentPid {
# Neat version compare function found at http://stackoverflow.com/a/4025065/2635443
# Returns 0 if equal, 1 if $1 > $2 and 2 if $1 < $2
vercomp () {
if [[ $1 == $2 ]]
then
return 0
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
function VerComp () {
if [ "$1" == "" ] || [ "$2" == "" ]; then
Logger "Bogus Vercomp values [$1] and [$2]." "WARN"
return 1
fi
if [[ $1 == $2 ]]
then
echo 0
return
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
echo 1
return
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
echo 2
return
fi
done
echo 0
return
}
function GetConfFileValue () {
@@ -1774,6 +1812,29 @@ function SetConfFileValue () {
fi
}
# Function can replace [ -f /some/file* ] tests
# Modified version of http://stackoverflow.com/a/6364244/2635443
function WildcardFileExists () {
local file="${1}"
local exists=0
for f in $file; do
## Check if the glob gets expanded to existing files.
## If not, f here will be exactly the pattern above
## and the exists test will evaluate to false.
if [ -e "$f" ]; then
exists=1
break
fi
done
if [ $exists -eq 1 ]; then
echo 1
else
echo 0
fi
}
# If using "include" statements, make sure the script does not get executed unless it's loaded by bootstrap
_OFUNCTIONS_BOOTSTRAP=true
[ "$_OFUNCTIONS_BOOTSTRAP" != true ] && echo "Please use bootstrap.sh to load this dev version of $(basename $0)" && exit 1
@@ -4011,23 +4072,23 @@ function Init {
REMOTE_HOST=${hosturi%%:*}
fi
## Add update to default RSYNC_ARGS
RSYNC_ARGS=$RSYNC_ARGS" -u"
## Add update to default RSYNC_TYPE_ARGS
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" -u"
if [ $_LOGGER_VERBOSE == true ]; then
RSYNC_ARGS=$RSYNC_ARGS" -i"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" -i"
fi
if [ "$DELETE_VANISHED_FILES" == "yes" ]; then
RSYNC_ARGS=$RSYNC_ARGS" --delete"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --delete"
fi
if [ $stats == true ]; then
RSYNC_ARGS=$RSYNC_ARGS" --stats"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --stats"
fi
## Fix for symlink to directories on target cannot get updated
RSYNC_ARGS=$RSYNC_ARGS" --force"
RSYNC_TYPE_ARGS=$RSYNC_TYPE_ARGS" --force"
}
function Main {
@@ -4114,12 +4175,16 @@ function Usage {
_DRYRUN=false
no_maxtime=false
stats=false
PARTIAL=no
partial_transfers=false
delete_vanished=false
dont_get_backup_size=false
_DECRYPT_MODE=false
DECRYPT_PATH=""
_ENCRYPT_MODE=false
function GetCommandlineArguments {
local isFirstArgument=true
if [ $# -eq 0 ]; then
Usage
fi
@@ -4139,16 +4204,16 @@ function GetCommandlineArguments {
stats=false
;;
--partial)
PARTIAL="yes"
partial_transfers=true
;;
--no-maxtime)
no_maxtime=true
;;
--delete)
DELETE_VANISHED_FILES="yes"
delete_vanished=true
;;
--dontgetsize)
GET_BACKUP_SIZE="no"
dont_get_backup_size=true
;;
--help|-h|--version|-v)
Usage
@@ -4184,7 +4249,15 @@ function GetCommandlineArguments {
if [ $(IsNumeric $PARALLEL_ENCRYPTION_PROCESSES) -ne 1 ]; then
Logger "Bogus --parallel value. Using only one CPU." "WARN"
fi
;;
*)
if [ $isFirstArgument == false ]; then
Logger "Unknown option '$i'" "CRITICAL"
Usage
fi
;;
esac
isFirstArgument=false
done
}
@@ -4226,6 +4299,27 @@ else
Logger "Script begin, logging to [$LOG_FILE]." "DEBUG"
fi
if [ $no_maxtime == true ]; then
SOFT_MAX_EXEC_TIME_DB_TASK=0
SOFT_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_DB_TASK=0
HARD_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_TOTAL=0
fi
if [ $partial_transfers == true ]; then
PARTIAL="yes"
fi
if [ $delete_vanished == true ]; then
DELETE_VANISHED_FILES="yes"
fi
if [ $dont_get_backup_size == true ]; then
GET_BACKUP_SIZE="no"
fi
if [ "$IS_STABLE" != "yes" ]; then
Logger "This is an unstable dev build [$PROGRAM_BUILD]. Please use with caution." "WARN"
fi
@@ -4246,13 +4340,5 @@ PostInit
CheckCurrentConfig
GetRemoteOS
InitRemoteOSDependingSettings
if [ $no_maxtime == true ]; then
SOFT_MAX_EXEC_TIME_DB_TASK=0
SOFT_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_DB_TASK=0
HARD_MAX_EXEC_TIME_FILE_TASK=0
HARD_MAX_EXEC_TIME_TOTAL=0
fi
RunBeforeHook
Main