## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
@ -26,7 +26,7 @@ _OFUNCTIONS_BOOTSTRAP=true
#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
## 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
echo"Please run this script only with bash shell. Tested on bash >= 3.2"
localpids="${1}"# pids to wait for, separated by semi-colon
localsoftMaxTime="${2:-0}"# If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0.
localhardMaxTime="${3:-0}"# If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0.
localsleepTime="${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).
localkeepLogging="${5:-0}"# Every keepLogging seconds, an alive log message is send. Setting this value to zero disables any alive logging.
localcounting="${6:-true}"# Count time since function has been launched (true), or since script has been launched (false)
localspinner="${7:-true}"# Show spinner (true), don't show anything (false)
localnoErrorLog="${8:-false}"# Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true)
localid="${9-base}"# Optional id in order to get $WAIT_FOR_TASK_COMPLETION_id global variable
# ParallelExec function emulation, now uses ExecTasks
## 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
# 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.
localid="${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
localsoftPerProcessTime="${2:-0}"
localhardPerProcessTime="${3:-0}"
localsoftMaxTime="${4:-0}"# If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0.
localhardMaxTime="${5:-0}"# If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0.
localsleepTime="${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).
localkeepLogging="${7:-0}"# Every keepLogging seconds, an alive message is logged. Setting this value to zero disables any alive logging.
localcounting="${8:-true}"# Count time since function has been launched (true), or since script has been launched (false)
localspinner="${9:-true}"# Show spinner (true), do not show anything (false)
localnoTimeErrorLog="${10:-false}"# Log errors when reaching soft / hard max time (false), do not log errors on those triggers (true)
localnoErrorLogAtAll="${11:-false}"# Do not log errros at all (false)
localexecTasksMode="${12:-1}"# In which mode the function should work, see above
localmainInput="${13}"# Contains list of pids / commands or filepath to list of pids / commands
localauxInput="${14}"# Contains list of conditional commands or filepath to list of conditional commands
localnumberOfProcesses="${15:-2}"# Number of simultaneous commands to run in ParallExec mode
local i
localcallerName="${FUNCNAME[1]}"
Logger "${FUNCNAME[0]} called by [${FUNCNAME[0]} < ${FUNCNAME[1]} < ${FUNCNAME[2]} < ${FUNCNAME[3]} < ${FUNCNAME[4]} ...].""PARANOIA_DEBUG"#__WITH_PARANOIA_DEBUG
__CheckArguments 8$#"$@"#__WITH_PARANOIA_DEBUG
locallog_ttime=0# local time instance for comparaison
Logger "${FUNCNAME[0]} called in $execTasksMode mode by [${FUNCNAME[0]} < ${FUNCNAME[1]} < ${FUNCNAME[2]} < ${FUNCNAME[3]} < ${FUNCNAME[4]} ...].""PARANOIA_DEBUG"#__WITH_PARANOIA_DEBUG
@ -730,23 +937,27 @@ function WaitForTaskCompletion {
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
if[$log_ttime -ne $exec_time];then# Fix when sleep time lower than 1second
log_ttime=$exec_time
Logger "Current tasks still running with pids [$(joinString , ${pidsArray[@]})].""NOTICE"
if[$functionMode=="Wait"];then
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"
Logger "${FUNCNAME[0]} ended for [$callerName] using [$pidCount] subprocesses with [$errorcount] errors.""PARANOIA_DEBUG"#__WITH_PARANOIA_DEBUG
Logger "${FUNCNAME[0]} ended for [$callerName] using [$mainItemCount] subprocesses with [$errorcount] errors.""PARANOIA_DEBUG"#__WITH_PARANOIA_DEBUG
# 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
if[$pidCount -eq 1];then
return$retval
else
return$errorcount
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 {
localnumberOfProcesses="${1}"# Number of simultaneous commands to run
localcommandsArg="${2}"# Semi-colon separated list of commands, or path to file containing one command per line
localreadFromFile="${3:-false}"# commandsArg is a file (true), or a string (false)
localsoftMaxTime="${4:-0}"# If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0.
localhardMaxTime="${5:-0}"# If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0.
localsleepTime="${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).
localkeepLogging="${7:-0}"# Every keepLogging seconds, an alive log message is send. Setting this value to zero disables any alive logging.
localcounting="${8:-true}"# Count time since function has been launched (true), or since script has been launched (false)
localspinner="${9:-false}"# Show spinner (true), don't show spinner (false)
localnoErrorLog="${10:-false}"# Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true)
localcallerName="${FUNCNAME[1]}"
Logger "${FUNCNAME[0]} called by [${FUNCNAME[0]} < ${FUNCNAME[1]} < ${FUNCNAME[2]} < ${FUNCNAME[3]} < ${FUNCNAME[4]} ...].""PARANOIA_DEBUG"#__WITH_PARANOIA_DEBUG
if[$log_ttime -ne $exec_time];then# Fix when sleep time lower than 1s
log_ttime=$exec_time
Logger "There are $((commandCount-counter)) / $commandCount tasks in the queue. Currently, ${#pidsArray[@]} tasks running with pids [$(joinString , ${pidsArray[@]})].""NOTICE"
@ -1752,7 +1866,7 @@ function InitLocalOSDependingSettings {
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 {
__CheckArguments 0$#"$@"#__WITH_PARANOIA_DEBUG
@ -1845,7 +1959,7 @@ function InitRemoteOSDependingSettings {
RSYNC_ARGS=$RSYNC_ARGS" --whole-file"
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
## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
@ -26,7 +26,7 @@ _OFUNCTIONS_BOOTSTRAP=true
#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
## 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
echo"Please run this script only with bash shell. Tested on bash >= 3.2"
# 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
## 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
# 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.
localid="${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
localsoftPerProcessTime="${2:-0}"
localhardPerProcessTime="${3:-0}"
localsoftMaxTime="${4:-0}"# If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0.
localhardMaxTime="${5:-0}"# If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0.
localsleepTime="${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).
localkeepLogging="${7:-0}"# Every keepLogging seconds, an alive message is logged. Setting this value to zero disables any alive logging.
localcounting="${8:-true}"# Count time since function has been launched (true), or since script has been launched (false)
localspinner="${9:-true}"# Show spinner (true), do not show anything (false)
localnoTimeErrorLog="${10:-false}"# Log errors when reaching soft / hard max time (false), do not log errors on those triggers (true)
localnoErrorLogAtAll="${11:-false}"# Do not log errros at all (false)
localexecTasksMode="${12:-1}"# In which mode the function should work, see above
localmainInput="${13}"# Contains list of pids / commands or filepath to list of pids / commands
localauxInput="${14}"# Contains list of conditional commands or filepath to list of conditional commands
localnumberOfProcesses="${15:-2}"# Number of simultaneous commands to run in ParallExec mode
function WaitForTaskCompletion {
localpids="${1}"# pids to wait for, separated by semi-colon
localsoftMaxTime="${2:-0}"# If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0.
localhardMaxTime="${3:-0}"# If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0.
localsleepTime="${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).
localkeepLogging="${5:-0}"# Every keepLogging seconds, an alive log message is send. Setting this value to zero disables any alive logging.
localcounting="${6:-true}"# Count time since function has been launched (true), or since script has been launched (false)
localspinner="${7:-true}"# Show spinner (true), don't show anything (false)
localnoErrorLog="${8:-false}"# Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true)
localid="${9-base}"# Optional id in order to get $WAIT_FOR_TASK_COMPLETION_id global variable
local i
localcallerName="${FUNCNAME[1]}"
locallog_ttime=0# local time instance for comparaison
localseconds_begin=$SECONDS# Seconds since the beginning of the script
localexec_time=0# Seconds since the beginning of this function
# 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
localretval=0# return value of monitored pid process
localerrorcount=0# Number of pids that finished with errors
@ -692,23 +890,27 @@ function WaitForTaskCompletion {
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
if[$log_ttime -ne $exec_time];then# Fix when sleep time lower than 1second
log_ttime=$exec_time
Logger "Current tasks still running with pids [$(joinString , ${pidsArray[@]})].""NOTICE"
if[$functionMode=="Wait"];then
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"
Logger "${FUNCNAME[0]} called by [$callerName] finished monitoring [$pid] [$currentCommand] with exitcode [$retval].""DEBUG"
fi
fi
fi
done
pidsArray=("${newPidsArray[@]}")
# Trivial wait time for bash to not eat up all CPU
sleep $sleepTime
done
# 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
if[$pidCount -eq 1];then
return$retval
else
return$errorcount
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 {
localnumberOfProcesses="${1}"# Number of simultaneous commands to run
localcommandsArg="${2}"# Semi-colon separated list of commands, or path to file containing one command per line
localreadFromFile="${3:-false}"# commandsArg is a file (true), or a string (false)
localsoftMaxTime="${4:-0}"# If process(es) with pid(s) $pids take longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0.
localhardMaxTime="${5:-0}"# If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0.
localsleepTime="${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).
localkeepLogging="${7:-0}"# Every keepLogging seconds, an alive log message is send. Setting this value to zero disables any alive logging.
localcounting="${8:-true}"# Count time since function has been launched (true), or since script has been launched (false)
localspinner="${9:-false}"# Show spinner (true), don't show spinner (false)
localnoErrorLog="${10:-false}"# Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true)
localcallerName="${FUNCNAME[1]}"
locallog_ttime=0# local time instance for comparaison
localseconds_begin=$SECONDS# Seconds since the beginning of the script
localexec_time=0# Seconds since the beginning of this function
if[$log_ttime -ne $exec_time];then# Fix when sleep time lower than 1s
log_ttime=$exec_time
Logger "There are $((commandCount-counter)) / $commandCount tasks in the queue. Currently, ${#pidsArray[@]} tasks running with pids [$(joinString , ${pidsArray[@]})].""NOTICE"
@ -1623,7 +1738,7 @@ function InitLocalOSDependingSettings {
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