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

Updated ofunctions

This commit is contained in:
deajan 2018-07-30 15:36:39 +02:00
parent fdb88e04f2
commit 5b0442caed

View File

@ -1,22 +1,18 @@
#!/usr/bin/env bash #!/usr/bin/env bash
#### OFUNCTIONS FULL SUBSET #### ## Generic and highly portable bash functions written in 2013-2018 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
#### OFUNCTIONS MINI SUBSET ####
#TODO: ExecTasks postponed arrays / files grow a lot. Consider having them "rolling" #TODO: ExecTasks postponed arrays / files grow a lot. Consider having them "rolling"
#done: add checkRFC function (and use it for --destination-mails) #TODO: command line arguments don't take -AaqV for example
#done: ExecTasks still needs some better call argument list #TODO: Vercomp, IsNumeric, IsNumericExpand are not busybux ash compatible
#done: ExecTasks sub function relocate
#done: SendMail and SendEmail convert functions inverted, check on osync and obackup
#command line arguments don't take -AaqV for example
#### OFUNCTIONS FULL SUBSET ####
#### OFUNCTIONS MINI SUBSET ####
_OFUNCTIONS_VERSION=2.3.0-dev _OFUNCTIONS_VERSION=2.3.0-dev
_OFUNCTIONS_BUILD=2018031501 _OFUNCTIONS_BUILD=2018070902
#### _OFUNCTIONS_BOOTSTRAP SUBSET #### #### _OFUNCTIONS_BOOTSTRAP SUBSET ####
_OFUNCTIONS_BOOTSTRAP=true _OFUNCTIONS_BOOTSTRAP=true
#### _OFUNCTIONS_BOOTSTRAP SUBSET END #### #### _OFUNCTIONS_BOOTSTRAP SUBSET END ####
## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
## To use in a program, define the following variables: ## To use in a program, define the following variables:
## PROGRAM=program-name ## PROGRAM=program-name
## INSTANCE_ID=program-instance-name ## INSTANCE_ID=program-instance-name
@ -81,9 +77,6 @@ fi
SCRIPT_PID=$$ SCRIPT_PID=$$
# TODO: Check if %N works on MacOS
TSTAMP=$(date '+%Y%m%dT%H%M%S.%N')
LOCAL_USER=$(whoami) LOCAL_USER=$(whoami)
LOCAL_HOST=$(hostname) LOCAL_HOST=$(hostname)
@ -111,6 +104,46 @@ else
RUN_DIR=. RUN_DIR=.
fi fi
#### PoorMansRandomGenerator SUBSET ####
# Get a random number on Windows BusyBox alike, also works on most Unixes
function PoorMansRandomGenerator {
local digits="${1}" # The number of digits to generate
local minimum=1
local maximum
local n=0
if [ "$digits" == "" ]; then
digits=5
fi
# Minimum already has a digit
for n in $(seq 1 $((digits-1))); do
minimum=$minimum"0"
maximum=$maximum"9"
done
maximum=$maximum"9"
#n=0; while [ $n -lt $minimum ]; do n=$n$(dd if=/dev/urandom bs=100 count=1 2>/dev/null | tr -cd '0-9'); done; n=$(echo $n | sed -e 's/^0//')
# bs=19 since if real random strikes, having a 19 digits number is not supported
while [ $n -lt $minimum ] || [ $n -gt $maximum ]; do
if [ $n -lt $minimum ]; then
# Add numbers
n=$n$(dd if=/dev/urandom bs=19 count=1 2>/dev/null | tr -cd '0-9')
n=$(echo $n | sed -e 's/^0//')
if [ "$n" == "" ]; then
n=0
fi
elif [ $n -gt $maximum ]; then
n=$(echo $n | sed 's/.$//')
fi
done
echo $n
}
#### PoorMansRandomGenerator SUBSET END ####
# Initial TSTMAP value before function declaration
TSTAMP=$(date '+%Y%m%dT%H%M%S').$(PoorMansRandomGenerator 4)
# Default alert attachment filename # Default alert attachment filename
ALERT_LOG_FILE="$RUN_DIR/$PROGRAM.$SCRIPT_PID.$TSTAMP.last.log" ALERT_LOG_FILE="$RUN_DIR/$PROGRAM.$SCRIPT_PID.$TSTAMP.last.log"
@ -143,8 +176,11 @@ function _Logger {
if [ "$logValue" != "" ]; then if [ "$logValue" != "" ]; then
echo -e "$logValue" >> "$LOG_FILE" echo -e "$logValue" >> "$LOG_FILE"
# Current log file
echo -e "$logValue" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" # Build current log file for alerts if we have a sufficient environment
if [ "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" != "" ]; then
echo -e "$logValue" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP"
fi
fi fi
if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then
@ -179,7 +215,7 @@ function RemoteLogger {
fi fi
return return
elif [ "$level" == "ERROR" ]; then elif [ "$level" == "ERROR" ]; then
_Logger "" "$prefix\e[91m$value\e[0m" true _Logger "" "$prefix\e[31m$value\e[0m" true
if [ $_DEBUG == "yes" ]; then if [ $_DEBUG == "yes" ]; then
_Logger -e "" "[$retval] in [$(joinString , ${FUNCNAME[@]})] SP=$SCRIPT_PID P=$$" true _Logger -e "" "[$retval] in [$(joinString , ${FUNCNAME[@]})] SP=$SCRIPT_PID P=$$" true
fi fi
@ -201,7 +237,7 @@ function RemoteLogger {
fi fi
return return
elif [ "$level" == "ALWAYS" ]; then elif [ "$level" == "ALWAYS" ]; then
_Logger "" "$prefix$value" _Logger "" "$prefix$value"
return return
elif [ "$level" == "DEBUG" ]; then elif [ "$level" == "DEBUG" ]; then
if [ "$_DEBUG" == "yes" ]; then if [ "$_DEBUG" == "yes" ]; then
@ -235,6 +271,7 @@ function RemoteLogger {
# VERBOSE sent to stdout if _LOGGER_VERBOSE = true # VERBOSE sent to stdout if _LOGGER_VERBOSE = true
# ALWAYS is sent to stdout unless _LOGGER_SILENT = true # ALWAYS is sent to stdout unless _LOGGER_SILENT = true
# DEBUG & PARANOIA_DEBUG are only sent to stdout if _DEBUG=yes # DEBUG & PARANOIA_DEBUG are only sent to stdout if _DEBUG=yes
# SIMPLE is a wrapper for QuickLogger that does not use advanced functionality
function Logger { function Logger {
local value="${1}" # Sentence to log (in double quotes) local value="${1}" # Sentence to log (in double quotes)
local level="${2}" # Log level local level="${2}" # Log level
@ -291,6 +328,13 @@ function Logger {
_Logger "$prefix$value" "$prefix\e[35m$value\e[0m" #__WITH_PARANOIA_DEBUG _Logger "$prefix$value" "$prefix\e[35m$value\e[0m" #__WITH_PARANOIA_DEBUG
return #__WITH_PARANOIA_DEBUG return #__WITH_PARANOIA_DEBUG
fi #__WITH_PARANOIA_DEBUG fi #__WITH_PARANOIA_DEBUG
elif [ "$level" == "SIMPLE" ]; then
if [ "$_LOGGER_SILENT" == true ]; then
_Logger "$preix$value"
else
_Logger "$preix$value" "$prefix$value"
fi
return
else else
_Logger "\e[41mLogger function called without proper loglevel [$level].\e[0m" "\e[41mLogger function called without proper loglevel [$level].\e[0m" true _Logger "\e[41mLogger function called without proper loglevel [$level].\e[0m" "\e[41mLogger function called without proper loglevel [$level].\e[0m" true
_Logger "Value was: $prefix$value" "Value was: $prefix$value" true _Logger "Value was: $prefix$value" "Value was: $prefix$value" true
@ -298,31 +342,6 @@ function Logger {
} }
#### Logger SUBSET END #### #### Logger SUBSET END ####
#### QuickLogger SUBSET ####
# QuickLogger subfunction, can be called directly
function _QuickLogger {
local value="${1}"
local destination="${2}" # Destination: stdout, log, both
if ([ "$destination" == "log" ] || [ "$destination" == "both" ]); then
echo -e "$(date) - $value" >> "$LOG_FILE"
elif ([ "$destination" == "stdout" ] || [ "$destination" == "both" ]); then
echo -e "$value"
fi
}
# Generic quick logging function
function QuickLogger {
local value="${1}"
if [ "$_LOGGER_SILENT" == true ]; then
_QuickLogger "$value" "log"
else
_QuickLogger "$value" "stdout"
fi
}
#### QuickLogger SUBSET END ####
# Portable child (and grandchild) kill function tester under Linux, BSD and MacOS X # Portable child (and grandchild) kill function tester under Linux, BSD and MacOS X
function KillChilds { function KillChilds {
local pid="${1}" # Parent pid to kill childs local pid="${1}" # Parent pid to kill childs
@ -335,7 +354,6 @@ function KillChilds {
fi fi
if kill -0 "$pid" > /dev/null 2>&1; then if kill -0 "$pid" > /dev/null 2>&1; then
# Warning: pgrep is not native on cygwin, have this checked in CheckEnvironment
if children="$(pgrep -P "$pid")"; then if children="$(pgrep -P "$pid")"; then
if [[ "$pid" == *"$children"* ]]; then if [[ "$pid" == *"$children"* ]]; then
Logger "Bogus pgrep implementation." "CRITICAL" Logger "Bogus pgrep implementation." "CRITICAL"
@ -457,6 +475,12 @@ function SendAlert {
# encryption can be set to tls, ssl or none # encryption can be set to tls, ssl or none
# smtpUser and smtpPassword are optional # smtpUser and smtpPassword are optional
# SendEmail "subject" "Body text" "receiver@example.com receiver2@otherdomain.com" "/path/to/attachment.file" "senderMail@example.com" "smtpServer.domain.tld" "smtpPort" "encryption" "smtpUser" "smtpPassword" # SendEmail "subject" "Body text" "receiver@example.com receiver2@otherdomain.com" "/path/to/attachment.file" "senderMail@example.com" "smtpServer.domain.tld" "smtpPort" "encryption" "smtpUser" "smtpPassword"
# If text is received as attachment ATT00001.bin or noname, consider adding the following to /etc/mail.rc
#set ttycharset=iso-8859-1
#set sendcharsets=iso-8859-1
#set encoding=8bit
function SendEmail { function SendEmail {
local subject="${1}" local subject="${1}"
local message="${2}" local message="${2}"
@ -479,11 +503,16 @@ function SendEmail {
local i local i
for i in "${destinationMails}"; do if [ "${destinationMails[@]}" != "" ]; then
if [ $(CheckRFC822 "$i") -ne 1 ]; then for i in "${destinationMails[@]}"; do
Logger "Given email [$i] does not seem to be valid." "WARN" if [ $(CheckRFC822 "$i") -ne 1 ]; then
fi Logger "Given email [$i] does not seem to be valid." "WARN"
done fi
done
else
Logger "No valid email adresses given." "WARN"
return 1
fi
# Prior to sending an email, convert its body if needed # Prior to sending an email, convert its body if needed
if [ "$MAIL_BODY_CHARSET" != "" ]; then if [ "$MAIL_BODY_CHARSET" != "" ]; then
@ -757,33 +786,33 @@ function ParallelExec {
function ExecTasks { function ExecTasks {
# Mandatory arguments # Mandatory arguments
local mainInput="${1}" # Contains list of pids / commands separated by semicolons or filepath to list of pids / commands local mainInput="${1}" # Contains list of pids / commands separated by semicolons or filepath to list of pids / commands
# Optional arguments # Optional arguments
local id="${2:-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 local id="${2:-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
local readFromFile="${3:-false}" # Is mainInput / auxInput a semicolon separated list (true) or a filepath (false) local readFromFile="${3:-false}" # Is mainInput / auxInput a semicolon separated list (true) or a filepath (false)
local softPerProcessTime="${4:-0}" # Max time (in seconds) a pid or command can run before a warning is logged, unless set to 0 local softPerProcessTime="${4:-0}" # Max time (in seconds) a pid or command can run before a warning is logged, unless set to 0
local hardPerProcessTime="${5:-0}" # Max time (in seconds) a pid or command can run before the given command / pid is stopped, unless set to 0 local hardPerProcessTime="${5:-0}" # Max time (in seconds) a pid or command can run before the given command / pid is stopped, unless set to 0
local softMaxTime="${6:-0}" # Max time (in seconds) for the whole function to run before a warning is logged, unless set to 0 local softMaxTime="${6:-0}" # Max time (in seconds) for the whole function to run before a warning is logged, unless set to 0
local hardMaxTime="${7:-0}" # Max time (in seconds) for the whole function to run before all pids / commands given are stopped, unless set to 0 local hardMaxTime="${7:-0}" # Max time (in seconds) for the whole function to run before all pids / commands given are stopped, unless set to 0
local counting="${8:-true}" # Should softMaxTime and hardMaxTime be accounted since function begin (true) or since script begin (false) local counting="${8:-true}" # Should softMaxTime and hardMaxTime be accounted since function begin (true) or since script begin (false)
local sleepTime="${9:-.5}" # Seconds between each state check. The shorter the value, the snappier ExecTasks will be, but as a tradeoff, more cpu power will be used (good values are between .05 and 1) local sleepTime="${9:-.5}" # Seconds between each state check. The shorter the value, the snappier ExecTasks will be, but as a tradeoff, more cpu power will be used (good values are between .05 and 1)
local keepLogging="${10:-1800}" # Every keepLogging seconds, an alive message is logged. Setting this value to zero disables any alive logging local keepLogging="${10:-1800}" # Every keepLogging seconds, an alive message is logged. Setting this value to zero disables any alive logging
local spinner="${11:-true}" # Show spinner (true) or do not show anything (false) while running local spinner="${11:-true}" # Show spinner (true) or do not show anything (false) while running
local noTimeErrorLog="${12:-false}" # Log errors when reaching soft / hard execution times (false) or do not log errors on those triggers (true) local noTimeErrorLog="${12:-false}" # Log errors when reaching soft / hard execution times (false) or do not log errors on those triggers (true)
local noErrorLogsAtAll="${13:-false}" # Do not log any errros at all (useful for recursive ExecTasks checks) local noErrorLogsAtAll="${13:-false}" # Do not log any errros at all (useful for recursive ExecTasks checks)
# Parallelism specific arguments # Parallelism specific arguments
local numberOfProcesses="${14:-0}" # Number of simulanteous commands to run, given as mainInput. Set to 0 by default (WaitForTaskCompletion mode). Setting this value enables ParallelExec mode. local numberOfProcesses="${14:-0}" # Number of simulanteous commands to run, given as mainInput. Set to 0 by default (WaitForTaskCompletion mode). Setting this value enables ParallelExec mode.
local auxInput="${15}" # Contains list of commands separated by semicolons or filepath fo list of commands. Exit code of those commands decide whether main commands will be executed or not local auxInput="${15}" # Contains list of commands separated by semicolons or filepath fo list of commands. Exit code of those commands decide whether main commands will be executed or not
local maxPostponeRetries="${16:-3}" # If a conditional command fails, how many times shall we try to postpone the associated main command. Set this to 0 to disable postponing local maxPostponeRetries="${16:-3}" # If a conditional command fails, how many times shall we try to postpone the associated main command. Set this to 0 to disable postponing
local minTimeBetweenRetries="${17:-300}" # Time (in seconds) between postponed command retries 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 local validExitCodes="${18:-0}" # Semi colon separated list of valid main command exit codes which will not trigger errors
local i local i
Logger "${FUNCNAME[0]} called by [${FUNCNAME[0]} < ${FUNCNAME[1]} < ${FUNCNAME[2]} < ${FUNCNAME[3]} < ${FUNCNAME[4]} ...]." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG 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 __CheckArguments 1-18 $# "$@" #__WITH_PARANOIA_DEBUG
# Since ExecTasks takes up to 17 arguments, do a quick preflight check in DEBUG mode # Since ExecTasks takes up to 17 arguments, do a quick preflight check in DEBUG mode
if [ "$_DEBUG" == "yes" ]; then if [ "$_DEBUG" == "yes" ]; then
@ -806,40 +835,40 @@ function ExecTasks {
IFS=';' read -r -a validExitCodes <<< "$validExitCodes" IFS=';' read -r -a validExitCodes <<< "$validExitCodes"
# ParallelExec specific variables # ParallelExec specific variables
local auxItemCount=0 # Number of conditional commands local auxItemCount=0 # Number of conditional commands
local commandsArray=() # Array containing commands local commandsArray=() # Array containing commands
local commandsConditionArray=() # Array containing conditional commands local commandsConditionArray=() # Array containing conditional commands
local currentCommand # Variable containing currently processed command local currentCommand # Variable containing currently processed command
local currentCommandCondition # Variable containing currently processed conditional command local currentCommandCondition # Variable containing currently processed conditional command
local commandsArrayPid=() # Array containing pids of commands currently run local commandsArrayPid=() # Array containing pids of commands currently run
local postponedRetryCount=0 # Number of current postponed commands retries local postponedRetryCount=0 # Number of current postponed commands retries
local postponedItemCount=0 # Number of commands that have been postponed (keep at least one in order to check once) local postponedItemCount=0 # Number of commands that have been postponed (keep at least one in order to check once)
local postponedCounter=0 local postponedCounter=0
local isPostponedCommand=false # Is the current command from a postponed file ? local isPostponedCommand=false # Is the current command from a postponed file ?
local postponedExecTime=0 # How much time has passed since last postponed condition was checked local postponedExecTime=0 # How much time has passed since last postponed condition was checked
local needsPostponing # Does currentCommand need to be postponed local needsPostponing # Does currentCommand need to be postponed
local temp local temp
# Common variables # Common variables
local pid # Current pid working on local pid # Current pid working on
local pidState # State of the process local pidState # State of the process
local mainItemCount=0 # number of given items (pids or commands) local mainItemCount=0 # number of given items (pids or commands)
local readFromFile # Should we read pids / commands from a file (true) local readFromFile # Should we read pids / commands from a file (true)
local counter=0 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
local exec_time=0 # Seconds since the beginning of this function local exec_time=0 # Seconds since the beginning of this function
local retval=0 # return value of monitored pid process local retval=0 # return value of monitored pid process
local subRetval=0 # return value of condition commands local subRetval=0 # return value of condition commands
local errorcount=0 # Number of pids that finished with errors local errorcount=0 # Number of pids that finished with errors
local pidsArray # Array of currently running pids local pidsArray # Array of currently running pids
local newPidsArray # New array of currently running pids for next iteration local newPidsArray # New array of currently running pids for next iteration
local pidsTimeArray # Array containing execution begin time of pids local pidsTimeArray # Array containing execution begin time of pids
local executeCommand # Boolean to check if currentCommand can be executed given a condition 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 hasPids=false # Are any valable pids given to function ? #__WITH_PARANOIA_DEBUG
local functionMode local functionMode
@ -892,7 +921,7 @@ function ExecTasks {
counter=$mainItemCount counter=$mainItemCount
fi fi
Logger "Running ${FUNCNAME[0]} as [$functionMode] for [$mainItemCount] mainItems and [$auxItemCount] auxItems." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG Logger "Running ${FUNCNAME[0]} as [$functionMode] for [$mainItemCount] mainItems and [$auxItemCount] auxItems." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG
# soft / hard execution time checks that needs to be a subfunction since it is called both from main loop and from parallelExec sub loop # soft / hard execution time checks that needs to be a subfunction since it is called both from main loop and from parallelExec sub loop
function _ExecTasksTimeCheck { function _ExecTasksTimeCheck {
@ -1008,7 +1037,7 @@ function ExecTasks {
# Check for valid exit codes # Check for valid exit codes
if [ $(ArrayContains $retval "${validExitCodes[@]}") -eq 0 ]; then if [ $(ArrayContains $retval "${validExitCodes[@]}") -eq 0 ]; then
if [ $noErrorLogsAtAll != true ]; then if [ $noErrorLogsAtAll != true ]; then
Logger "${FUNCNAME[0]} called by [$id] finished monitoring pid [$pid] with exitcode [$retval]." "ERROR" Logger "${FUNCNAME[0]} called by [$id] finished monitoring pid [$pid] with exitcode [$retval]." "DEBUG"
if [ "$functionMode" == "ParallelExec" ]; then if [ "$functionMode" == "ParallelExec" ]; then
Logger "Command was [${commandsArrayPid[$pid]}]." "ERROR" Logger "Command was [${commandsArrayPid[$pid]}]." "ERROR"
fi fi
@ -1024,22 +1053,22 @@ function ExecTasks {
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]." "DEBUG"
fi fi
fi fi
hasPids=true ##__WITH_PARANOIA_DEBUG hasPids=true ##__WITH_PARANOIA_DEBUG
fi fi
done done
# hasPids can be false on last iteration in ParallelExec mode # hasPids can be false on last iteration in ParallelExec mode
if [ $hasPids == false ] && [ "$functionMode" = "WaitForTaskCompletion" ]; then ##__WITH_PARANOIA_DEBUG if [ $hasPids == false ] && [ "$functionMode" = "WaitForTaskCompletion" ]; then ##__WITH_PARANOIA_DEBUG
Logger "No valable pids given." "ERROR" ##__WITH_PARANOIA_DEBUG Logger "No valable pids given." "ERROR" ##__WITH_PARANOIA_DEBUG
fi ##__WITH_PARANOIA_DEBUG fi ##__WITH_PARANOIA_DEBUG
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
if [ "$_PERF_PROFILER" == "yes" ]; then ##__WITH_PARANOIA_DEBUG if [ "$_PERF_PROFILER" == "yes" ]; then ##__WITH_PARANOIA_DEBUG
_PerfProfiler ##__WITH_PARANOIA_DEBUG _PerfProfiler ##__WITH_PARANOIA_DEBUG
fi ##__WITH_PARANOIA_DEBUG fi ##__WITH_PARANOIA_DEBUG
} }
@ -1228,6 +1257,13 @@ function EscapeSpaces {
echo "${string// /\\ }" echo "${string// /\\ }"
} }
# Usage var=$(EscapeDoubleQuotes "$var") or var="$(EscapeDoubleQuotes "$var")"
function EscapeDoubleQuotes {
local value="${1}"
echo "${value//\"/\\\"}"
}
function IsNumericExpand { function IsNumericExpand {
eval "local value=\"${1}\"" # Needed eval so variable variables can be processed eval "local value=\"${1}\"" # Needed eval so variable variables can be processed
@ -1249,28 +1285,24 @@ function IsNumeric {
fi fi
} }
#### CheckRFC822 SUBSET ####
# Checks email address validity
function CheckRFC822 {
local mail="${1}"
local rfc822="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"
if [[ $mail =~ $rfc822 ]]; then
echo 1
else
echo 0
fi
}
#### CheckRFC822 SUBSET END ####
#### IsInteger SUBSET #### #### IsInteger SUBSET ####
# Function is busybox compatible since busybox ash does not understand direct regex, we use expr
function IsInteger { function IsInteger {
local value="${1}" local value="${1}"
if [[ $value =~ ^[0-9]+$ ]]; then if type expr > /dev/null 2>&1; then
echo 1 expr "$value" : "^[0-9]\+$" > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo 1
else
echo 0
fi
else else
echo 0 if [[ $value =~ ^[0-9]+$ ]]; then
echo 1
else
echo 0
fi
fi fi
} }
#### IsInteger SUBSET END #### #### IsInteger SUBSET END ####
@ -1308,13 +1340,29 @@ function HumanToNumeric {
} }
#### HumanToNumeric SUBSET END #### #### HumanToNumeric SUBSET END ####
#### CheckRFC822 SUBSET ####
# Checks email address validity
function CheckRFC822 {
local mail="${1}"
local rfc822="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"
if [[ $mail =~ $rfc822 ]]; then
echo 1
else
echo 0
fi
}
#### CheckRFC822 SUBSET END ####
#### UrlEncode SUBSET #### #### UrlEncode SUBSET ####
## from https://gist.github.com/cdown/1163649 ## Modified version of https://gist.github.com/cdown/1163649
function UrlEncode { function UrlEncode {
local length="${#1}" local length="${#1}"
local i
local LANG=C local LANG=C
for (( i = 0; i < length; i++ )); do for i in $(seq 0 $((length-1))); do
local c="${1:i:1}" local c="${1:i:1}"
case $c in case $c in
[a-zA-Z0-9.~_-]) [a-zA-Z0-9.~_-])
@ -1421,10 +1469,34 @@ function GetLocalOS {
if [ -f "/etc/os-release" ]; then if [ -f "/etc/os-release" ]; then
localOsName=$(GetConfFileValue "/etc/os-release" "NAME" true) localOsName=$(GetConfFileValue "/etc/os-release" "NAME" true)
localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION" true) localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION" true)
elif [ "$LOCAL_OS" == "BusyBox" ]; then
localOsVer=`ls --help 2>&1 | head -1 | cut -f2 -d' '`
localOsName="BusyBox"
fi fi
# Add a global variable for statistics in installer # Get Host info for Windows
LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer)" if [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "BusyBox" ] || [ "$LOCAL_OS" == "Cygwin" ] || [ "$LOCAL_OS" == "WinNT10" ]; then localOsVar="$(uname -a)"
if [ "$PROGRAMW6432" != "" ]; then
LOCAL_OS_BITNESS=64
LOCAL_OS_FAMILY="Windows"
elif [ "$PROGRAMFILES" != "" ]; then
LOCAL_OS_BITNESS=32
LOCAL_OS_FAMILY="Windows"
# Case where running on BusyBox but no program files defined
elif [ "$LOCAL_OS" == "BusyBox" ]; then
LOCAL_OS_FAMILY="Unix"
fi
# Get Host info for Unix
else
LOCAL_OS_FAMILY="Unix"
if uname -m | grep '64' > /dev/null 2>&1; then
LOCAL_OS_BITNESS=64
else
LOCAL_OS_BITNESS=32
fi
fi
LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer) $LOCAL_OS_BITNESS-bit $LOCAL_OS_FAMILY"
if [ "$_OFUNCTIONS_VERSION" != "" ]; then if [ "$_OFUNCTIONS_VERSION" != "" ]; then
Logger "Local OS: [$LOCAL_OS_FULL]." "DEBUG" Logger "Local OS: [$LOCAL_OS_FULL]." "DEBUG"
@ -1506,6 +1578,8 @@ function GetOs {
local localOsVar local localOsVar
local localOsName local localOsName
local localOsVer local localOsVer
local localOsBitness
local localOsFamily
local osInfo="/etc/os-release" local osInfo="/etc/os-release"
@ -1532,9 +1606,36 @@ function GetOs {
localOsName="${localOsName##*=}" localOsName="${localOsName##*=}"
localOsVer=$(grep "^VERSION=" "$osInfo") localOsVer=$(grep "^VERSION=" "$osInfo")
localOsVer="${localOsVer##*=}" localOsVer="${localOsVer##*=}"
elif [ "$localOsVar" == "BusyBox" ]; then
localOsVer=`ls --help 2>&1 | head -1 | cut -f2 -d' '`
localOsName="BusyBox"
fi fi
echo "$localOsVar ($localOsName $localOsVer)" # Get Host info for Windows
case $localOsVar in
*"MINGW32"*|*"MINGW64"*|*"MSYS"*|*"CYGWIN*"|*"Microsoft"*|*"WinNT10*")
if [ "$PROGRAMW6432" != "" ]; then
localOsBitness=64
localOsFamily="Windows"
elif [ "$PROGRAMFILES" != "" ]; then
localOsBitness=32
localOsFamily="Windows"
# Case where running on BusyBox but no program files defined
elif [ "$localOsVar" == "BusyBox" ]; then
localOsFamily="Unix"
fi
;;
*)
localOsFamily="Unix"
if uname -m | grep '64' > /dev/null 2>&1; then
localOsBitness=64
else
localOsBitness=32
fi
;;
esac
echo "$localOsVar ($localOsName $localOsVer) $localOsBitness-bit $localOsFamily"
} }
GetOs GetOs
@ -1542,6 +1643,9 @@ GetOs
ENDSSH ENDSSH
if [ $? != 0 ]; then if [ $? != 0 ]; then
Logger "Cannot connect to remote system [$REMOTE_HOST] port [$REMOTE_PORT]." "CRITICAL" Logger "Cannot connect to remote system [$REMOTE_HOST] port [$REMOTE_PORT]." "CRITICAL"
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" ]; then
Logger "$(cat "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP")" "ERROR"
fi
exit 1 exit 1
fi fi
@ -1960,7 +2064,7 @@ function InitLocalOSDependingSettings {
## Using mingw version of find instead of windows one ## Using mingw version of find instead of windows one
## Getting running processes is quite different ## Getting running processes is quite different
## Ping command is not the same ## Ping command is not the same
if [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then if [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ] || [ "$LOCAL_OS" == "Microsoft" ] || [ "$LOCAL_OS" == "WinNT10" ]; then
FIND_CMD=$(dirname $BASH)/find FIND_CMD=$(dirname $BASH)/find
PING_CMD='$SYSTEMROOT\system32\ping -n 2' PING_CMD='$SYSTEMROOT\system32\ping -n 2'