1
0
mirror of https://github.com/deajan/obackup.git synced 2024-11-15 04:03:41 +01:00

Rebuilt targets

This commit is contained in:
deajan 2018-01-03 22:32:19 +01:00
parent c5ad174a0e
commit f3a9e1d05e
3 changed files with 810 additions and 539 deletions

File diff suppressed because it is too large Load Diff

View File

@ -93,7 +93,7 @@ function GetLocalOS {
local localOsName local localOsName
local localOsVer local localOsVer
# There's no good way to tell if currently running in BusyBox shell. Using sluggish way. # There is 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 if ls --help 2>&1 | grep -i "BusyBox" > /dev/null; then
localOsVar="BusyBox" localOsVar="BusyBox"
else else
@ -151,8 +151,8 @@ function GetLocalOS {
# Get linux versions # Get linux versions
if [ -f "/etc/os-release" ]; then if [ -f "/etc/os-release" ]; then
localOsName=$(GetConfFileValue "/etc/os-release" "NAME") localOsName=$(GetConfFileValue "/etc/os-release" "NAME" true)
localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION") localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION" true)
fi fi
# Add a global variable for statistics in installer # Add a global variable for statistics in installer
@ -165,17 +165,24 @@ function GetLocalOS {
function GetConfFileValue () { function GetConfFileValue () {
local file="${1}" local file="${1}"
local name="${2}" local name="${2}"
local noError="${3:-false}"
local value local value
value=$(grep "^$name=" "$file") value=$(grep "^$name=" "$file")
if [ $? == 0 ]; then if [ $? == 0 ]; then
value="${value##*=}" value="${value##*=}"
echo "$value" echo "$value"
else
if [ $noError == true ]; then
Logger "Cannot get value for [$name] in config file [$file]." "NOTICE"
else else
Logger "Cannot get value for [$name] in config file [$file]." "ERROR" Logger "Cannot get value for [$name] in config file [$file]." "ERROR"
fi fi
fi
} }
function SetLocalOSSettings { function SetLocalOSSettings {
USER=root USER=root

View File

@ -6,14 +6,14 @@
PROGRAM="obackup" PROGRAM="obackup"
AUTHOR="(C) 2013-2017 by Orsiris de Jong" AUTHOR="(C) 2013-2017 by Orsiris de Jong"
CONTACT="http://www.netpower.fr/obackup - ozy@netpower.fr" CONTACT="http://www.netpower.fr/obackup - ozy@netpower.fr"
PROGRAM_VERSION=2.1-beta3 PROGRAM_VERSION=2.1-beta4
PROGRAM_BUILD=2017062004 PROGRAM_BUILD=2018010302
IS_STABLE=no IS_STABLE=no
_OFUNCTIONS_VERSION=2.1.4-rc1 _OFUNCTIONS_VERSION=2.2.0-dev
_OFUNCTIONS_BUILD=2017060903 _OFUNCTIONS_BUILD=2018010303
_OFUNCTIONS_BOOTSTRAP=true _OFUNCTIONS_BOOTSTRAP=true
## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr ## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
@ -27,8 +27,10 @@ _OFUNCTIONS_BOOTSTRAP=true
## _LOGGER_ERR_ONLY=true/false ## _LOGGER_ERR_ONLY=true/false
## _LOGGER_PREFIX="date"/"time"/"" ## _LOGGER_PREFIX="date"/"time"/""
#TODO: global WAIT_FOR_TASK_COMPLETION_id instead of callerName has to be backported to ParallelExec and osync / obackup / pmocr ocde
## Logger sets {ERROR|WARN}_ALERT variable when called with critical / error / warn loglevel ## Logger sets {ERROR|WARN}_ALERT variable when called with critical / error / warn loglevel
## When called from subprocesses, variable of main process can't be set. Status needs to be get via $RUN_DIR/$PROGRAM.Logger.{error|warn}.$SCRIPT_PID.$TSTAMP ## When called from subprocesses, variable of main process cannot be set. Status needs to be get via $RUN_DIR/$PROGRAM.Logger.{error|warn}.$SCRIPT_PID.$TSTAMP
if ! type "$BASH" > /dev/null; then if ! type "$BASH" > /dev/null; then
echo "Please run this script only with bash shell. Tested on bash >= 3.2" echo "Please run this script only with bash shell. Tested on bash >= 3.2"
@ -240,7 +242,7 @@ function Logger {
if [ "$level" == "CRITICAL" ]; then if [ "$level" == "CRITICAL" ]; then
_Logger "$prefix($level):$value" "$prefix\e[1;33;41m$value\e[0m" true _Logger "$prefix($level):$value" "$prefix\e[1;33;41m$value\e[0m" true
ERROR_ALERT=true ERROR_ALERT=true
# ERROR_ALERT / WARN_ALERT isn't set in main when Logger is called from a subprocess. Need to keep this flag. # ERROR_ALERT / WARN_ALERT is not set in main when Logger is called from a subprocess. Need to keep this flag.
echo -e "[$retval] in [$(joinString , ${FUNCNAME[@]})] SP=$SCRIPT_PID P=$$\n$prefix($level):$value" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" echo -e "[$retval] in [$(joinString , ${FUNCNAME[@]})] SP=$SCRIPT_PID P=$$\n$prefix($level):$value" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP"
return return
elif [ "$level" == "ERROR" ]; then elif [ "$level" == "ERROR" ]; then
@ -306,8 +308,8 @@ function KillChilds {
local pid="${1}" # Parent pid to kill childs local pid="${1}" # Parent pid to kill childs
local self="${2:-false}" # Should parent be killed too ? local self="${2:-false}" # Should parent be killed too ?
# Paranoid checks, we can safely assume that $pid shouldn't be 0 nor 1 # Paranoid checks, we can safely assume that $pid should not be 0 nor 1
if [ $(IsNumeric "$pid") -eq 0 ] || [ "$pid" == "" ] || [ "$pid" == "0" ] || [ "$pid" == "1" ]; then if [ $(IsInteger "$pid") -eq 0 ] || [ "$pid" == "" ] || [ "$pid" == "0" ] || [ "$pid" == "1" ]; then
Logger "Bogus pid given [$pid]." "CRITICAL" Logger "Bogus pid given [$pid]." "CRITICAL"
return 1 return 1
fi fi
@ -480,13 +482,13 @@ function SendEmail {
if [ $? != 0 ]; then if [ $? != 0 ]; then
Logger "Cannot send alert mail via $(type -p sendmail) !!!" "WARN" Logger "Cannot send alert mail via $(type -p sendmail) !!!" "WARN"
# Don't bother try other mail systems with busybox # Do not bother try other mail systems with busybox
return 1 return 1
else else
return 0 return 0
fi fi
else else
Logger "Sendmail not present. Won't send any mail" "WARN" Logger "Sendmail not present. Will not send any mail" "WARN"
return 1 return 1
fi fi
fi fi
@ -620,6 +622,8 @@ function LoadConfigFile {
CONFIG_FILE="$configFile" CONFIG_FILE="$configFile"
} }
# Quick and dirty performance logger only used for debugging
_OFUNCTIONS_SPINNER="|/-\\" _OFUNCTIONS_SPINNER="|/-\\"
function Spinner { function Spinner {
if [ $_LOGGER_SILENT == true ] || [ "$_LOGGER_ERR_ONLY" == true ]; then if [ $_LOGGER_SILENT == true ] || [ "$_LOGGER_ERR_ONLY" == true ]; then
@ -632,26 +636,133 @@ function Spinner {
fi fi
} }
# WaitForTaskCompletion function emulation, now uses ExecTasks
# 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
# Standard wait $! emulation would be WaitForTaskCompletion $! 0 0 1 0 true false true false
function WaitForTaskCompletion { function WaitForTaskCompletion {
local pids="${1}" # pids to wait for, separated by semi-colon local pids="${1}"
local softMaxTime="${2:-0}" # If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0. local softMaxTime="${2:-0}"
local hardMaxTime="${3:-0}" # If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0. local hardMaxTime="${3:-0}"
local sleepTime="${4:-.05}" # Seconds between each state check, the shorter this value, the snappier it will be, but as a tradeoff cpu power will be used (general values between .05 and 1). local sleepTime="${4:-.05}"
local keepLogging="${5:-0}" # Every keepLogging seconds, an alive log message is send. Setting this value to zero disables any alive logging. local keepLogging="${5:-0}"
local counting="${6:-true}" # Count time since function has been launched (true), or since script has been launched (false) local counting="${6:-true}"
local spinner="${7:-true}" # Show spinner (true), don't show anything (false) local spinner="${7:-true}"
local noErrorLog="${8:-false}" # Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true) local noErrorLog="${8:-false}"
local id="${9-base}"
local callerName="${FUNCNAME[1]}" ExecTasks "$id" 0 0 "$softMaxTime" "$hardMaxTime" "$sleepTime" "$keepLogging" "$counting" "$spinner" "$noErrorlog" false 1 "$pids" "" ""
}
# ParallelExec function emulation, now uses ExecTasks
function ParallelExec {
local numberOfProcesses="${1}"
local commandsArg="${2}"
local readFromFile="${3:-false}"
local softMaxTime="${4:-0}"
local hardMaxTime="${5:-0}"
local sleepTime="${6:-.05}"
local keepLogging="${7:-0}"
local counting="${8:-true}"
local spinner="${9:-false}"
local noErrorLog="${10:-false}"
if [ $readFromFile == true ]; then
ExecTasks "base" 0 0 "$softMaxTime" "$hardMaxTime" "$sleepTime" "$keepLogging" "$counting" "$spinner" "$noErrorLog" false 6 "$commandsArg" "" "$numberOfProcesses"
else
ExecTasks "base" 0 0 "$softMaxTime" "$hardMaxTime" "$sleepTime" "$keepLogging" "$counting" "$spinner" "$noErrorLog" false 3 "$commandsArg" "" "$numberOfProcesses"
fi
}
## Main asynchronous execution function
## This function can monitor given pids as background processes, and stop them if max execution time is reached. Suitable for multiple synchronous processes.
## It can also take a list of commands to execute in parallel, and stop them if max execution time is reached.
## Function has 8 execution modes
# WaitForTaskCompletion mode: Monitor given pids as background processes, stop them if max execution time is reached. Suitaable for multiple synhronous processes.
# 1 : WaitForTaskCompletion, semi-colon separated list of pids to monitor
# 2 : WaitForTaskCompletion, list of pids to monior, from file, one per line
# Example of improved wait $! emulation
# ExecTasks "some_identifier" 0 0 0 0 1 1800 true false true true 1 $!
# Example: monitor two sleep processes, warn if execution time is higher than 10 seconds, stop after 20 seconds
# sleep 15 &
# pid=$!
# sleep 20 &
# pid2=$!
# ExecTasks "some_identifier" 0 0 10 20 1 1800 true true false false 1 "$pid;$pid2"
# ParallelExecMode: Take list of commands to execute in parallel, stop them if max execution time is reached.
# Also take optional conditional arguments to verifiy before execution main commands. Conditional command exit code 0 means ready to execute. Other exit codes will ignore/postpone main command.
# 3 : ParallelExec, semi-colon separated list of commands to execute in parallel, no conditions
# 4 : ParallelExec, semi-colon separated list of commands to execute in parallel , semi-colon separated list of conditional commands, ignoring main commands on condition failures
# 5 : ParallelExec, semi-colon separated list of commands, semi-colon separated list of conditional commands, postponing main commands on condition failures
# 6 : ParallelExec, list of commands from file, one per line, no conditions
# 7 : ParallelExec, list of commands from file, one per line, list of conditional commands from file, one per line, ignoring main commands on condition failures
# 8 : ParallelExec, list of commands from file, one per line, list of conditional commands from file, one per line, postponing main commands on condition failures
# Exmaple: execute four du commands, only if directories exist, warn if execution takes more than 300 seconds, stop if takes longer than 900 seconds. Execute max 3 commands in parallel.
# commands="du -csh /var;du -csh /etc;du -csh /home;du -csh /usr"
# conditions="[ -d /var ];[ -d /etc ];[ -d /home];[ -d /usr]"
# ExecTasks "some_identifier" 0 0 300 900 1 1800 true true false false 4 "$commands" "$conditions" 3
# ParallelExecMode also creates output for commands in "$RUN_DIR/$PROGRAM.ExecTasks.$id.$SCRIPT_PID.$TSTAMP"
## ofunctions.sh subfunction requirements:
## Spinner
## Logger
## JoinString
## KillChilds
function ExecTasks {
local id="${1:-base}" # Optional ID in order to identify global variables from this run (only bash variable names, no '-'). Global variables are WAIT_FOR_TASK_COMPLETION_$id and HARD_MAX_EXEC_TIME_REACHED_$id
#TODO: not implemented yet
local softPerProcessTime="${2:-0}"
local hardPerProcessTime="${3:-0}"
local softMaxTime="${4:-0}" # If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0.
local hardMaxTime="${5:-0}" # If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0.
local sleepTime="${6:-.05}" # Seconds between each state check, the shorter this value, the snappier it will be, but as a tradeoff cpu power will be used (general values between .05 and 1).
local keepLogging="${7:-0}" # Every keepLogging seconds, an alive message is logged. Setting this value to zero disables any alive logging.
local counting="${8:-true}" # Count time since function has been launched (true), or since script has been launched (false)
local spinner="${9:-true}" # Show spinner (true), do not show anything (false)
local noTimeErrorLog="${10:-false}" # Log errors when reaching soft / hard max time (false), do not log errors on those triggers (true)
#TODO not implemented
local noErrorLogAtAll="${11:-false}" # Do not log errros at all (false)
local execTasksMode="${12:-1}" # In which mode the function should work, see above
local mainInput="${13}" # Contains list of pids / commands or filepath to list of pids / commands
local auxInput="${14}" # Contains list of conditional commands or filepath to list of conditional commands
local numberOfProcesses="${15:-2}" # Number of simultaneous commands to run in ParallExec mode
local i
# Since ExecTasks takes up to 15 arguments, do a quick preflight check in DEBUG mode
if [ "$_DEBUG" == "yes" ]; then
declare -a booleans=(counting spinner noTimeErrorLog noErrorLogAtAll)
for i in "${num_vars[@]}"; do
test="if [ $i != false ] && [ $i != true ]; then Logger \"Bogus $i value [\$$i] given to ${FUNCNAME[0]}.\" \"CRITICAL\"; exit 1; fi"
eval "$test"
done
declare -a integers=(softPerProcessTime hardPerProcessTime softMaxTime hardMaxTime keepLogging execTasksMode numberOfProcesses)
for i in "${integers[@]}"; do
test="if [ $(IsNumericExpand \"\$$i\") -eq 0 ]; then Logger \"Bogus $i value [\$$i] given to ${FUNCNAME[0]}.\" \"CRITICAL\"; exit 1; fi"
eval "$test"
done
fi
# ParallelExec specific variables
local auxItemCount=0 # Number of conditional commands
local commandsArray=() # Array containing commands
local commandsConditionArray=() # Array containing conditional commands
local currentCommand # Variable containing currently processed command
local currentCommandCondition # Variable containing currently processed conditional command
local commandsArrayPid # Array containing pids of commands currently run
local postPoneIfConditionFails # Boolean to check if command needs to be postponed if condition command fails
# Common variables
local pid # Current pid working on
local pidState # State of the process
local mainItemCount=0 # number of given items (pids or commands)
local readFromFile # Should we read pids / commands from a file (true)
local counter=0
local log_ttime=0 # local time instance for comparaison local log_ttime=0 # local time instance for comparaison
local seconds_begin=$SECONDS # Seconds since the beginning of the script local seconds_begin=$SECONDS # Seconds since the beginning of the script
@ -659,27 +770,116 @@ function WaitForTaskCompletion {
local retval=0 # return value of monitored pid process local retval=0 # return value of monitored pid process
local errorcount=0 # Number of pids that finished with errors local errorcount=0 # Number of pids that finished with errors
local pid # Current pid working on
local pidCount # number of given pids
local pidState # State of the process
local pidsArray # Array of currently running pids local pidsArray # Array of currently running pids
local newPidsArray # New array of currently running pids local newPidsArray # New array of currently running pids for next iteration
local pidsTimeArray # Array containing execution begin time of pids
local executeCommand # Boolean to check if currentCommand can be executed given a condition
if [ $counting == true ]; then # If counting == false _SOFT_ALERT should be a global value so no more than one soft alert is shown local functionMode
local _SOFT_ALERT=false # Does a soft alert need to be triggered, if yes, send an alert once
if [ $counting == true ]; then
local softAlert=false # Does a soft alert need to be triggered, if yes, send an alert once
else
local softAlert=false
fi fi
IFS=';' read -a pidsArray <<< "$pids" # Initialise global variable
pidCount=${#pidsArray[@]} eval "WAIT_FOR_TASK_COMPLETION_$id=\"\""
eval "HARD_MAX_EXEC_TIME_REACHED_$id=false"
# Set global var default case $execTasksMode in
eval "WAIT_FOR_TASK_COMPLETION_$callerName=\"\"" 1)
eval "HARD_MAX_EXEC_TIME_REACHED_$callerName=false" IFS=';' read -r -a pidsArray <<< "$mainInput"
mainItemCount=${#pidsArray[@]}
readFromFile=false
functionMode=WaitForTaskCompletion
# Force while condition to be true
counter=$mainItemCount
;;
2)
if [ -f "$mainInput" ]; then
mainItemCount=$(wc -l < "$mainInput")
readFromFile=true
else
Logger "Cannot read file [$mainInput]." "WARN"
fi
functionMode=WaitForTaskCompletion
# Force while condition to be true
counter=$mainItemCount
;;
3)
IFS=';' read -r -a commandsArray <<< "$mainInput"
mainItemCount=${#commandsArray[@]}
readFromFile=false
functionMode=ParallelExec
;;
4)
IFS=';' read -r -a commandsArray <<< "$mainInput"
mainItemCount=${#commandsArray[@]}
IFS=';' read -r -a commandsConditionArray <<< "$auxInput"
auxItemCount=${#commandsConditionArray[@]}
readFromFile=false
postPoneIfConditionFails=false
functionMode=ParallelExec
;;
5)
IFS=';' read -r -a commandsArray <<< "$mainInput"
mainItemCount=${#commandsArray[@]}
IFS=';' read -r -a commandsConditionArray <<< "$auxInput"
auxItemCount=${#commandsConditionArray[@]}
readFromFile=false
postPoneIfConditionFails=true
functionMode=ParallelExec
;;
6)
if [ -f "$mainInput" ]; then
mainItemCount=$(wc -l < "$mainInput")
readFromFile=true
else
Logger "Cannot read file [$mainInput]." "WARN"
fi
functionMode=ParallelExec
;;
7)
if [ -f "$mainInput" ]; then
mainItemCount=$(wc -l < "$mainInput")
readFromFile=true
else
Logger "Cannot read file [$mainInput]." "WARN"
fi
if [ -f "$auxInput" ]; then
auxItemCount=$(wc -l < "$auxInput")
else
Logger "Cannot read file [$auxInput]." "WARN"
fi
postPoneIfConditionFails=false
functionMode=ParallelExec
;;
8)
if [ -f "$mainInput" ]; then
mainItemCount=$(wc -l < "$mainInput")
readFromFile=true
else
Logger "Cannot read file [$mainInput]." "WARN"
fi
if [ -f "$auxInput" ]; then
auxItemCount=$(wc -l < "$auxInput")
else
Logger "Cannot read file [$auxInput]." "WARN"
fi
postPoneIfConditionFails=true
functionMode=ParallelExec
;;
*)
Logger "Unknown exec mode for ${FUNCNAME}." "CRITICAL"
exit 1
esac
while [ ${#pidsArray[@]} -gt 0 ]; do
#while [ ${#pidsArray[@]} -gt 0 ]; do
# The counter -lt mainItemCount has to be false for WaitForTaskCompletion modes
while [ ${#pidsArray[@]} -gt 0 ] || [ $counter -lt $mainItemCount ]; do
newPidsArray=() newPidsArray=()
if [ $spinner == true ]; then if [ $spinner == true ]; then
@ -693,24 +893,28 @@ function WaitForTaskCompletion {
if [ $keepLogging -ne 0 ]; then if [ $keepLogging -ne 0 ]; then
if [ $((($exec_time + 1) % $keepLogging)) -eq 0 ]; then if [ $((($exec_time + 1) % $keepLogging)) -eq 0 ]; then
if [ $log_ttime -ne $exec_time ]; then # Fix when sleep time lower than 1s if [ $log_ttime -ne $exec_time ]; then # Fix when sleep time lower than 1 second
log_ttime=$exec_time log_ttime=$exec_time
if [ $functionMode == "Wait" ]; then
Logger "Current tasks still running with pids [$(joinString , ${pidsArray[@]})]." "NOTICE" Logger "Current tasks still running with pids [$(joinString , ${pidsArray[@]})]." "NOTICE"
elif [ $functionMode == "ParallelExec" ]; then
Logger "There are $((mainItemCount-counter)) / $mainItemCount tasks in the queue. Currently, ${#pidsArray[@]} tasks running with pids [$(joinString , ${pidsArray[@]})]." "NOTICE"
fi
fi fi
fi fi
fi fi
if [ $exec_time -gt $softMaxTime ]; then if [ $exec_time -gt $softMaxTime ]; then
if [ "$_SOFT_ALERT" != true ] && [ $softMaxTime -ne 0 ] && [ $noErrorLog != true ]; then if [ "$softAlert" != true ] && [ $softMaxTime -ne 0 ] && [ $noTimeErrorLog != true ]; then
Logger "Max soft execution time exceeded for task [$callerName] with pids [$(joinString , ${pidsArray[@]})]." "WARN" Logger "Max soft execution time exceeded for task [$id] with pids [$(joinString , ${pidsArray[@]})]." "WARN"
_SOFT_ALERT=true softAlert=true
SendAlert true SendAlert true
fi fi
fi fi
if [ $exec_time -gt $hardMaxTime ] && [ $hardMaxTime -ne 0 ]; then if [ $exec_time -gt $hardMaxTime ] && [ $hardMaxTime -ne 0 ]; then
if [ $noErrorLog != true ]; then if [ $noTimeErrorLog != true ]; then
Logger "Max hard execution time exceeded for task [$callerName] with pids [$(joinString , ${pidsArray[@]})]. Stopping task execution." "ERROR" Logger "Max hard execution time exceeded for task [$id] with pids [$(joinString , ${pidsArray[@]})]. Stopping task execution." "ERROR"
fi fi
for pid in "${pidsArray[@]}"; do for pid in "${pidsArray[@]}"; do
KillChilds $pid true KillChilds $pid true
@ -721,11 +925,75 @@ function WaitForTaskCompletion {
fi fi
errorcount=$((errorcount+1)) errorcount=$((errorcount+1))
done done
if [ $noErrorLog != true ]; then if [ $noTimeErrorLog != true ]; then
SendAlert true SendAlert true
fi fi
eval "HARD_MAX_EXEC_TIME_REACHED_$callerName=true" eval "HARD_MAX_EXEC_TIME_REACHED_$id=true"
if [ $functionMode == "WaitForTaskCompletion" ]; then
return $errorcount return $errorcount
elif [ $functionMode == "ParallelExec" ]; then
return $((mainItemCount - counter + ${#pidsArray[@]}))
fi
fi
# The following execution bloc is only needed in ParallelExec mode since WaitForTaskCompletion does not execute commands, but only monitors them
if [ $functionMode == "ParallelExec" ]; then
while [ $counter -lt "$mainItemCount" ] && [ ${#pidsArray[@]} -lt $numberOfProcesses ]; do
if [ $readFromFile == true ]; then
currentCommand=$(awk 'NR == num_line {print; exit}' num_line=$((counter+1)) "$mainInput")
if [ $auxItemCount -ne 0 ]; then
currentCommandCondition=$(awk 'NR == num_line {print; exit}' num_line=$((counter+1)) "$auxInput")
fi
else
currentCommand="${commandsArray[$counter]}"
if [ $auxItemCount -ne 0 ]; then
currentCommandCondition="${commandsConditionArray[$counter]}"
fi
fi
executeCommand=false
if [ $auxItemCount -ne 0 ]; then
Logger "Checking condition [$currentCommandCondition] for command [$currentCommand]." "DEBUG"
eval "$currentCommandCondition" &
ExecTasks "subConditionCheck" 0 0 1800 3600 1 $KEEP_LOGGING true true true true 1 $!
retval=$?
if [ $retval -ne 0 ]; then
if [ $postPoneIfConditionFails == true ]; then
Logger "Condition not met for command [$currentCommand]. Postponing command." "NOTICE"
if [ $readFromFile == true ]; then
# TODO: we should not write to the original file, but create a copy instead we can write postponed commands to
echo "$currentCommand" >> "$mainInput"
echo "$currentCommandCondition" >> "$auxInput"
else
commandsArray+=($currentCommand)
commandsConditionArray+=($currentCommandCondition)
fi
mainItemCount=$((mainItemCount+1))
# Trivial sleeptime so postponed commands will not stack too fast
sleep $sleepTime
else
Logger "Condition not met for command [$currentCommand]. Ignoring command." "NOTICE"
fi
else
executeCommand=true
fi
else
executeCommand=true
fi
if [ $executeCommand == true ]; then
Logger "Running command [$currentCommand]." "DEBUG"
eval "$currentCommand" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$id.$SCRIPT_PID.$TSTAMP" 2>&1 &
pid=$!
pidsArray+=($pid)
commandsArrayPid[$pid]="$currentCommand"
#TODO not implemented
pidsTimeArray[$pid]=$((SECONDS - seconds_begin))
else
Logger "Skipping command [$currentCommand]." "DEBUG"
fi
counter=$((counter+1))
done
fi fi
for pid in "${pidsArray[@]}"; do for pid in "${pidsArray[@]}"; do
@ -734,196 +1002,51 @@ function WaitForTaskCompletion {
# Handle uninterruptible sleep state or zombies by ommiting them from running process array (How to kill that is already dead ? :) # Handle uninterruptible sleep state or zombies by ommiting them from running process array (How to kill that is already dead ? :)
pidState="$(eval $PROCESS_STATE_CMD)" pidState="$(eval $PROCESS_STATE_CMD)"
if [ "$pidState" != "D" ] && [ "$pidState" != "Z" ]; then if [ "$pidState" != "D" ] && [ "$pidState" != "Z" ]; then
#TODO: implement pidsTimeArray[$pid] check here
newPidsArray+=($pid) newPidsArray+=($pid)
fi fi
else else
# pid is dead, get it's exit code from wait command # pid is dead, get its exit code from wait command
wait $pid wait $pid
retval=$? retval=$?
if [ $retval -ne 0 ]; then if [ $retval -ne 0 ]; then
Logger "${FUNCNAME[0]} called by [$callerName] finished monitoring [$pid] with exitcode [$retval]." "DEBUG" Logger "${FUNCNAME[0]} called by [$id] finished monitoring [$pid] [$currentCommad] with exitcode [$retval]." "DEBUG"
errorcount=$((errorcount+1)) errorcount=$((errorcount+1))
# Welcome to variable variable bash hell # Welcome to variable variable bash hell
if [ "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_$callerName\")" == "" ]; then if [ "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_$id\")" == "" ]; then
eval "WAIT_FOR_TASK_COMPLETION_$callerName=\"$pid:$retval\"" eval "WAIT_FOR_TASK_COMPLETION_$id=\"$pid:$retval\""
else else
eval "WAIT_FOR_TASK_COMPLETION_$callerName=\";$pid:$retval\"" eval "WAIT_FOR_TASK_COMPLETION_$id=\";$pid:$retval\""
fi fi
else
Logger "${FUNCNAME[0]} called by [$id] finished monitoring [$pid] [$currentCommand] with exitcode [$retval]." "DEBUG"
fi fi
fi fi
fi fi
done done
pidsArray=("${newPidsArray[@]}") pidsArray=("${newPidsArray[@]}")
# Trivial wait time for bash to not eat up all CPU # Trivial wait time for bash to not eat up all CPU
sleep $sleepTime sleep $sleepTime
done done
# Return exit code if only one process was monitored, else return number of errors # Return exit code if only one process was monitored, else return number of errors
# As we cannot return multiple values, a global variable WAIT_FOR_TASK_COMPLETION contains all pids with their return value # As we cannot return multiple values, a global variable WAIT_FOR_TASK_COMPLETION contains all pids with their return value
if [ $pidCount -eq 1 ]; then #WIP: return code has nothing to do with logging
#if [ $noErrorLogAtAll == true ]; then
# return 0
#fi
if [ $mainItemCount -eq 1 ]; then
return $retval return $retval
else else
return $errorcount return $errorcount
fi fi
} }
# Take a list of commands to run, runs them sequentially with numberOfProcesses commands simultaneously runs
# Returns the number of non zero exit codes from commands
# Use cmd1;cmd2;cmd3 syntax for small sets, use file for large command sets
# Only 2 first arguments are mandatory
# Sets a global variable called HARD_MAX_EXEC_TIME_REACHED to true if hardMaxTime is reached
function ParallelExec {
local numberOfProcesses="${1}" # Number of simultaneous commands to run
local commandsArg="${2}" # Semi-colon separated list of commands, or path to file containing one command per line
local readFromFile="${3:-false}" # commandsArg is a file (true), or a string (false)
local softMaxTime="${4:-0}" # If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0.
local hardMaxTime="${5:-0}" # If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0.
local sleepTime="${6:-.05}" # Seconds between each state check, the shorter this value, the snappier it will be, but as a tradeoff cpu power will be used (general values between .05 and 1).
local keepLogging="${7:-0}" # Every keepLogging seconds, an alive log message is send. Setting this value to zero disables any alive logging.
local counting="${8:-true}" # Count time since function has been launched (true), or since script has been launched (false)
local spinner="${9:-false}" # Show spinner (true), don't show spinner (false)
local noErrorLog="${10:-false}" # Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true)
local callerName="${FUNCNAME[1]}"
local log_ttime=0 # local time instance for comparaison
local seconds_begin=$SECONDS # Seconds since the beginning of the script
local exec_time=0 # Seconds since the beginning of this function
local commandCount
local command
local pid
local counter=0
local commandsArray
local pidsArray
local newPidsArray
local retval
local errorCount=0
local pidState
local commandsArrayPid
# Set global var default
eval "HARD_MAX_EXEC_TIME_REACHED_$callerName=false"
if [ $counting == true ]; then # If counting == false _SOFT_ALERT should be a global value so no more than one soft alert is shown
local _SOFT_ALERT=false # Does a soft alert need to be triggered, if yes, send an alert once
fi
if [ $readFromFile == true ];then
if [ -f "$commandsArg" ]; then
commandCount=$(wc -l < "$commandsArg")
else
commandCount=0
fi
else
IFS=';' read -r -a commandsArray <<< "$commandsArg"
commandCount=${#commandsArray[@]}
fi
Logger "Runnning $commandCount commands in $numberOfProcesses simultaneous processes." "DEBUG"
while [ $counter -lt "$commandCount" ] || [ ${#pidsArray[@]} -gt 0 ]; do
if [ $spinner == true ]; then
Spinner
fi
if [ $counting == true ]; then
exec_time=$((SECONDS - seconds_begin))
else
exec_time=$SECONDS
fi
if [ $keepLogging -ne 0 ]; then
if [ $((($exec_time + 1) % $keepLogging)) -eq 0 ]; then
if [ $log_ttime -ne $exec_time ]; then # Fix when sleep time lower than 1s
log_ttime=$exec_time
Logger "Current tasks still running with pids [$(joinString , ${pidsArray[@]})]." "NOTICE"
fi
fi
fi
if [ $exec_time -gt $softMaxTime ]; then
if [ "$_SOFT_ALERT" != true ] && [ $softMaxTime -ne 0 ] && [ $noErrorLog != true ]; then
Logger "Max soft execution time exceeded for task [$callerName] with pids [$(joinString , ${pidsArray[@]})]." "WARN"
_SOFT_ALERT=true
SendAlert true
fi
fi
if [ $exec_time -gt $hardMaxTime ] && [ $hardMaxTime -ne 0 ]; then
if [ $noErrorLog != true ]; then
Logger "Max hard execution time exceeded for task [$callerName] with pids [$(joinString , ${pidsArray[@]})]. Stopping task execution." "ERROR"
fi
for pid in "${pidsArray[@]}"; do
KillChilds $pid true
if [ $? == 0 ]; then
Logger "Task with pid [$pid] stopped successfully." "NOTICE"
else
Logger "Could not stop task with pid [$pid]." "ERROR"
fi
done
if [ $noErrorLog != true ]; then
SendAlert true
fi
eval "HARD_MAX_EXEC_TIME_REACHED_$callerName=true"
# Return the number of commands that haven't run / finished run
return $((commandCount - counter + ${#pidsArray[@]}))
fi
while [ $counter -lt "$commandCount" ] && [ ${#pidsArray[@]} -lt $numberOfProcesses ]; do
if [ $readFromFile == true ]; then
command=$(awk 'NR == num_line {print; exit}' num_line=$((counter+1)) "$commandsArg")
else
command="${commandsArray[$counter]}"
fi
Logger "Running command [$command]." "DEBUG"
eval "$command" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$callerName.$SCRIPT_PID.$TSTAMP" 2>&1 &
pid=$!
pidsArray+=($pid)
commandsArrayPid[$pid]="$command"
counter=$((counter+1))
done
newPidsArray=()
for pid in "${pidsArray[@]}"; do
if [ $(IsInteger $pid) -eq 1 ]; then
# Handle uninterruptible sleep state or zombies by ommiting them from running process array (How to kill that is already dead ? :)
if kill -0 $pid > /dev/null 2>&1; then
pidState="$(eval $PROCESS_STATE_CMD)"
if [ "$pidState" != "D" ] && [ "$pidState" != "Z" ]; then
newPidsArray+=($pid)
fi
else
# pid is dead, get it's exit code from wait command
wait $pid
retval=$?
if [ $retval -ne 0 ]; then
Logger "Command [${commandsArrayPid[$pid]}] failed with exit code [$retval]." "ERROR"
errorCount=$((errorCount+1))
fi
fi
fi
done
pidsArray=("${newPidsArray[@]}")
# Trivial wait time for bash to not eat up all CPU
sleep $sleepTime
done
return $errorCount
}
function CleanUp { function CleanUp {
if [ "$_DEBUG" != "yes" ]; then if [ "$_DEBUG" != "yes" ]; then
@ -1074,7 +1197,7 @@ function GetLocalOS {
local localOsName local localOsName
local localOsVer local localOsVer
# There's no good way to tell if currently running in BusyBox shell. Using sluggish way. # There is 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 if ls --help 2>&1 | grep -i "BusyBox" > /dev/null; then
localOsVar="BusyBox" localOsVar="BusyBox"
else else
@ -1132,8 +1255,8 @@ function GetLocalOS {
# Get linux versions # Get linux versions
if [ -f "/etc/os-release" ]; then if [ -f "/etc/os-release" ]; then
localOsName=$(GetConfFileValue "/etc/os-release" "NAME") localOsName=$(GetConfFileValue "/etc/os-release" "NAME" true)
localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION") localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION" true)
fi fi
# Add a global variable for statistics in installer # Add a global variable for statistics in installer
@ -1164,7 +1287,7 @@ function GetOs {
local osInfo="/etc/os-release" local osInfo="/etc/os-release"
# There's no good way to tell if currently running in BusyBox shell. Using sluggish way. # There is 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 if ls --help 2>&1 | grep -i "BusyBox" > /dev/null; then
localOsVar="BusyBox" localOsVar="BusyBox"
else else
@ -1254,7 +1377,7 @@ function RunLocalCommand {
Logger "Running command [$command] on local host." "NOTICE" Logger "Running command [$command] on local host." "NOTICE"
eval "$command" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 & eval "$command" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 &
WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING true true false false 1 $!
retval=$? retval=$?
if [ $retval -eq 0 ]; then if [ $retval -eq 0 ]; then
Logger "Command succeded." "NOTICE" Logger "Command succeded." "NOTICE"
@ -1294,7 +1417,7 @@ function RunRemoteCommand {
cmd=$SSH_CMD' "env LC_ALL=C 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" Logger "cmd: $cmd" "DEBUG"
eval "$cmd" & eval "$cmd" &
WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING true true false false 1 $!
retval=$? retval=$?
if [ $retval -eq 0 ]; then if [ $retval -eq 0 ]; then
Logger "Command succeded." "NOTICE" Logger "Command succeded." "NOTICE"
@ -1327,7 +1450,7 @@ function RunBeforeHook {
pids="$pids;$!" pids="$pids;$!"
fi fi
if [ "$pids" != "" ]; then if [ "$pids" != "" ]; then
WaitForTaskCompletion $pids 0 0 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 0 0 true true false false 1 $pids
fi fi
} }
@ -1345,7 +1468,7 @@ function RunAfterHook {
pids="$pids;$!" pids="$pids;$!"
fi fi
if [ "$pids" != "" ]; then if [ "$pids" != "" ]; then
WaitForTaskCompletion $pids 0 0 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 0 0 true true false false 1 $pids
fi fi
} }
@ -1356,7 +1479,7 @@ function CheckConnectivityRemoteHost {
if [ "$REMOTE_HOST_PING" != "no" ] && [ "$REMOTE_OPERATION" != "no" ]; then if [ "$REMOTE_HOST_PING" != "no" ] && [ "$REMOTE_OPERATION" != "no" ]; then
eval "$PING_CMD $REMOTE_HOST > /dev/null 2>&1" & eval "$PING_CMD $REMOTE_HOST > /dev/null 2>&1" &
WaitForTaskCompletion $! 60 180 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 60 180 $SLEEP_TIME $KEEP_LOGGING true true false false 1 $!
retval=$? retval=$?
if [ $retval != 0 ]; then if [ $retval != 0 ]; then
Logger "Cannot ping [$REMOTE_HOST]. Return code [$retval]." "WARN" Logger "Cannot ping [$REMOTE_HOST]. Return code [$retval]." "WARN"
@ -1369,6 +1492,7 @@ function CheckConnectivity3rdPartyHosts {
local remote3rdPartySuccess local remote3rdPartySuccess
local retval local retval
local i
if [ "$REMOTE_3RD_PARTY_HOSTS" != "" ]; then if [ "$REMOTE_3RD_PARTY_HOSTS" != "" ]; then
@ -1376,7 +1500,7 @@ function CheckConnectivity3rdPartyHosts {
for i in $REMOTE_3RD_PARTY_HOSTS for i in $REMOTE_3RD_PARTY_HOSTS
do do
eval "$PING_CMD $i > /dev/null 2>&1" & eval "$PING_CMD $i > /dev/null 2>&1" &
WaitForTaskCompletion $! 180 360 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 180 360 $SLEEP_TIME $KEEP_LOGGING true true false false 1 $!
retval=$? retval=$?
if [ $retval != 0 ]; then if [ $retval != 0 ]; then
Logger "Cannot ping 3rd party host [$i]. Return code [$retval]." "NOTICE" Logger "Cannot ping 3rd party host [$i]. Return code [$retval]." "NOTICE"
@ -1447,7 +1571,7 @@ function RsyncPatterns {
RsyncPatternsFromAdd "exclude" "$RSYNC_EXCLUDE_FROM" RsyncPatternsFromAdd "exclude" "$RSYNC_EXCLUDE_FROM"
fi fi
if [ "$RSYNC_INCLUDE_PATTERN" != "" ]; then if [ "$RSYNC_INCLUDE_PATTERN" != "" ]; then
RsyncPatternsAdd "$RSYNC_INCLUDE_PATTERN" "include" RsyncPatternsAdd "include" "$RSYNC_INCLUDE_PATTERN"
fi fi
if [ "$RSYNC_INCLUDE_FROM" != "" ]; then if [ "$RSYNC_INCLUDE_FROM" != "" ]; then
RsyncPatternsFromAdd "include" "$RSYNC_INCLUDE_FROM" RsyncPatternsFromAdd "include" "$RSYNC_INCLUDE_FROM"
@ -1535,7 +1659,7 @@ function PostInit {
} }
function SetCompression { function SetCompression {
## Busybox fix (Termux xz command doesn't support compression at all) ## Busybox fix (Termux xz command does not support compression at all)
if [ "$LOCAL_OS" == "BusyBox" ] || [ "$REMOTE_OS" == "Busybox" ] || [ "$LOCAL_OS" == "Android" ] || [ "$REMOTE_OS" == "Android" ]; then if [ "$LOCAL_OS" == "BusyBox" ] || [ "$REMOTE_OS" == "Busybox" ] || [ "$LOCAL_OS" == "Android" ] || [ "$REMOTE_OS" == "Android" ]; then
compressionString="" compressionString=""
if type gzip > /dev/null 2>&1 if type gzip > /dev/null 2>&1
@ -1624,7 +1748,7 @@ function InitLocalOSDependingSettings {
SetCompression SetCompression
} }
# Gets executed regardless of the need of remote connections. It's just that this code needs to get executed after we know if there is a remote os, and if yes, which one # Gets executed regardless of the need of remote connections. It is just that this code needs to get executed after we know if there is a remote os, and if yes, which one
function InitRemoteOSDependingSettings { function InitRemoteOSDependingSettings {
if [ "$REMOTE_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then if [ "$REMOTE_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then
@ -1716,7 +1840,7 @@ function InitRemoteOSDependingSettings {
RSYNC_ARGS=$RSYNC_ARGS" --whole-file" RSYNC_ARGS=$RSYNC_ARGS" --whole-file"
fi fi
# Set compression options again after we know what remote OS we're dealing with # Set compression options again after we know what remote OS we are dealing with
SetCompression SetCompression
} }
@ -1785,17 +1909,24 @@ function VerComp () {
function GetConfFileValue () { function GetConfFileValue () {
local file="${1}" local file="${1}"
local name="${2}" local name="${2}"
local noError="${3:-false}"
local value local value
value=$(grep "^$name=" "$file") value=$(grep "^$name=" "$file")
if [ $? == 0 ]; then if [ $? == 0 ]; then
value="${value##*=}" value="${value##*=}"
echo "$value" echo "$value"
else
if [ $noError == true ]; then
Logger "Cannot get value for [$name] in config file [$file]." "NOTICE"
else else
Logger "Cannot get value for [$name] in config file [$file]." "ERROR" Logger "Cannot get value for [$name] in config file [$file]." "ERROR"
fi fi
fi
} }
function SetConfFileValue () { function SetConfFileValue () {
local file="${1}" local file="${1}"
local name="${2}" local name="${2}"
@ -2055,7 +2186,7 @@ function _ListDatabasesLocal {
sqlCmd="mysql -u $SQL_USER -Bse 'SELECT table_schema, round(sum( data_length + index_length ) / 1024) FROM information_schema.TABLES GROUP by table_schema;' > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" sqlCmd="mysql -u $SQL_USER -Bse 'SELECT table_schema, round(sum( data_length + index_length ) / 1024) FROM information_schema.TABLES GROUP by table_schema;' > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1"
Logger "Launching command [$sqlCmd]." "DEBUG" Logger "Launching command [$sqlCmd]." "DEBUG"
eval "$sqlCmd" & eval "$sqlCmd" &
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ $retval -eq 0 ]; then if [ $retval -eq 0 ]; then
Logger "Listing databases succeeded." "NOTICE" Logger "Listing databases succeeded." "NOTICE"
@ -2080,7 +2211,7 @@ function _ListDatabasesRemote {
sqlCmd="$SSH_CMD \"env _REMOTE_TOKEN=$_REMOTE_TOKEN mysql -u $SQL_USER -Bse 'SELECT table_schema, round(sum( data_length + index_length ) / 1024) FROM information_schema.TABLES GROUP by table_schema;'\" > \"$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP\" 2>&1" sqlCmd="$SSH_CMD \"env _REMOTE_TOKEN=$_REMOTE_TOKEN mysql -u $SQL_USER -Bse 'SELECT table_schema, round(sum( data_length + index_length ) / 1024) FROM information_schema.TABLES GROUP by table_schema;'\" > \"$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP\" 2>&1"
Logger "Command output: $sqlCmd" "DEBUG" Logger "Command output: $sqlCmd" "DEBUG"
eval "$sqlCmd" & eval "$sqlCmd" &
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ $retval -eq 0 ]; then if [ $retval -eq 0 ]; then
Logger "Listing databases succeeded." "NOTICE" Logger "Listing databases succeeded." "NOTICE"
@ -2395,7 +2526,7 @@ function ListRecursiveBackupDirectories {
Logger "Listing directories to backup." "NOTICE" Logger "Listing directories to backup." "NOTICE"
if [ "$BACKUP_TYPE" == "local" ] || [ "$BACKUP_TYPE" == "push" ]; then if [ "$BACKUP_TYPE" == "local" ] || [ "$BACKUP_TYPE" == "push" ]; then
_ListRecursiveBackupDirectoriesLocal & _ListRecursiveBackupDirectoriesLocal &
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_FILE_TASK $HARD_MAX_EXEC_TIME_FILE_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_TOTAL $HARD_MAX_EXEC_TIME_TOTAL $SLEEP_TIME $KEEP_LOGGING true true false false $!
if [ $? -eq 1 ]; then if [ $? -eq 1 ]; then
output_file="" output_file=""
else else
@ -2403,7 +2534,7 @@ function ListRecursiveBackupDirectories {
fi fi
elif [ "$BACKUP_TYPE" == "pull" ]; then elif [ "$BACKUP_TYPE" == "pull" ]; then
_ListRecursiveBackupDirectoriesRemote & _ListRecursiveBackupDirectoriesRemote &
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_FILE_TASK $HARD_MAX_EXEC_TIME_FILE_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_TOTAL $HARD_MAX_EXEC_TIME_TOTAL $SLEEP_TIME $KEEP_LOGGING true true false false $!
if [ $? -eq 1 ]; then if [ $? -eq 1 ]; then
output_file="" output_file=""
else else
@ -2467,10 +2598,10 @@ function _GetDirectoriesSizeLocal {
cmd="du -cs $dirList | tail -n1 | cut -f1 > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2> $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" cmd="du -cs $dirList | tail -n1 | cut -f1 > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2> $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP"
Logger "Launching command [$cmd]." "DEBUG" Logger "Launching command [$cmd]." "DEBUG"
eval "$cmd" & eval "$cmd" &
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_FILE_TASK $HARD_MAX_EXEC_TIME_FILE_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_FILE_TASK $HARD_MAX_EXEC_TIME_FILE_TASK $SLEEP_TIME $KEEP_LOGGING true true false false $!
# $cmd will return 0 even if some errors found, so we need to check if there is an error output # $cmd will return 0 even if some errors found, so we need to check if there is an error output
retval=$? retval=$?
if [ $retval -ne 0 ] || [ -s $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP ]; then if [ $retval -ne 0 ] || [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then
Logger "Could not get files size for some or all local directories." "ERROR" Logger "Could not get files size for some or all local directories." "ERROR"
_LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN"
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" ]; then if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" ]; then
@ -2621,9 +2752,9 @@ function RemoteLogger {
exit $retval exit $retval
ENDSSH ENDSSH
# $cmd will return 0 even if some errors found, so we need to check if there is an error output # $cmd will return 0 even if some errors found, so we need to check if there is an error output
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_FILE_TASK $HARD_MAX_EXEC_TIME_FILE_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_FILE_TASK $HARD_MAX_EXEC_TIME_FILE_TASK $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ $retval -ne 0 ] || [ -s $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP ]; then if [ $retval -ne 0 ] || [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then
Logger "Could not get files size for some or all remote directories." "ERROR" Logger "Could not get files size for some or all remote directories." "ERROR"
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" ]; then if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" ]; then
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "ERROR" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "ERROR"
@ -2667,7 +2798,7 @@ function _CreateDirectoryLocal {
if [ ! -d "$dirToCreate" ]; then if [ ! -d "$dirToCreate" ]; then
# No sudo, you should have all necessary rights # No sudo, you should have all necessary rights
mkdir -p "$dirToCreate" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1 & mkdir -p "$dirToCreate" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1 &
WaitForTaskCompletion $! 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ $retval -ne 0 ]; then if [ $retval -ne 0 ]; then
Logger "Cannot create directory [$dirToCreate]" "CRITICAL" Logger "Cannot create directory [$dirToCreate]" "CRITICAL"
@ -2811,7 +2942,7 @@ function RemoteLogger {
fi fi
exit 0 exit 0
ENDSSH ENDSSH
WaitForTaskCompletion $! 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ $retval -ne 0 ]; then if [ $retval -ne 0 ]; then
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "ERROR" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "ERROR"
@ -2873,7 +3004,8 @@ function GetDiskSpaceLocal {
if [ -d "$pathToCheck" ]; then if [ -d "$pathToCheck" ]; then
# Not elegant solution to make df silent on errors # Not elegant solution to make df silent on errors
# No sudo on local commands, assuming you should have all the necesarry rights to check backup directories sizes # No sudo on local commands, assuming you should have all the necesarry rights to check backup directories sizes
$DF_CMD "$pathToCheck" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 $DF_CMD "$pathToCheck" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 &
ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_TOTAL $HARD_MAX_EXEC_TIME_TOTAL $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ $retval -ne 0 ]; then if [ $retval -ne 0 ]; then
DISK_SPACE=0 DISK_SPACE=0
@ -3035,7 +3167,7 @@ function _GetDiskSpaceRemoteSub {
_GetDiskSpaceRemoteSub _GetDiskSpaceRemoteSub
exit $? exit $?
ENDSSH ENDSSH
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_TOTAL $HARD_MAX_EXEC_TIME_TOTAL $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_TOTAL $HARD_MAX_EXEC_TIME_TOTAL $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ $retval -ne 0 ]; then if [ $retval -ne 0 ]; then
DISK_SPACE=0 DISK_SPACE=0
@ -3213,7 +3345,7 @@ function _BackupDatabaseLocalToLocal {
Logger "Launching command [$drySqlCmd]." "DEBUG" Logger "Launching command [$drySqlCmd]." "DEBUG"
eval "$drySqlCmd" & eval "$drySqlCmd" &
fi fi
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then
if [ $_DRYRUN == false ]; then if [ $_DRYRUN == false ]; then
@ -3261,7 +3393,7 @@ function _BackupDatabaseLocalToRemote {
Logger "Launching command [$drySqlCmd]." "DEBUG" Logger "Launching command [$drySqlCmd]." "DEBUG"
eval "$drySqlCmd" & eval "$drySqlCmd" &
fi fi
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then
if [ $_DRYRUN == false ]; then if [ $_DRYRUN == false ]; then
@ -3309,7 +3441,7 @@ function _BackupDatabaseRemoteToLocal {
Logger "Launching command [$drySqlCmd]." "DEBUG" Logger "Launching command [$drySqlCmd]." "DEBUG"
eval "$drySqlCmd" & eval "$drySqlCmd" &
fi fi
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then
if [ $_DRYRUN == false ]; then if [ $_DRYRUN == false ]; then
@ -3450,12 +3582,12 @@ function EncryptFiles {
hardMaxExecTime=0 hardMaxExecTime=0
fi fi
ParallelExec $PARALLEL_ENCRYPTION_PROCESSES "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.parallel.$SCRIPT_PID.$TSTAMP" true $softMaxExecTime $hardMaxExecTime $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $softMaxExecTime $hardMaxExecTime $SLEEP_TIME $KEEP_LOGGING true true false false 6 "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.parallel.$SCRIPT_PID.$TSTAMP" "" PARALLEL_ENCRYPTION_PROCESSES
retval=$? retval=$?
if [ $retval -ne 0 ]; then if [ $retval -ne 0 ]; then
Logger "Encryption error." "ERROR" Logger "Encryption error." "ERROR"
# Output file is defined in ParallelExec # Output file is defined in ParallelExec
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.ParallelExec.EncryptFiles.$SCRIPT_PID.$TSTAMP)" "DEBUG" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.ExecTasks.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "DEBUG"
fi fi
successCounter=$(($(wc -l < "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.parallel.$SCRIPT_PID.$TSTAMP") - retval)) successCounter=$(($(wc -l < "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.parallel.$SCRIPT_PID.$TSTAMP") - retval))
errorCounter=$retval errorCounter=$retval
@ -3618,7 +3750,7 @@ function Rsync {
Logger "Launching command [$rsyncCmd]." "DEBUG" Logger "Launching command [$rsyncCmd]." "DEBUG"
eval "$rsyncCmd" & eval "$rsyncCmd" &
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_FILE_TASK $HARD_MAX_EXEC_TIME_FILE_TASK $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 $SOFT_MAX_EXEC_TIME_FILE_TASK $HARD_MAX_EXEC_TIME_FILE_TASK $SLEEP_TIME $KEEP_LOGGING true true false false $!
retval=$? retval=$?
if [ $retval -ne 0 ]; then if [ $retval -ne 0 ]; then
Logger "Failed to backup [$sourceDir] to [$destinationDir]." "ERROR" Logger "Failed to backup [$sourceDir] to [$destinationDir]." "ERROR"
@ -3765,7 +3897,7 @@ function _RotateBackupsLocal {
cmd="rm -rf \"$path\"" cmd="rm -rf \"$path\""
Logger "Launching command [$cmd]." "DEBUG" Logger "Launching command [$cmd]." "DEBUG"
eval "$cmd" & eval "$cmd" &
WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false false $!
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
Logger "Cannot delete oldest copy [$path]." "ERROR" Logger "Cannot delete oldest copy [$path]." "ERROR"
_LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN"
@ -3778,7 +3910,7 @@ function _RotateBackupsLocal {
cmd="mv \"$path\" \"$backup.$PROGRAM.$copy\"" cmd="mv \"$path\" \"$backup.$PROGRAM.$copy\""
Logger "Launching command [$cmd]." "DEBUG" Logger "Launching command [$cmd]." "DEBUG"
eval "$cmd" & eval "$cmd" &
WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false false $!
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
Logger "Cannot move [$path] to [$backup.$PROGRAM.$copy]." "ERROR" Logger "Cannot move [$path] to [$backup.$PROGRAM.$copy]." "ERROR"
_LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN"
@ -3793,7 +3925,7 @@ function _RotateBackupsLocal {
cmd="mv \"$backup\" \"$backup.$PROGRAM.1\"" cmd="mv \"$backup\" \"$backup.$PROGRAM.1\""
Logger "Launching command [$cmd]." "DEBUG" Logger "Launching command [$cmd]." "DEBUG"
eval "$cmd" & eval "$cmd" &
WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false false $!
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
Logger "Cannot move [$backup] to [$backup.$PROGRAM.1]." "ERROR" Logger "Cannot move [$backup] to [$backup.$PROGRAM.1]." "ERROR"
_LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN"
@ -3803,7 +3935,7 @@ function _RotateBackupsLocal {
cmd="cp -R \"$backup\" \"$backup.$PROGRAM.1\"" cmd="cp -R \"$backup\" \"$backup.$PROGRAM.1\""
Logger "Launching command [$cmd]." "DEBUG" Logger "Launching command [$cmd]." "DEBUG"
eval "$cmd" & eval "$cmd" &
WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false false $!
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
Logger "Cannot copy [$backup] to [$backup.$PROGRAM.1]." "ERROR" Logger "Cannot copy [$backup] to [$backup.$PROGRAM.1]." "ERROR"
_LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN"
@ -3813,7 +3945,7 @@ function _RotateBackupsLocal {
cmd="mv \"$backup\" \"$backup.$PROGRAM.1\"" cmd="mv \"$backup\" \"$backup.$PROGRAM.1\""
Logger "Launching command [$cmd]." "DEBUG" Logger "Launching command [$cmd]." "DEBUG"
eval "$cmd" & eval "$cmd" &
WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false false $!
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
Logger "Cannot move [$backup] to [$backup.$PROGRAM.1]." "ERROR" Logger "Cannot move [$backup] to [$backup.$PROGRAM.1]." "ERROR"
_LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN"
@ -4004,7 +4136,7 @@ function _RotateBackupsRemoteSSH {
ENDSSH ENDSSH
WaitForTaskCompletion $! 1800 0 $SLEEP_TIME $KEEP_LOGGING true true false ExecTasks "${FUNCNAME[0]}" 0 0 1800 0 $SLEEP_TIME $KEEP_LOGGING true true false false $!
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
Logger "Could not rotate backups in [$backupPath]." "ERROR" Logger "Could not rotate backups in [$backupPath]." "ERROR"
Logger "Command output:\n $(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "ERROR" Logger "Command output:\n $(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "ERROR"