diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index 67c8deb..e1eaf22 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -1,6 +1,6 @@ #### MINIMAL-FUNCTION-SET BEGIN #### -## FUNC_BUILD=2016112206 +## FUNC_BUILD=2016112401 ## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr ## To use in a program, define the following variables: @@ -15,9 +15,6 @@ ## 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 -#TODO: Rewrite Logger so we can decide what to send to stdout, stderr and logfile -#TODO: Windows checks, check sendmail & mailsend - if ! type "$BASH" > /dev/null; then echo "Please run this script only with bash shell. Tested on bash >= 3.2" exit 127 @@ -51,10 +48,10 @@ fi #__WITH_PARANOIA_DEBUG ## allow debugging from command line with _DEBUG=yes if [ ! "$_DEBUG" == "yes" ]; then _DEBUG=no - SLEEP_TIME=.05 # Tested under linux and FreeBSD bash, #TODO tests on cygwin / msys + SLEEP_TIME=.05 _LOGGER_VERBOSE=false else - if [ "$SLEEP_TIME" == "" ]; then # Set SLEEP_TIME as environment variable when runinng with bash -x in order to avoid spamming console + if [ "$SLEEP_TIME" == "" ]; then # Leave the possibity to set SLEEP_TIME as environment variable when runinng with bash -x in order to avoid spamming console SLEEP_TIME=.05 fi trap 'TrapError ${LINENO} $?' ERR @@ -571,23 +568,21 @@ function joinString { # Fills a global variable called WAIT_FOR_TASK_COMPLETION that contains list of failed pids in format pid1:result1;pid2:result2 # Warning: Don't imbricate this function into another run if you plan to use the global variable output -# Standard wait $! emulation would be WaitForTaskCompletion $! 0 0 ${FUNCNAME[0]} true 0 true false - -#TODO: function WaitForTask $pid $softTime $hardTime $sleepTime $keepLogging $counting $spinner $noErrror $callerName +# Standard wait $! emulation would be WaitForTaskCompletion $! 0 0 1 0 true false true "${FUNCNAME[0]}" function WaitForTaskCompletion { local pids="${1}" # pids to wait for, separated by semi-colon - local softMaxTime="${2}" # If program with pid $pid takes longer than $softMaxTime seconds, will log a warning, unless $softMaxTime equals 0. - local hardMaxTime="${3}" # If program with pid $pid takes longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 0. - local callerName="${4}" # Who called this function - local counting="${5:-true}" # Count time since function has been launched if true, since script has been launched if false - local keepLogging="${6:-0}" # Log a standby message every X seconds. Set to zero to disable logging - local noError="${7:-false}" # When set to true, reaching soft or hard max time does not trigger an error - local spinner="${8:-true}" # Do we show spinner ? - local sleepTime="${9:-0}" # Override SLEEP_TIME + 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 hardMaxTime="${3:-0}" # If process(es) with pid(s) $pids take longer than $hardMaxTime seconds, will stop execution, unless $hardMaxTime equals 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 keepLogging="${5:-0}" # Every keepLogging seconds, an 'alive' log message is send. Setting this value to zero disables any alive logging. + local counting="${6:-true}" # Count time since function has been launched (true), or since script has been launched (false) + local spinner="${7:-true}" # Show spinner (true), don't show anything (false) + local noError="${8:-false}" # Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true) + local callerName="${9}" # Name of the function who called this function for debugging purposes, generally ${FUNCNAME[0]} Logger "${FUNCNAME[0]} called by [$callerName]." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG - __CheckArguments 6-8 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 9 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG local soft_alert=false # Does a soft alert need to be triggered, if yes, send an alert once local log_ttime=0 # local time instance for comparaison @@ -612,11 +607,6 @@ function WaitForTaskCompletion { WAIT_FOR_TASK_COMPLETION="" - # Default value when not overriden - if [ $sleepTime -eq 0 ]; then - sleepTime=$SLEEP_TIME - fi - while [ ${#pidsArray[@]} -gt 0 ]; do newPidsArray=() @@ -711,15 +701,22 @@ function WaitForTaskCompletion { # 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 + +#TODO: function ParallelExec $numberOfProcesses $commandsArg $readFromFile $softTime $HardTime $sleepTime $keepLogging $counting $Spinner $noError $callerName + +#WIP function ParallelExec { - local numberOfProcesses="${1}" # Number of simultaneous commands to run - local commandsArg="${2}" # Semi-colon separated list of commands, or file containing one command per line - local readFromFile="${3:-false}" # Is commandsArg a file or a string ? - local softMaxTime="${4:-0}" + 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}" # local hardMaxTime="${5:-0}" - local callerName="${6}" # Who called this function - local counting="${7:-true}" # Count time since function has been launched if true, since script has been launched if false - local keepLogging="${8:-0}" # Log a standby message every X seconds. Set to zero to disable logging + local sleepTime="${6:-.05}" + local keepLogging="${7:-0}" + 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 noError="${10:-false}" + local callerName="${11}" __CheckArguments 8 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG @@ -752,9 +749,12 @@ function ParallelExec { while [ $counter -lt "$commandCount" ] || [ ${#pidsArray[@]} -gt 0 ]; do + if [ $spinner == true ]; then + Spinner + fi + while [ $counter -lt "$commandCount" ] && [ ${#pidsArray[@]} -lt $numberOfProcesses ]; do if [ $readFromFile == true ]; then - #TODO: Checked on FreeBSD 10, also check on Win command=$(awk 'NR == num_line {print; exit}' num_line=$((counter+1)) "$commandsArg") else command="${commandsArray[$counter]}" @@ -1105,7 +1105,8 @@ function RunLocalCommand { Logger "Running command [$command] on local host." "NOTICE" eval "$command" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 & - WaitForTaskCompletion $! 0 $hardMaxTime ${FUNCNAME[0]} true $KEEP_LOGGING + + WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} retval=$? if [ $retval -eq 0 ]; then Logger "Command succeded." "NOTICE" @@ -1140,7 +1141,7 @@ function RunRemoteCommand { cmd=$SSH_CMD' "$command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1' Logger "cmd: $cmd" "DEBUG" eval "$cmd" & - WaitForTaskCompletion $! 0 $hardMaxTime ${FUNCNAME[0]} true $KEEP_LOGGING + WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} retval=$? if [ $retval -eq 0 ]; then Logger "Command succeded." "NOTICE" @@ -1174,7 +1175,7 @@ function RunBeforeHook { pids="$pids;$!" fi if [ "$pids" != "" ]; then - WaitForTaskCompletion $pids 0 0 ${FUNCNAME[0]} true $KEEP_LOGGING + WaitForTaskCompletion $pids 0 0 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} fi } @@ -1193,7 +1194,7 @@ function RunAfterHook { pids="$pids;$!" fi if [ "$pids" != "" ]; then - WaitForTaskCompletion $pids 0 0 ${FUNCNAME[0]} true $KEEP_LOGGING + WaitForTaskCompletion $pids 0 0 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} fi } @@ -1206,7 +1207,7 @@ function CheckConnectivityRemoteHost { if [ "$REMOTE_HOST_PING" != "no" ] && [ "$REMOTE_OPERATION" != "no" ]; then eval "$PING_CMD $REMOTE_HOST > /dev/null 2>&1" & - WaitForTaskCompletion $! 60 180 ${FUNCNAME[0]} true $KEEP_LOGGING + WaitForTaskCompletion $! 60 180 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} retval=$? if [ $retval != 0 ]; then Logger "Cannot ping [$REMOTE_HOST]. Return code [$retval]." "WARN" @@ -1229,7 +1230,7 @@ function CheckConnectivity3rdPartyHosts { for i in $REMOTE_3RD_PARTY_HOSTS do eval "$PING_CMD $i > /dev/null 2>&1" & - WaitForTaskCompletion $! 180 360 ${FUNCNAME[0]} true $KEEP_LOGGING + WaitForTaskCompletion $! 180 360 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} retval=$? if [ $retval != 0 ]; then Logger "Cannot ping 3rd party host [$i]. Return code [$retval]." "NOTICE"