From ff9b9b632b3f8f113c3b35732c8cf3cab294737f Mon Sep 17 00:00:00 2001 From: deajan Date: Mon, 5 Nov 2018 14:12:39 +0100 Subject: [PATCH] Updated ofunctions --- dev/ofunctions.sh | 132 +++++++++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 54 deletions(-) diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index d1ba31a..7e8c5b9 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -31,7 +31,7 @@ #### OFUNCTIONS MINI SUBSET #### #### OFUNCTIONS MICRO SUBSET #### _OFUNCTIONS_VERSION=2.3.0-RC2 -_OFUNCTIONS_BUILD=2018100205 +_OFUNCTIONS_BUILD=2018110502 #### _OFUNCTIONS_BOOTSTRAP SUBSET #### _OFUNCTIONS_BOOTSTRAP=true #### _OFUNCTIONS_BOOTSTRAP SUBSET END #### @@ -104,7 +104,9 @@ else LOG_FILE="/tmp/$PROGRAM.log" fi +#### RUN_DIR SUBSET #### ## Default directory where to store temporary run files + if [ -w /tmp ]; then RUN_DIR=/tmp elif [ -w /var/tmp ]; then @@ -113,6 +115,13 @@ else RUN_DIR=. fi +## Special note when remote target is on the same host as initiator (happens for unit tests): we'll have to differentiate RUN_DIR so remote CleanUp won't affect initiator. +if [ "$_REMOTE_EXECUTION" == true ]; then + mkdir -p "$RUN_DIR/$PROGRAM.remote" + RUN_DIR="$RUN_DIR/$PROGRAM.remote" +fi +#### RUN_DIR SUBSET END #### + #### PoorMansRandomGenerator SUBSET #### # Get a random number on Windows BusyBox alike, also works on most Unixes that have dd, if dd is not found, then return $RANDOM function PoorMansRandomGenerator { @@ -155,7 +164,7 @@ function PoorMansRandomGenerator { #### PoorMansRandomGenerator SUBSET END #### # Initial TSTMAP value before function declaration -TSTAMP=$(date '+%Y%m%dT%H%M%S').$(PoorMansRandomGenerator 4) +TSTAMP=$(date '+%Y%m%dT%H%M%S').$(PoorMansRandomGenerator 5) # Default alert attachment filename ALERT_LOG_FILE="$RUN_DIR/$PROGRAM.$SCRIPT_PID.$TSTAMP.last.log" @@ -205,6 +214,8 @@ function RemoteLogger { local level="${2}" # Log level local retval="${3:-undef}" # optional return value of command + local prefix + if [ "$_LOGGER_PREFIX" == "time" ]; then prefix="TIME: $SECONDS - " elif [ "$_LOGGER_PREFIX" == "date" ]; then @@ -282,6 +293,8 @@ function Logger { local level="${2}" # Log level local retval="${3:-undef}" # optional return value of command + local prefix + if [ "$_LOGGER_PREFIX" == "time" ]; then prefix="TIME: $SECONDS - " elif [ "$_LOGGER_PREFIX" == "date" ]; then @@ -347,6 +360,28 @@ function Logger { } #### Logger SUBSET END #### +#### IsInteger SUBSET #### +# Function is busybox compatible since busybox ash does not understand direct regex, we use expr +function IsInteger { + local value="${1}" + + if type expr > /dev/null 2>&1; then + expr "$value" : '^[0-9]\{1,\}$' > /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo 1 + else + echo 0 + fi + else + if [[ $value =~ ^[0-9]+$ ]]; then + echo 1 + else + echo 0 + fi + fi +} +#### IsInteger SUBSET END #### + # Portable child (and grandchild) kill function tester under Linux, BSD and MacOS X function KillChilds { local pid="${1}" # Parent pid to kill childs @@ -416,8 +451,6 @@ function KillAllChilds { #### CleanUp SUBSET #### function CleanUp { - __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG - if [ "$_DEBUG" != "yes" ]; then rm -f "$RUN_DIR/$PROGRAM."*".$SCRIPT_PID.$TSTAMP" # Fix for sed -i requiring backup extension for BSD & Mac (see all sed -i statements) @@ -846,10 +879,11 @@ function ExecTasks { local minTimeBetweenRetries="${17:-300}" # Time (in seconds) between postponed command retries local validExitCodes="${18:-0}" # Semi colon separated list of valid main command exit codes which will not trigger errors + __CheckArguments 1-18 $# "$@" #__WITH_PARANOIA_DEBUG + local i - Logger "${FUNCNAME[0]} called by [${FUNCNAME[0]} < ${FUNCNAME[1]} < ${FUNCNAME[2]} < ${FUNCNAME[3]} < ${FUNCNAME[4]} ...]." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG - __CheckArguments 1-18 $# "$@" #__WITH_PARANOIA_DEBUG + Logger "${FUNCNAME[0]} id [$id] called by [${FUNCNAME[1]} < ${FUNCNAME[2]} < ${FUNCNAME[3]} < ${FUNCNAME[4]} < ${FUNCNAME[5]} < ${FUNCNAME[6]} ...]." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG # Since ExecTasks takes up to 17 arguments, do a quick preflight check in DEBUG mode if [ "$_DEBUG" == "yes" ]; then @@ -865,9 +899,6 @@ function ExecTasks { done fi - # Change '-' to '_' in task id - id="${id/-/_}" - # Expand validExitCodes into array IFS=';' read -r -a validExitCodes <<< "$validExitCodes" @@ -904,16 +935,10 @@ function ExecTasks { 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 - local hasPids=false # Are any valable pids given to function ? #__WITH_PARANOIA_DEBUG - local functionMode - - 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 + local softAlert=false + local failedPidsList # List containing failed pids with exit code separated by semicolons (eg : 2355:1;4534:2;2354:3) # Initialise global variable eval "WAIT_FOR_TASK_COMPLETION_$id=\"\"" @@ -1074,17 +1099,17 @@ function ExecTasks { # Check for valid exit codes if [ $(ArrayContains $retval "${validExitCodes[@]}") -eq 0 ]; then if [ $noErrorLogsAtAll != true ]; then - Logger "${FUNCNAME[0]} called by [$id] finished monitoring pid [$pid] with exitcode [$retval]." "DEBUG" + Logger "${FUNCNAME[0]} called by [$id] finished monitoring pid [$pid] with exitcode [$retval]." "ERROR" if [ "$functionMode" == "ParallelExec" ]; then Logger "Command was [${commandsArrayPid[$pid]}]." "ERROR" fi fi errorcount=$((errorcount+1)) # Welcome to variable variable bash hell - if [ "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_$id\")" == "" ]; then - eval "WAIT_FOR_TASK_COMPLETION_$id=\"$pid:$retval\"" + if [ "$failedPidsList" == "" ]; then + failedPidsList="$pid:$retval" else - eval "WAIT_FOR_TASK_COMPLETION_$id=\";$pid:$retval\"" + failedPidsList="$failedPidsList;$pid:$retval" fi else Logger "${FUNCNAME[0]} called by [$id] finished monitoring pid [$pid] with exitcode [$retval]." "DEBUG" @@ -1246,6 +1271,8 @@ function ExecTasks { # 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 + eval "WAIT_FOR_TASK_COMPLETION_$id=\"$failedPidsList\"" + if [ $mainItemCount -eq 1 ]; then return $retval else @@ -1296,7 +1323,7 @@ function IsNumeric { local value="${1}" if type expr > /dev/null 2>&1; then - expr "$value" : "^[-+]\?[0-9]*\.\?[0-9]\+$" > /dev/null 2>&1 + expr "$value" : '^[-+]\{0,1\}[0-9]*\.\{0,1\}[0-9]\{1,\}$' > /dev/null 2>&1 if [ $? -eq 0 ]; then echo 1 else @@ -1317,28 +1344,6 @@ function IsNumericExpand { echo $(IsNumeric "$value") } -#### IsInteger SUBSET #### -# Function is busybox compatible since busybox ash does not understand direct regex, we use expr -function IsInteger { - local value="${1}" - - if type expr > /dev/null 2>&1; then - expr "$value" : "^[0-9]\+$" > /dev/null 2>&1 - if [ $? -eq 0 ]; then - echo 1 - else - echo 0 - fi - else - if [[ $value =~ ^[0-9]+$ ]]; then - echo 1 - else - echo 0 - fi - fi -} -#### IsInteger SUBSET END #### - #### HumanToNumeric SUBSET #### # Converts human readable sizes into integer kilobyte sizes # Usage numericSize="$(HumanToNumeric $humanSize)" @@ -1444,6 +1449,8 @@ function GetLocalOS { # 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 localOsVar="BusyBox" + elif set -o | grep "winxp" > /dev/null; then + localOsVar="BusyBox-w32" else # Detecting the special ubuntu userland in Windows 10 bash if grep -i Microsoft /proc/sys/kernel/osrelease > /dev/null 2>&1; then @@ -1476,7 +1483,7 @@ function GetLocalOS { *"CYGWIN"*) LOCAL_OS="Cygwin" ;; - *"Microsoft"*) + *"Microsoft"*|*"MS/Windows"*) LOCAL_OS="WinNT10" ;; *"Darwin"*) @@ -1507,7 +1514,8 @@ function GetLocalOS { fi # Get Host info for Windows - if [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "BusyBox" ] || [ "$LOCAL_OS" == "Cygwin" ] || [ "$LOCAL_OS" == "WinNT10" ]; then localOsVar="$(uname -a)" + if [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "BusyBox" ] || [ "$LOCAL_OS" == "Cygwin" ] || [ "$LOCAL_OS" == "WinNT10" ]; then + localOsVar="$localOsVar $(uname -a)" if [ "$PROGRAMW6432" != "" ]; then LOCAL_OS_BITNESS=64 LOCAL_OS_FAMILY="Windows" @@ -1521,6 +1529,9 @@ function GetLocalOS { # Get Host info for Unix else LOCAL_OS_FAMILY="Unix" + fi + + if [ "$LOCAL_OS_FAMILY" == "Unix" ]; then if uname -m | grep '64' > /dev/null 2>&1; then LOCAL_OS_BITNESS=64 else @@ -2139,14 +2150,14 @@ function InitLocalOSDependingSettings { function InitRemoteOSDependingSettings { __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG - if [ "$REMOTE_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then + if [ "$REMOTE_OS" == "msys" ] || [ "$REMOTE_OS" == "Cygwin" ]; then REMOTE_FIND_CMD=$(dirname $BASH)/find else REMOTE_FIND_CMD=find fi ## Stat command has different syntax on Linux and FreeBSD/MacOSX - if [ "$LOCAL_OS" == "MacOSX" ] || [ "$LOCAL_OS" == "BSD" ]; then + if [ "$REMOTE_OS" == "MacOSX" ] || [ "$REMOTE_OS" == "BSD" ]; then REMOTE_STAT_CMD="stat -f \"%Sm\"" REMOTE_STAT_CTIME_MTIME_CMD="stat -f \\\"%N;%c;%m\\\"" else @@ -2330,13 +2341,26 @@ function SetConfFileValue () { local value="${3}" local separator="${4:-#}" - if grep "^$name=" "$file" > /dev/null; then - # Using -i.tmp for BSD compat - sed -i.tmp "s$separator^$name=.*$separator$name=$value$separator" "$file" - rm -f "$file.tmp" - Logger "Set [$name] to [$value] in config file [$file]." "DEBUG" + if [ -f "$file" ]; then + if grep "^$name=" "$file" > /dev/null 2>&1; then + # Using -i.tmp for BSD compat + sed -i.tmp "s$separator^$name=.*$separator$name=$value$separator" "$file" + if [ $? -ne 0 ]; then + Logger "Cannot update value [$name] to [$value] in config file [$file]." "ERROR" + fi + rm -f "$file.tmp" + Logger "Set [$name] to [$value] in config file [$file]." "DEBUG" + else + echo "$name=$value" >> "$file" + if [ $? -ne 0 ]; then + Logger "Cannot create value [$name] to [$value] in config file [$file]." "ERROR" + fi + fi else - Logger "Cannot set value [$name] to [$value] in config file [$file]." "ERROR" + echo "$name=$value" > "$file" + if [ $? -ne 0 ]; then + Logger "Config file [$file] does not exist. Failed to create it witn value [$name]." "ERROR" + fi fi } #### SetConfFileValue SUBSET END ####