From f291611011ae9f28e9b010f6270b7dab4a60778a Mon Sep 17 00:00:00 2001 From: deajan Date: Tue, 14 Mar 2017 22:31:15 +0100 Subject: [PATCH] Rebuilt targets --- dev/debug_obackup.sh | 222 ++++++++++++++++++++++-------- install.sh | 317 +++++++++++++++++++++++++++---------------- obackup.sh | 220 ++++++++++++++++++++++-------- 3 files changed, 529 insertions(+), 230 deletions(-) diff --git a/dev/debug_obackup.sh b/dev/debug_obackup.sh index 181d5b1..535b248 100755 --- a/dev/debug_obackup.sh +++ b/dev/debug_obackup.sh @@ -6,12 +6,11 @@ PROGRAM="obackup" AUTHOR="(C) 2013-2017 by Orsiris de Jong" CONTACT="http://www.netpower.fr/obackup - ozy@netpower.fr" -PROGRAM_VERSION=2.1-beta1 -PROGRAM_BUILD=2017010305 +PROGRAM_VERSION=2.1-beta2 +PROGRAM_BUILD=2017021001 IS_STABLE=no -# Execution order #__WITH_PARANOIA_DEBUG - +#### Execution order #__WITH_PARANOIA_DEBUG # GetLocalOS #__WITH_PARANOIA_DEBUG # InitLocalOSDependingSettings #__WITH_PARANOIA_DEBUG # CheckRunningInstances #__WITH_PARANOIA_DEBUG @@ -36,9 +35,8 @@ IS_STABLE=no # FilesBackup #__WITH_PARANOIA_DEBUG - -_OFUNCTIONS_VERSION=2.1-RC1+dev -_OFUNCTIONS_BUILD=2017010401 +_OFUNCTIONS_VERSION=2.1-RC3+dev +_OFUNCTIONS_BUILD=2017031401 _OFUNCTIONS_BOOTSTRAP=true ## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr @@ -99,7 +97,7 @@ if [ "$SLEEP_TIME" == "" ]; then # Leave the possibity to set SLEEP_TIME as envi fi SCRIPT_PID=$$ -TSTAMP=$(date '+%Y%m%d%H%M%S%N') +TSTAMP=$(date '+%Y%m%dT%H%M%S.%N') LOCAL_USER=$(whoami) LOCAL_HOST=$(hostname) @@ -155,7 +153,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -164,7 +162,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -263,6 +261,10 @@ function Logger { prefix="" fi + ## Obfuscate _REMOTE_TOKEN in logs (for ssh_filter usage only in osync and obackup) + value="${value/env _REMOTE_TOKEN=$_REMOTE_TOKEN/__(o_O)__}" + value="${value/env _REMOTE_TOKEN=\$_REMOTE_TOKEN/__(o_O)__}" + if [ "$level" == "CRITICAL" ]; then _Logger "$prefix($level):$value" "$prefix\e[1;33;41m$value\e[0m" true ERROR_ALERT=true @@ -414,7 +416,12 @@ function SendAlert { attachment=true fi if [ -e "$RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID.$TSTAMP" ]; then - body="$MAIL_ALERT_MSG"$'\n\n'"$(cat $RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID.$TSTAMP)" + if [ "$MAIL_BODY_CHARSET" != "" ] && type iconv > /dev/null 2>&1; then + iconv -f UTF-8 -t $MAIL_BODY_CHARSET "$RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID.$TSTAMP" > "$RUN_DIR/$PROGRAM._Logger.iconv.$SCRIPT_PID.$TSTAMP" + body="$MAIL_ALERT_MSG"$'\n\n'"$(cat $RUN_DIR/$PROGRAM._Logger.iconv.$SCRIPT_PID.$TSTAMP)" + else + body="$MAIL_ALERT_MSG"$'\n\n'"$(cat $RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID.$TSTAMP)" + fi fi if [ $ERROR_ALERT == true ]; then @@ -1100,6 +1107,8 @@ function ArrayContains () { function GetLocalOS { local localOsVar + local localOsName + local localOsVer # There's 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 @@ -1160,8 +1169,14 @@ function GetLocalOS { Logger "Local OS: [$localOsVar]." "DEBUG" fi + # Get linux versions + if [ -f "/etc/os-release" ]; then + localOsName=$(GetConfFileValue "/etc/os-release" "NAME") + localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION") + fi + # Add a global variable for statistics in installer - LOCAL_OS_FULL="$localOsVar" + LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer)" } @@ -1174,10 +1189,12 @@ function GetRemoteOS { local remoteOsVar -$SSH_CMD bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 +$SSH_CMD env _REMOTE_TOKEN="$_REMOTE_TOKEN" bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 function GetOs { local localOsVar + local localOsName + local localOsVer # There's 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 @@ -1196,7 +1213,13 @@ function GetOs { fi fi fi - echo "$localOsVar" + # Get linux versions + if [ -f "/etc/os-release" ]; then + localOsName=$(GetConfFileValue "/etc/os-release" "NAME") + localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION") + fi + + echo "$localOsVar ($localOsName $localOsVer)" } GetOs @@ -1286,6 +1309,12 @@ function RunRemoteCommand { local hardMaxTime="${2}" # Max time to wait for command to compleet __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG + + if [ "$REMOTE_OPERATION" != "yes" ]; then + Logger "Ignoring remote command [$command] because remote host is not configured." "WARN" + return 0 + fi + CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost if [ $_DRYRUN == true ]; then @@ -1294,7 +1323,7 @@ function RunRemoteCommand { fi Logger "Running command [$command] on remote host." "NOTICE" - cmd=$SSH_CMD' "$command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1' + cmd=$SSH_CMD' "env _REMOTE_TOKEN="'$_REMOTE_TOKEN'" $command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1' Logger "cmd: $cmd" "DEBUG" eval "$cmd" & WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false @@ -1635,13 +1664,17 @@ function SetCompression { COMPRESSION_PROGRAM="| pigz -c$compressionString" COMPRESSION_EXTENSION=.gz # obackup specific - COMPRESSION_OPTIONS=--rsyncable + if [ "$LOCAL_OS" != "MacOSX" ]; then + COMPRESSION_OPTIONS=--rsyncable + fi elif type gzip > /dev/null 2>&1 then COMPRESSION_PROGRAM="| gzip -c$compressionString" COMPRESSION_EXTENSION=.gz # obackup specific - COMPRESSION_OPTIONS=--rsyncable + if [ "$LOCAL_OS" != "MacOSX" ]; then + COMPRESSION_OPTIONS=--rsyncable + fi else COMPRESSION_PROGRAM= COMPRESSION_EXTENSION= @@ -1660,6 +1693,11 @@ function InitLocalOSDependingSettings { if [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then FIND_CMD=$(dirname $BASH)/find PING_CMD='$SYSTEMROOT\system32\ping -n 2' + + # On BSD, when not root, min ping interval is 1s + elif [ "$LOCAL_OS" == "BSD" ] && [ "$LOCAL_USER" != "root" ]; then + FIND_CMD=find + PING_CMD="ping -c 2 -i 1" else FIND_CMD=find PING_CMD="ping -c 2 -i .2" @@ -1709,7 +1747,7 @@ function InitRemoteOSDependingSettings { fi ## Set rsync default arguments - RSYNC_ARGS="-rltD" + RSYNC_ARGS="-rltD -8" if [ "$_DRYRUN" == true ]; then RSYNC_DRY_ARG="-n" DRY_WARNING="/!\ DRY RUN " @@ -1804,6 +1842,68 @@ function ParentPid { fi } +# Neat version compare function found at http://stackoverflow.com/a/4025065/2635443 +# Returns 0 if equal, 1 if $1 > $2 and 2 if $1 < $2 +vercomp () { + if [[ $1 == $2 ]] + then + return 0 + fi + local IFS=. + local i ver1=($1) ver2=($2) + # fill empty fields in ver1 with zeros + for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) + do + ver1[i]=0 + done + for ((i=0; i<${#ver1[@]}; i++)) + do + if [[ -z ${ver2[i]} ]] + then + # fill empty fields in ver2 with zeros + ver2[i]=0 + fi + if ((10#${ver1[i]} > 10#${ver2[i]})) + then + return 1 + fi + if ((10#${ver1[i]} < 10#${ver2[i]})) + then + return 2 + fi + done + return 0 +} + +function GetConfFileValue () { + local file="${1}" + local name="${2}" + local value + + value=$(grep "^$name=" "$file") + if [ $? == 0 ]; then + value="${value##*=}" + echo "$value" + else + Logger "Cannot get value for [$name] in config file [$file]." "ERROR" + fi +} + +function SetConfFileValue () { + local file="${1}" + local name="${2}" + 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" + else + Logger "Cannot set value [$name] to [$value] in config file [$file]." "ERROR" + fi +} # If using "include" statements, make sure the script does not get executed unless it's loaded by bootstrap _OFUNCTIONS_BOOTSTRAP=true @@ -1913,6 +2013,11 @@ function CheckEnvironment { if [ "$ENCRYPTION" == "yes" ]; then CheckCryptEnvironnment fi + + if ! type pgrep > /dev/null 2>&1 ; then + Logger "pgrep not present. $0 cannot start." "CRITICAL" + exit 1 + fi } function CheckCryptEnvironnment { @@ -2030,7 +2135,7 @@ function _ListDatabasesLocal { Logger "Listing databases succeeded." "NOTICE" else Logger "Listing databases failed." "ERROR" - Logger "Command was [$sqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$sqlCmd]." "WARN" 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" fi @@ -2047,7 +2152,7 @@ function _ListDatabasesRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - sqlCmd="$SSH_CMD \"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" eval "$sqlCmd" & WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false @@ -2172,7 +2277,7 @@ function _ListRecursiveBackupDirectoriesLocal { retval=$? if [ $retval -ne 0 ]; then Logger "Could not enumerate directories in [$directory]." "ERROR" - Logger "Command was [$cmd]." "Warn" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" 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" fi @@ -2198,7 +2303,8 @@ function _ListRecursiveBackupDirectoriesRemote { local retval -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" \ env RECURSIVE_DIRECTORY_LIST="'$RECURSIVE_DIRECTORY_LIST'" env PATH_SEPARATOR_CHAR="'$PATH_SEPARATOR_CHAR'" \ env REMOTE_FIND_CMD="'$REMOTE_FIND_CMD'" $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" @@ -2239,7 +2345,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -2248,7 +2354,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -2455,14 +2561,14 @@ function _GetDirectoriesSizeLocal { retval=$? 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 "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" 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" fi if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then Logger "Error output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP)" "ERROR" fi - elsew + else Logger "File size fetched successfully." "NOTICE" fi @@ -2484,7 +2590,8 @@ function _GetDirectoriesSizeRemote { local retval # Error output is different from stdout because not all files in list may fail at once -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" dirList="'$dirList'" \ $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" & ## allow function call checks #__WITH_PARANOIA_DEBUG @@ -2524,7 +2631,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -2533,7 +2640,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -2683,7 +2790,8 @@ function _CreateDirectoryRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" \ env dirToCreate="'$dirToCreate'" $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 & ## allow function call checks #__WITH_PARANOIA_DEBUG @@ -2723,7 +2831,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -2732,7 +2840,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -2906,7 +3014,8 @@ function GetDiskSpaceRemote { local cmd local retval -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" \ env DF_CMD="'$DF_CMD'" \ env pathToCheck="'$pathToCheck'" $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" & @@ -2947,7 +3056,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -2956,7 +3065,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -3233,10 +3342,10 @@ function _BackupDatabaseLocalToLocal { retval=$? if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ $_DRYRUN == false ]; then - Logger "Command was [$sqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$sqlCmd]." "WARN" eval "$sqlCmd" & else - Logger "Command was [$drySqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$drySqlCmd]." "WARN" eval "$drySqlCmd" & fi Logger "Error output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP)" "ERROR" @@ -3269,7 +3378,7 @@ function _BackupDatabaseLocalToRemote { fi local drySqlCmd="mysqldump -u $SQL_USER $exportOptions --databases $database $COMPRESSION_PROGRAM $COMPRESSION_OPTIONS $encryptOptions > /dev/null 2> $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" - local sqlCmd="mysqldump -u $SQL_USER $exportOptions --databases $database $COMPRESSION_PROGRAM $COMPRESSION_OPTIONS $encryptOptions | $SSH_CMD '$COMMAND_SUDO tee \"$SQL_STORAGE/$database.sql$COMPRESSION_EXTENSION$encryptExtension\" > /dev/null' 2> $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" + local sqlCmd="mysqldump -u $SQL_USER $exportOptions --databases $database $COMPRESSION_PROGRAM $COMPRESSION_OPTIONS $encryptOptions | $SSH_CMD 'env _REMOTE_TOKEN=$_REMOTE_TOKEN $COMMAND_SUDO tee \"$SQL_STORAGE/$database.sql$COMPRESSION_EXTENSION$encryptExtension\" > /dev/null' 2> $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" if [ $_DRYRUN == false ]; then Logger "Launching command [$sqlCmd]." "DEBUG" @@ -3282,10 +3391,10 @@ function _BackupDatabaseLocalToRemote { retval=$? if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ $_DRYRUN == false ]; then - Logger "Command was [$sqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$sqlCmd]." "WARN" eval "$sqlCmd" & else - Logger "Command was [$drySqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$drySqlCmd]." "WARN" eval "$drySqlCmd" & fi Logger "Error output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP)" "ERROR" @@ -3317,8 +3426,8 @@ function _BackupDatabaseRemoteToLocal { encryptExtension="$CRYPT_FILE_EXTENSION" fi - local drySqlCmd=$SSH_CMD' "mysqldump -u '$SQL_USER' '$exportOptions' --databases '$database' '$COMPRESSION_PROGRAM' '$COMPRESSION_OPTIONS' '$encryptOptions'" > /dev/null 2> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP'"' - local sqlCmd=$SSH_CMD' "mysqldump -u '$SQL_USER' '$exportOptions' --databases '$database' '$COMPRESSION_PROGRAM' '$COMPRESSION_OPTIONS' '$encryptOptions'" > "'$SQL_STORAGE/$database.sql$COMPRESSION_EXTENSION$encryptExtension'" 2> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP'"' + local drySqlCmd=$SSH_CMD' "env _REMOTE_TOKEN=$_REMOTE_TOKEN mysqldump -u '$SQL_USER' '$exportOptions' --databases '$database' '$COMPRESSION_PROGRAM' '$COMPRESSION_OPTIONS' '$encryptOptions'" > /dev/null 2> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP'"' + local sqlCmd=$SSH_CMD' "env _REMOTE_TOKEN=$_REMOTE_TOKEN mysqldump -u '$SQL_USER' '$exportOptions' --databases '$database' '$COMPRESSION_PROGRAM' '$COMPRESSION_OPTIONS' '$encryptOptions'" > "'$SQL_STORAGE/$database.sql$COMPRESSION_EXTENSION$encryptExtension'" 2> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP'"' if [ $_DRYRUN == false ]; then Logger "Launching command [$sqlCmd]." "DEBUG" @@ -3331,10 +3440,10 @@ function _BackupDatabaseRemoteToLocal { retval=$? if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ $_DRYRUN == false ]; then - Logger "Command was [$sqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$sqlCmd]." "WARN" eval "$sqlCmd" & else - Logger "Command was [$drySqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$drySqlCmd]." "WARN" eval "$drySqlCmd" & fi Logger "Error output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP)" "ERROR" @@ -3474,7 +3583,7 @@ function EncryptFiles { ParallelExec $PARALLEL_ENCRYPTION_PROCESSES "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.parallel.$SCRIPT_PID.$TSTAMP" true $softMaxExecTime $hardMaxExecTime $SLEEP_TIME $KEEP_LOGGING true true false retval=$? if [ $retval -ne 0 ]; then - Logger "Encryption error.." "ERROR" + Logger "Encryption error." "ERROR" # Output file is defined in ParallelExec Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.ParallelExec.EncryptFiles.$SCRIPT_PID.$TSTAMP)" "DEBUG" fi @@ -3630,13 +3739,13 @@ function Rsync { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost sourceDir=$(EscapeSpaces "$sourceDir") - rsyncCmd="$(type -p $RSYNC_EXECUTABLE) $RSYNC_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $RSYNC_NO_RECURSE_ARGS $RSYNC_DELETE $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --rsync-path=\"$RSYNC_PATH\" -e \"$RSYNC_SSH_CMD\" \"$REMOTE_USER@$REMOTE_HOST:$sourceDir\" \"$destinationDir\" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" + rsyncCmd="$(type -p $RSYNC_EXECUTABLE) $RSYNC_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $RSYNC_NO_RECURSE_ARGS $RSYNC_DELETE $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --rsync-path=\"env _REMOTE_TOKEN=$_REMOTE_TOKEN $RSYNC_PATH\" -e \"$RSYNC_SSH_CMD\" \"$REMOTE_USER@$REMOTE_HOST:$sourceDir\" \"$destinationDir\" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" elif [ "$BACKUP_TYPE" == "push" ]; then destinationDir=$(EscapeSpaces "$destinationDir") _CreateDirectoryRemote "$destinationDir" CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - rsyncCmd="$(type -p $RSYNC_EXECUTABLE) $RSYNC_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $RSYNC_NO_RECURSE_ARGS $RSYNC_DELETE $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --rsync-path=\"$RSYNC_PATH\" -e \"$RSYNC_SSH_CMD\" \"$sourceDir\" \"$REMOTE_USER@$REMOTE_HOST:$destinationDir\" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" + rsyncCmd="$(type -p $RSYNC_EXECUTABLE) $RSYNC_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $RSYNC_NO_RECURSE_ARGS $RSYNC_DELETE $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --rsync-path=\"env _REMOTE_TOKEN=$_REMOTE_TOKEN $RSYNC_PATH\" -e \"$RSYNC_SSH_CMD\" \"$sourceDir\" \"$REMOTE_USER@$REMOTE_HOST:$destinationDir\" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" fi Logger "Launching command [$rsyncCmd]." "DEBUG" @@ -3645,7 +3754,7 @@ function Rsync { retval=$? if [ $retval -ne 0 ]; then Logger "Failed to backup [$sourceDir] to [$destinationDir]." "ERROR" - Logger "Command was [$rsyncCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$rsyncCmd]." "WARN" Logger "Command output:\n $(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "ERROR" else Logger "File backup succeed." "NOTICE" @@ -3794,7 +3903,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot delete oldest copy [$path]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi fi fi @@ -3807,7 +3916,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot move [$path] to [$backup.$PROGRAM.$copy]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi fi @@ -3822,7 +3931,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot move [$backup] to [$backup.$PROGRAM.1]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi elif [ "$REMOTE_OPERATION" == "yes" ]; then @@ -3832,7 +3941,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot copy [$backup] to [$backup.$PROGRAM.1]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi else @@ -3842,7 +3951,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot move [$backup] to [$backup.$PROGRAM.1]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi fi done @@ -3853,7 +3962,8 @@ function _RotateBackupsRemote { local rotateCopies="${2}" __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" \ env REMOTE_FIND_CMD="'$REMOTE_FIND_CMD'" env rotateCopies="'$rotateCopies'" env backupPath="'$backupPath'" \ $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" @@ -3894,7 +4004,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -3903,7 +4013,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") diff --git a/install.sh b/install.sh index 69aa57a..d7947a5 100755 --- a/install.sh +++ b/install.sh @@ -1,12 +1,18 @@ #!/usr/bin/env bash +## Installer script suitable for osync / obackup / pmocr + _OFUNCTIONS_BOOTSTRAP=true -PROGRAM=obackup -PROGRAM_VERSION=2.1-beta1 +PROGRAM=osync + +PROGRAM_VERSION=$(grep "PROGRAM_VERSION=" $PROGRAM.sh) +PROGRAM_VERSION=${PROGRAM_VERSION#*=} PROGRAM_BINARY=$PROGRAM".sh" PROGRAM_BATCH=$PROGRAM"-batch.sh" -SCRIPT_BUILD=2016122701 +SSH_FILTER="ssh_filter.sh" + +SCRIPT_BUILD=2017031401 ## osync / obackup / pmocr / zsnap install script ## Tested on RHEL / CentOS 6 & 7, Fedora 23, Debian 7 & 8, Mint 17 and FreeBSD 8, 10 and 11 @@ -22,19 +28,20 @@ SERVICE_DIR_INIT=$FAKEROOT/etc/init.d SERVICE_DIR_SYSTEMD_SYSTEM=$FAKEROOT/lib/systemd/system SERVICE_DIR_SYSTEMD_USER=$FAKEROOT/etc/systemd/user -## osync specific code -OSYNC_SERVICE_FILE_INIT="osync-srv" -OSYNC_SERVICE_FILE_SYSTEMD_SYSTEM="osync-srv@.service" -OSYNC_SERVICE_FILE_SYSTEMD_USER="osync-srv@.service.user" +if [ "$PROGRAM" == "osync" ]; then + SERVICE_NAME="osync-srv" +elif [ "$PROGRAM" == "pmocr" ]; then + SERVICE_NAME="pmocr-srv" +fi -## pmocr specfic code -PMOCR_SERVICE_FILE_INIT="pmocr-srv" -PMOCR_SERVICE_FILE_SYSTEMD_SYSTEM="pmocr-srv@.service" +SERVICE_FILE_INIT="$SERVICE_NAME" +SERVICE_FILE_SYSTEMD_SYSTEM="$SERVICE_NAME@.service" +SERVICE_FILE_SYSTEMD_USER="$SERVICE_NAME@.service.user" ## Generic code ## Default log file -if [ -w $FAKEROOT/var/log ]; then +if [ -w "$FAKEROOT/var/log" ]; then LOG_FILE="$FAKEROOT/var/log/$PROGRAM-install.log" elif ([ "$HOME" != "" ] && [ -w "$HOME" ]); then LOG_FILE="$HOME/$PROGRAM-install.log" @@ -83,6 +90,8 @@ function UrlEncode { } function GetLocalOS { local localOsVar + local localOsName + local localOsVer # There's 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 @@ -143,9 +152,29 @@ function GetLocalOS { Logger "Local OS: [$localOsVar]." "DEBUG" fi + # Get linux versions + if [ -f "/etc/os-release" ]; then + localOsName=$(GetConfFileValue "/etc/os-release" "NAME") + localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION") + fi + # Add a global variable for statistics in installer - LOCAL_OS_FULL="$localOsVar" + LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer)" } +function GetConfFileValue () { + local file="${1}" + local name="${2}" + local value + + value=$(grep "^$name=" "$file") + if [ $? == 0 ]; then + value="${value##*=}" + echo "$value" + else + Logger "Cannot get value for [$name] in config file [$file]." "ERROR" + fi +} + function SetLocalOSSettings { USER=root @@ -167,7 +196,7 @@ function SetLocalOSSettings { ;; esac - if [ "$LOCAL_OS" == "Android" ] || [ "$LOCAL_OS" == "MacOSX" ] || [ "$LOCAL_OS" == "BusyBox" ]; then + if [ "$LOCAL_OS" == "Android" ] || [ "$LOCAL_OS" == "BusyBox" ]; then QuickLogger "Cannot be installed on [$LOCAL_OS]. Please use $PROGRAM.sh directly." exit 1 fi @@ -193,126 +222,129 @@ function GetInit { fi } -function CreateConfDir { - if [ ! -d "$CONF_DIR" ]; then - mkdir "$CONF_DIR" +function CreateDir { + local dir="${1}" + + if [ ! -d "$dir" ]; then + mkdir "$dir" if [ $? == 0 ]; then - QuickLogger "Created directory [$CONF_DIR]." + QuickLogger "Created directory [$dir]." else - QuickLogger "Cannot create directory [$CONF_DIR]." + QuickLogger "Cannot create directory [$dir]." exit 1 fi + fi +} + +function CopyFile { + local sourcePath="${1}" + local destPath="${2}" + local fileName="${3}" + local fileMod="${4}" + local fileUser="${5}" + local fileGroup="${6}" + local overwrite="${7:-false}" + + local userGroup="" + local oldFileName + + if [ -f "$destPath/$fileName" ] && [ $overwrite == false ]; then + oldFileName="$fileName" + fileName="$oldFileName.new" + cp "$sourcePath/$oldFileName" "$destPath/$fileName" else - QuickLogger "Config directory [$CONF_DIR] exists." + cp "$sourcePath/$fileName" "$destPath" + fi + + if [ $? != 0 ]; then + QuickLogger "Cannot copy [$fileName] to [$destPath]. Make sure to run install script in the directory containing all other files." + QuickLogger "Also make sure you have permissions to write to [$BIN_DIR]." + exit 1 + else + QuickLogger "Copied [$fileName] to [$destPath]." + if [ "$fileMod" != "" ]; then + chmod "$fileMod" "$destPath/$fileName" + if [ $? != 0 ]; then + QuickLogger "Cannot set file permissions of [$destPath/$fileName] to [$fileMod]." + exit 1 + else + QuickLogger "Set file permissions to [$fileMod] on [$destPath/$fileName]." + fi + fi + + if [ "$fileUser" != "" ]; then + userGroup="$fileUser" + + if [ "$fileGroup" != "" ]; then + userGroup="$userGroup"":$fileGroup" + fi + + chown "$userGroup" "$destPath/$fileName" + if [ $? != 0 ]; then + QuickLogger "Could not set file ownership on [$destPath/$fileName] to [$userGroup]." + exit 1 + else + QuickLogger "Set file ownership on [$destPath/$fileName] to [$userGroup]." + fi + fi fi } function CopyExampleFiles { - if [ -f "$SCRIPT_PATH/sync.conf.example" ]; then - cp "$SCRIPT_PATH/sync.conf.example" "$CONF_DIR/sync.conf.example" - fi + exampleFiles=() + exampleFiles[0]="sync.conf.example" # osync + exampleFiles[1]="host_backup.conf.example" # obackup + exampleFiles[2]="exclude.list.example" # osync & obackup + exampleFiles[3]="snapshot.conf.example" # zsnap + exampleFiles[4]="default.conf" # pmocr - if [ -f "$SCRIPT_PATH/host_backup.conf.example" ]; then - cp "$SCRIPT_PATH/host_backup.conf.example" "$CONF_DIR/host_backup.conf.example" - fi - - if [ -f "$SCRIPT_PATH/exlude.list.example" ]; then - cp "$SCRIPT_PATH/exclude.list.example" "$CONF_DIR/exclude.list.example" - fi - - if [ -f "$SCRIPT_PATH/snapshot.conf.example" ]; then - cp "$SCRIPT_PATH/snapshot.conf.example" "$CONF_DIR/snapshot.conf.example" - fi - - if [ -f "$SCRIPT_PATH/default.conf" ]; then - if [ -f "$CONF_DIR/default.conf" ]; then - cp "$SCRIPT_PATH/default.conf" "$CONF_DIR/default.conf.new" - QuickLogger "Copied default.conf to [$CONF_DIR/default.conf.new]." - else - cp "$SCRIPT_PATH/default.conf" "$CONF_DIR/default.conf" + for file in "${exampleFiles[@]}"; do + if [ -f "$SCRIPT_PATH/$file" ]; then + CopyFile "$SCRIPT_PATH" "$CONF_DIR" "$file" "" "" "" false fi - fi + done } function CopyProgram { - cp "$SCRIPT_PATH/$PROGRAM_BINARY" "$BIN_DIR" - if [ $? != 0 ]; then - QuickLogger "Cannot copy $PROGRAM_BINARY to [$BIN_DIR]. Make sure to run install script in the directory containing all other files." - QuickLogger "Also make sure you have permissions to write to [$BIN_DIR]." - exit 1 - else - chmod 755 "$BIN_DIR/$PROGRAM_BINARY" - QuickLogger "Copied $PROGRAM_BINARY to [$BIN_DIR]." + binFiles=() + binFiles[0]="$PROGRAM_BINARY" + if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then + binFiles[1]="$PROGRAM_BATCH" + binFiles[2]="$SSH_FILTER" fi - if [ -f "$SCRIPT_PATH/$PROGRAM_BATCH" ]; then - cp "$SCRIPT_PATH/$PROGRAM_BATCH" "$BIN_DIR" - if [ $? != 0 ]; then - QuickLogger "Cannot copy $PROGRAM_BATCH to [$BIN_DIR]." - else - chmod 755 "$BIN_DIR/$PROGRAM_BATCH" - QuickLogger "Copied $PROGRAM_BATCH to [$BIN_DIR]." - fi + local user="" + local group="" + + if ([ "$USER" != "" ] && [ "$FAKEROOT" == "" ]); then + user="$USER" + fi + if ([ "$GROUP" != "" ] && [ "$FAKEROOT" == "" ]); then + group="$GROUP" fi - if [ -f "$SCRIPT_PATH/ssh_filter.sh" ]; then - cp "$SCRIPT_PATH/ssh_filter.sh" "$BIN_DIR" - if [ $? != 0 ]; then - QuickLogger "Cannot copy ssh_filter.sh to [$BIN_DIR]." - else - chmod 755 "$BIN_DIR/ssh_filter.sh" - if ([ "$USER" != "" ] && [ "$GROUP" != "" ] && [ "$FAKEROOT" == "" ]); then - chown $USER:$GROUP "$BIN_DIR/ssh_filter.sh" - fi - QuickLogger "Copied ssh_filter.sh to [$BIN_DIR]." - fi - fi + for file in "${binFiles[@]}"; do + CopyFile "$SCRIPT_PATH" "$BIN_DIR" "$file" 755 "$user" "$group" true + done } function CopyServiceFiles { - # OSYNC SPECIFIC - if ([ "$init" == "systemd" ] && [ -f "$SCRIPT_PATH/$OSYNC_SERVICE_FILE_SYSTEMD_SYSTEM" ]); then - cp "$SCRIPT_PATH/$OSYNC_SERVICE_FILE_SYSTEMD_SYSTEM" "$SERVICE_DIR_SYSTEMD_SYSTEM" && cp "$SCRIPT_PATH/$OSYNC_SERVICE_FILE_SYSTEMD_USER" "$SERVICE_DIR_SYSTEMD_USER/$SERVICE_FILE_SYSTEMD_SYSTEM" - if [ $? != 0 ]; then - QuickLogger "Cannot copy the systemd file to [$SERVICE_DIR_SYSTEMD_SYSTEM] or [$SERVICE_DIR_SYSTEMD_USER]." - else - QuickLogger "Created osync-srv service in [$SERVICE_DIR_SYSTEMD_SYSTEM] and [$SERVICE_DIR_SYSTEMD_USER]." - QuickLogger "Can be activated with [systemctl start osync-srv@instance.conf] where instance.conf is the name of the config file in $CONF_DIR." - QuickLogger "Can be enabled on boot with [systemctl enable osync-srv@instance.conf]." - QuickLogger "In userland, active with [systemctl --user start osync-srv@instance.conf]." - fi - elif ([ "$init" == "initV" ] && [ -f "$SCRIPT_PATH/$OSYNC_SERVICE_FILE_INIT" ]); then - cp "$SCRIPT_PATH/$OSYNC_SERVICE_FILE_INIT" "$SERVICE_DIR_INIT" - if [ $? != 0 ]; then - QuickLogger "Cannot copy osync-srv to [$SERVICE_DIR_INIT]." - else - chmod 755 "$SERVICE_DIR_INIT/$OSYNC_SERVICE_FILE_INIT" - QuickLogger "Created osync-srv service in [$SERVICE_DIR_INIT]." - QuickLogger "Can be activated with [service $OSYNC_SERVICE_FILE_INIT start]." - QuickLogger "Can be enabled on boot with [chkconfig $OSYNC_SERVICE_FILE_INIT on]." - fi - fi + if ([ "$init" == "systemd" ] && [ -f "$SCRIPT_PATH/$SERVICE_FILE_SYSTEMD_SYSTEM" ]); then + CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_SYSTEMD_SYSTEM" "$SERVICE_FILE_SYSTEMD_SYSTEM" "" "" "" true + CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_SYSTEMD_USER" "$SERVICE_FILE_SYSTEMD_USER" "" "" "" true - # PMOCR SPECIFIC - if ([ "$init" == "systemd" ] && [ -f "$SCRIPT_PATH/$PMOCR_SERVICE_FILE_SYSTEMD_SYSTEM" ]); then - cp "$SCRIPT_PATH/$PMOCR_SERVICE_FILE_SYSTEMD_SYSTEM" "$SERVICE_DIR_SYSTEMD_SYSTEM" - if [ $? != 0 ]; then - QuickLogger "Cannot copy the systemd file to [$SERVICE_DIR_SYSTEMD_SYSTEM] or [$SERVICE_DIR_SYSTEMD_USER]." - else - QuickLogger "Created pmocr-srv service in [$SERVICE_DIR_SYSTEMD_SYSTEM] and [$SERVICE_DIR_SYSTEMD_USER]." - QuickLogger "Can be activated with [systemctl start pmocr-srv@default.conf] where default.conf is the name of the config file in $CONF_DIR." - QuickLogger "Can be enabled on boot with [systemctl enable pmocr-srv@default.conf]." - fi - elif ([ "$init" == "initV" ] && [ -f "$SCRIPT_PATH/$PMOCR_SERVICE_FILE_INIT" ]); then - cp "$SCRIPT_PATH/$PMOCR_SERVICE_FILE_INIT" "$SERVICE_DIR_INIT" - if [ $? != 0 ]; then - QuickLogger "Cannot copy pmoct-srv to [$SERVICE_DIR_INIT]." - else - chmod 755 "$SERVICE_DIR_INIT/$PMOCR_SERVICE_FILE_INIT" - QuickLogger "Created osync-srv service in [$SERVICE_DIR_INIT]." - QuickLogger "Can be activated with [service $PMOCR_SERVICE_FILE_INIT start]." - QuickLogger "Can be enabled on boot with [chkconfig $PMOCR_SERVICE_FILE_INIT on]." - fi + QuickLogger "Created [$SERVICE_NAME] service in [$SERVICE_DIR_SYSTEMD_SYSTEM] and [$SERVICE_DIR_SYSTEMD_USER]." + QuickLogger "Can be activated with [systemctl start SERVICE_NAME@instance.conf] where instance.conf is the name of the config file in $CONF_DIR." + QuickLogger "Can be enabled on boot with [systemctl enable $SERVICE_NAME@instance.conf]." + QuickLogger "In userland, active with [systemctl --user start $SERVICE_NAME@instance.conf]." + elif ([ "$init" == "initV" ] && [ -f "$SCRIPT_PATH/$SERVICE_FILE_INIT" ] && [ -d "$SERVICE_DIR_INIT" ]); then + CopyFile "$SCRIPT_PATH" "$SERVICE_DIR_INIT" "$SERVICE_FILE_INIT" "755" "" "" true + + QuickLogger "Created osync-srv service in [$SERVICE_DIR_INIT]." + QuickLogger "Can be activated with [service $OSYNC_SERVICE_FILE_INIT start]." + QuickLogger "Can be enabled on boot with [chkconfig $OSYNC_SERVICE_FILE_INIT on]." + else + QuickLogger "Cannot define what init style is in use on this system. Skipping service file installation." fi } @@ -335,6 +367,36 @@ function Statistics { return 1 } +function RemoveFile { + local file="${1}" + + if [ -f "$file" ]; then + rm -f "$file" + if [ $? != 0 ]; then + QuickLogger "Could not remove file [$file]." + else + QuickLogger "Removed file [$file]." + fi + else + QuickLogger "File [$file] not found. Skipping." + fi +} + +function RemoveAll { + RemoveFile "$BIN_DIR/$PROGRAM_BINARY" + RemoveFile "$BIN_DIR/$PROGRAM_BATCH" + if [ ! -f "$BIN_DIR/osync.sh" ] && [ ! -f "$BIN_DIR/obackup.sh" ]; then # Check if any other program requiring ssh filter is present before removal + RemoveFile "$BIN_DIR/$SSH_FILTER" + else + QuickLogger "Skipping removal of [$BIN_DIR/$SSH_FILTER] because other programs present that need it." + fi + RemoveFile "$SERVICE_DIR_SYSTEMD_SYSTEM/$SERVICE_FILE_SYSTEMD_SYSTEM" + RemoveFile "$SERVICE_DIR_SYSTEMD_USER/$SERVICE_FILE_SYSTEMD_SYSTEM" + RemoveFile "$SERVICE_DIR_INIT/$SERVICE_FILE_INIT" + + QuickLogger "Skipping configuration files in [$CONF_DIR]. You may remove this directory manually." +} + function Usage { echo "Installs $PROGRAM into $BIN_DIR" echo "options:" @@ -345,6 +407,8 @@ function Usage { _LOGGER_SILENT=false _STATS=1 +ACTION="install" + for i in "$@" do case $i in @@ -354,6 +418,9 @@ do --no-stats) _STATS=0 ;; + --remove) + ACTION="uninstall" + ;; --help|-h|-?) Usage esac @@ -365,21 +432,33 @@ fi GetLocalOS SetLocalOSSettings -CreateConfDir -CopyExampleFiles -CopyProgram GetInit -CopyServiceFiles -STATS_LINK="http://instcount.netpower.fr?program=$PROGRAM&version=$PROGRAM_VERSION&os=$OS" +STATS_LINK="http://instcount.netpower.fr?program=$PROGRAM&version=$PROGRAM_VERSION&os=$OS&action=$ACTION" + +if [ "$ACTION" == "uninstall" ]; then + RemoveAll + QuickLogger "$PROGRAM uninstalled." +else + CreateDir "$CONF_DIR" + CreateDir "$BIN_DIR" + CopyExampleFiles + CopyProgram + CopyServiceFiles + QuickLogger "$PROGRAM installed. Use with $BIN_DIR/$PROGRAM" + if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then + QuickLogger "" + QuickLogger "If connecting remotely, consider setup ssh filter to enhance security." + QuickLogger "" + fi +fi -QuickLogger "$PROGRAM installed. Use with $BIN_DIR/$PROGRAM" if [ $_STATS -eq 1 ]; then if [ $_LOGGER_SILENT == true ]; then Statistics else - QuickLogger "In order to make install statistics, the script would like to connect to $STATS_LINK" - read -r -p "No data except those in the url will be send. Allow [Y/n]" response + QuickLogger "In order to make usage statistics, the script would like to connect to $STATS_LINK" + read -r -p "No data except those in the url will be send. Allow [Y/n] " response case $response in [nN]) exit diff --git a/obackup.sh b/obackup.sh index 1814e80..6fefb74 100755 --- a/obackup.sh +++ b/obackup.sh @@ -6,16 +6,14 @@ PROGRAM="obackup" AUTHOR="(C) 2013-2017 by Orsiris de Jong" CONTACT="http://www.netpower.fr/obackup - ozy@netpower.fr" -PROGRAM_VERSION=2.1-beta1 -PROGRAM_BUILD=2017010305 +PROGRAM_VERSION=2.1-beta2 +PROGRAM_BUILD=2017021001 IS_STABLE=no - - -_OFUNCTIONS_VERSION=2.1-RC1+dev -_OFUNCTIONS_BUILD=2017010401 +_OFUNCTIONS_VERSION=2.1-RC3+dev +_OFUNCTIONS_BUILD=2017031401 _OFUNCTIONS_BOOTSTRAP=true ## BEGIN Generic bash functions written in 2013-2017 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr @@ -72,7 +70,7 @@ if [ "$SLEEP_TIME" == "" ]; then # Leave the possibity to set SLEEP_TIME as envi fi SCRIPT_PID=$$ -TSTAMP=$(date '+%Y%m%d%H%M%S%N') +TSTAMP=$(date '+%Y%m%dT%H%M%S.%N') LOCAL_USER=$(whoami) LOCAL_HOST=$(hostname) @@ -127,7 +125,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -136,7 +134,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -230,6 +228,10 @@ function Logger { prefix="" fi + ## Obfuscate _REMOTE_TOKEN in logs (for ssh_filter usage only in osync and obackup) + value="${value/env _REMOTE_TOKEN=$_REMOTE_TOKEN/__(o_O)__}" + value="${value/env _REMOTE_TOKEN=\$_REMOTE_TOKEN/__(o_O)__}" + if [ "$level" == "CRITICAL" ]; then _Logger "$prefix($level):$value" "$prefix\e[1;33;41m$value\e[0m" true ERROR_ALERT=true @@ -373,7 +375,12 @@ function SendAlert { attachment=true fi if [ -e "$RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID.$TSTAMP" ]; then - body="$MAIL_ALERT_MSG"$'\n\n'"$(cat $RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID.$TSTAMP)" + if [ "$MAIL_BODY_CHARSET" != "" ] && type iconv > /dev/null 2>&1; then + iconv -f UTF-8 -t $MAIL_BODY_CHARSET "$RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID.$TSTAMP" > "$RUN_DIR/$PROGRAM._Logger.iconv.$SCRIPT_PID.$TSTAMP" + body="$MAIL_ALERT_MSG"$'\n\n'"$(cat $RUN_DIR/$PROGRAM._Logger.iconv.$SCRIPT_PID.$TSTAMP)" + else + body="$MAIL_ALERT_MSG"$'\n\n'"$(cat $RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID.$TSTAMP)" + fi fi if [ $ERROR_ALERT == true ]; then @@ -1042,6 +1049,8 @@ function ArrayContains () { function GetLocalOS { local localOsVar + local localOsName + local localOsVer # There's 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 @@ -1102,8 +1111,14 @@ function GetLocalOS { Logger "Local OS: [$localOsVar]." "DEBUG" fi + # Get linux versions + if [ -f "/etc/os-release" ]; then + localOsName=$(GetConfFileValue "/etc/os-release" "NAME") + localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION") + fi + # Add a global variable for statistics in installer - LOCAL_OS_FULL="$localOsVar" + LOCAL_OS_FULL="$localOsVar ($localOsName $localOsVer)" } @@ -1115,10 +1130,12 @@ function GetRemoteOS { local remoteOsVar -$SSH_CMD bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 +$SSH_CMD env _REMOTE_TOKEN="$_REMOTE_TOKEN" bash -s << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 function GetOs { local localOsVar + local localOsName + local localOsVer # There's 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 @@ -1137,7 +1154,13 @@ function GetOs { fi fi fi - echo "$localOsVar" + # Get linux versions + if [ -f "/etc/os-release" ]; then + localOsName=$(GetConfFileValue "/etc/os-release" "NAME") + localOsVer=$(GetConfFileValue "/etc/os-release" "VERSION") + fi + + echo "$localOsVar ($localOsName $localOsVer)" } GetOs @@ -1225,6 +1248,12 @@ function RunRemoteCommand { local command="${1}" # Command to run local hardMaxTime="${2}" # Max time to wait for command to compleet + + if [ "$REMOTE_OPERATION" != "yes" ]; then + Logger "Ignoring remote command [$command] because remote host is not configured." "WARN" + return 0 + fi + CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost if [ $_DRYRUN == true ]; then @@ -1233,7 +1262,7 @@ function RunRemoteCommand { fi Logger "Running command [$command] on remote host." "NOTICE" - cmd=$SSH_CMD' "$command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1' + cmd=$SSH_CMD' "env _REMOTE_TOKEN="'$_REMOTE_TOKEN'" $command" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP'" 2>&1' Logger "cmd: $cmd" "DEBUG" eval "$cmd" & WaitForTaskCompletion $! 0 $hardMaxTime $SLEEP_TIME $KEEP_LOGGING true true false @@ -1506,13 +1535,17 @@ function SetCompression { COMPRESSION_PROGRAM="| pigz -c$compressionString" COMPRESSION_EXTENSION=.gz # obackup specific - COMPRESSION_OPTIONS=--rsyncable + if [ "$LOCAL_OS" != "MacOSX" ]; then + COMPRESSION_OPTIONS=--rsyncable + fi elif type gzip > /dev/null 2>&1 then COMPRESSION_PROGRAM="| gzip -c$compressionString" COMPRESSION_EXTENSION=.gz # obackup specific - COMPRESSION_OPTIONS=--rsyncable + if [ "$LOCAL_OS" != "MacOSX" ]; then + COMPRESSION_OPTIONS=--rsyncable + fi else COMPRESSION_PROGRAM= COMPRESSION_EXTENSION= @@ -1530,6 +1563,11 @@ function InitLocalOSDependingSettings { if [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then FIND_CMD=$(dirname $BASH)/find PING_CMD='$SYSTEMROOT\system32\ping -n 2' + + # On BSD, when not root, min ping interval is 1s + elif [ "$LOCAL_OS" == "BSD" ] && [ "$LOCAL_USER" != "root" ]; then + FIND_CMD=find + PING_CMD="ping -c 2 -i 1" else FIND_CMD=find PING_CMD="ping -c 2 -i .2" @@ -1578,7 +1616,7 @@ function InitRemoteOSDependingSettings { fi ## Set rsync default arguments - RSYNC_ARGS="-rltD" + RSYNC_ARGS="-rltD -8" if [ "$_DRYRUN" == true ]; then RSYNC_DRY_ARG="-n" DRY_WARNING="/!\ DRY RUN " @@ -1673,6 +1711,68 @@ function ParentPid { fi } +# Neat version compare function found at http://stackoverflow.com/a/4025065/2635443 +# Returns 0 if equal, 1 if $1 > $2 and 2 if $1 < $2 +vercomp () { + if [[ $1 == $2 ]] + then + return 0 + fi + local IFS=. + local i ver1=($1) ver2=($2) + # fill empty fields in ver1 with zeros + for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) + do + ver1[i]=0 + done + for ((i=0; i<${#ver1[@]}; i++)) + do + if [[ -z ${ver2[i]} ]] + then + # fill empty fields in ver2 with zeros + ver2[i]=0 + fi + if ((10#${ver1[i]} > 10#${ver2[i]})) + then + return 1 + fi + if ((10#${ver1[i]} < 10#${ver2[i]})) + then + return 2 + fi + done + return 0 +} + +function GetConfFileValue () { + local file="${1}" + local name="${2}" + local value + + value=$(grep "^$name=" "$file") + if [ $? == 0 ]; then + value="${value##*=}" + echo "$value" + else + Logger "Cannot get value for [$name] in config file [$file]." "ERROR" + fi +} + +function SetConfFileValue () { + local file="${1}" + local name="${2}" + 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" + else + Logger "Cannot set value [$name] to [$value] in config file [$file]." "ERROR" + fi +} # If using "include" statements, make sure the script does not get executed unless it's loaded by bootstrap _OFUNCTIONS_BOOTSTRAP=true @@ -1781,6 +1881,11 @@ function CheckEnvironment { if [ "$ENCRYPTION" == "yes" ]; then CheckCryptEnvironnment fi + + if ! type pgrep > /dev/null 2>&1 ; then + Logger "pgrep not present. $0 cannot start." "CRITICAL" + exit 1 + fi } function CheckCryptEnvironnment { @@ -1895,7 +2000,7 @@ function _ListDatabasesLocal { Logger "Listing databases succeeded." "NOTICE" else Logger "Listing databases failed." "ERROR" - Logger "Command was [$sqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$sqlCmd]." "WARN" 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" fi @@ -1911,7 +2016,7 @@ function _ListDatabasesRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - sqlCmd="$SSH_CMD \"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" eval "$sqlCmd" & WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME_DB_TASK $HARD_MAX_EXEC_TIME_DB_TASK $SLEEP_TIME $KEEP_LOGGING true true false @@ -2034,7 +2139,7 @@ function _ListRecursiveBackupDirectoriesLocal { retval=$? if [ $retval -ne 0 ]; then Logger "Could not enumerate directories in [$directory]." "ERROR" - Logger "Command was [$cmd]." "Warn" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" 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" fi @@ -2059,7 +2164,8 @@ function _ListRecursiveBackupDirectoriesRemote { local retval -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" \ env RECURSIVE_DIRECTORY_LIST="'$RECURSIVE_DIRECTORY_LIST'" env PATH_SEPARATOR_CHAR="'$PATH_SEPARATOR_CHAR'" \ env REMOTE_FIND_CMD="'$REMOTE_FIND_CMD'" $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" @@ -2096,7 +2202,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -2105,7 +2211,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -2305,14 +2411,14 @@ function _GetDirectoriesSizeLocal { retval=$? 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 "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" 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" fi if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then Logger "Error output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP)" "ERROR" fi - elsew + else Logger "File size fetched successfully." "NOTICE" fi @@ -2333,7 +2439,8 @@ function _GetDirectoriesSizeRemote { local retval # Error output is different from stdout because not all files in list may fail at once -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" dirList="'$dirList'" \ $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" & @@ -2369,7 +2476,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -2378,7 +2485,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -2520,7 +2627,8 @@ function _CreateDirectoryRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" \ env dirToCreate="'$dirToCreate'" $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2>&1 & @@ -2556,7 +2664,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -2565,7 +2673,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -2731,7 +2839,8 @@ function GetDiskSpaceRemote { local cmd local retval -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" \ env DF_CMD="'$DF_CMD'" \ env pathToCheck="'$pathToCheck'" $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" & @@ -2768,7 +2877,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -2777,7 +2886,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue") @@ -3047,10 +3156,10 @@ function _BackupDatabaseLocalToLocal { retval=$? if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ $_DRYRUN == false ]; then - Logger "Command was [$sqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$sqlCmd]." "WARN" eval "$sqlCmd" & else - Logger "Command was [$drySqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$drySqlCmd]." "WARN" eval "$drySqlCmd" & fi Logger "Error output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP)" "ERROR" @@ -3082,7 +3191,7 @@ function _BackupDatabaseLocalToRemote { fi local drySqlCmd="mysqldump -u $SQL_USER $exportOptions --databases $database $COMPRESSION_PROGRAM $COMPRESSION_OPTIONS $encryptOptions > /dev/null 2> $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" - local sqlCmd="mysqldump -u $SQL_USER $exportOptions --databases $database $COMPRESSION_PROGRAM $COMPRESSION_OPTIONS $encryptOptions | $SSH_CMD '$COMMAND_SUDO tee \"$SQL_STORAGE/$database.sql$COMPRESSION_EXTENSION$encryptExtension\" > /dev/null' 2> $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" + local sqlCmd="mysqldump -u $SQL_USER $exportOptions --databases $database $COMPRESSION_PROGRAM $COMPRESSION_OPTIONS $encryptOptions | $SSH_CMD 'env _REMOTE_TOKEN=$_REMOTE_TOKEN $COMMAND_SUDO tee \"$SQL_STORAGE/$database.sql$COMPRESSION_EXTENSION$encryptExtension\" > /dev/null' 2> $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" if [ $_DRYRUN == false ]; then Logger "Launching command [$sqlCmd]." "DEBUG" @@ -3095,10 +3204,10 @@ function _BackupDatabaseLocalToRemote { retval=$? if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ $_DRYRUN == false ]; then - Logger "Command was [$sqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$sqlCmd]." "WARN" eval "$sqlCmd" & else - Logger "Command was [$drySqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$drySqlCmd]." "WARN" eval "$drySqlCmd" & fi Logger "Error output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP)" "ERROR" @@ -3129,8 +3238,8 @@ function _BackupDatabaseRemoteToLocal { encryptExtension="$CRYPT_FILE_EXTENSION" fi - local drySqlCmd=$SSH_CMD' "mysqldump -u '$SQL_USER' '$exportOptions' --databases '$database' '$COMPRESSION_PROGRAM' '$COMPRESSION_OPTIONS' '$encryptOptions'" > /dev/null 2> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP'"' - local sqlCmd=$SSH_CMD' "mysqldump -u '$SQL_USER' '$exportOptions' --databases '$database' '$COMPRESSION_PROGRAM' '$COMPRESSION_OPTIONS' '$encryptOptions'" > "'$SQL_STORAGE/$database.sql$COMPRESSION_EXTENSION$encryptExtension'" 2> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP'"' + local drySqlCmd=$SSH_CMD' "env _REMOTE_TOKEN=$_REMOTE_TOKEN mysqldump -u '$SQL_USER' '$exportOptions' --databases '$database' '$COMPRESSION_PROGRAM' '$COMPRESSION_OPTIONS' '$encryptOptions'" > /dev/null 2> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP'"' + local sqlCmd=$SSH_CMD' "env _REMOTE_TOKEN=$_REMOTE_TOKEN mysqldump -u '$SQL_USER' '$exportOptions' --databases '$database' '$COMPRESSION_PROGRAM' '$COMPRESSION_OPTIONS' '$encryptOptions'" > "'$SQL_STORAGE/$database.sql$COMPRESSION_EXTENSION$encryptExtension'" 2> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP'"' if [ $_DRYRUN == false ]; then Logger "Launching command [$sqlCmd]." "DEBUG" @@ -3143,10 +3252,10 @@ function _BackupDatabaseRemoteToLocal { retval=$? if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" ]; then if [ $_DRYRUN == false ]; then - Logger "Command was [$sqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$sqlCmd]." "WARN" eval "$sqlCmd" & else - Logger "Command was [$drySqlCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$drySqlCmd]." "WARN" eval "$drySqlCmd" & fi Logger "Error output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP)" "ERROR" @@ -3283,7 +3392,7 @@ function EncryptFiles { ParallelExec $PARALLEL_ENCRYPTION_PROCESSES "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.parallel.$SCRIPT_PID.$TSTAMP" true $softMaxExecTime $hardMaxExecTime $SLEEP_TIME $KEEP_LOGGING true true false retval=$? if [ $retval -ne 0 ]; then - Logger "Encryption error.." "ERROR" + Logger "Encryption error." "ERROR" # Output file is defined in ParallelExec Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.ParallelExec.EncryptFiles.$SCRIPT_PID.$TSTAMP)" "DEBUG" fi @@ -3437,13 +3546,13 @@ function Rsync { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost sourceDir=$(EscapeSpaces "$sourceDir") - rsyncCmd="$(type -p $RSYNC_EXECUTABLE) $RSYNC_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $RSYNC_NO_RECURSE_ARGS $RSYNC_DELETE $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --rsync-path=\"$RSYNC_PATH\" -e \"$RSYNC_SSH_CMD\" \"$REMOTE_USER@$REMOTE_HOST:$sourceDir\" \"$destinationDir\" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" + rsyncCmd="$(type -p $RSYNC_EXECUTABLE) $RSYNC_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $RSYNC_NO_RECURSE_ARGS $RSYNC_DELETE $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --rsync-path=\"env _REMOTE_TOKEN=$_REMOTE_TOKEN $RSYNC_PATH\" -e \"$RSYNC_SSH_CMD\" \"$REMOTE_USER@$REMOTE_HOST:$sourceDir\" \"$destinationDir\" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" elif [ "$BACKUP_TYPE" == "push" ]; then destinationDir=$(EscapeSpaces "$destinationDir") _CreateDirectoryRemote "$destinationDir" CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - rsyncCmd="$(type -p $RSYNC_EXECUTABLE) $RSYNC_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $RSYNC_NO_RECURSE_ARGS $RSYNC_DELETE $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --rsync-path=\"$RSYNC_PATH\" -e \"$RSYNC_SSH_CMD\" \"$sourceDir\" \"$REMOTE_USER@$REMOTE_HOST:$destinationDir\" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" + rsyncCmd="$(type -p $RSYNC_EXECUTABLE) $RSYNC_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $RSYNC_NO_RECURSE_ARGS $RSYNC_DELETE $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --rsync-path=\"env _REMOTE_TOKEN=$_REMOTE_TOKEN $RSYNC_PATH\" -e \"$RSYNC_SSH_CMD\" \"$sourceDir\" \"$REMOTE_USER@$REMOTE_HOST:$destinationDir\" > $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP 2>&1" fi Logger "Launching command [$rsyncCmd]." "DEBUG" @@ -3452,7 +3561,7 @@ function Rsync { retval=$? if [ $retval -ne 0 ]; then Logger "Failed to backup [$sourceDir] to [$destinationDir]." "ERROR" - Logger "Command was [$rsyncCmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$rsyncCmd]." "WARN" Logger "Command output:\n $(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP)" "ERROR" else Logger "File backup succeed." "NOTICE" @@ -3598,7 +3707,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot delete oldest copy [$path]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi fi fi @@ -3611,7 +3720,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot move [$path] to [$backup.$PROGRAM.$copy]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi fi @@ -3626,7 +3735,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot move [$backup] to [$backup.$PROGRAM.1]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi elif [ "$REMOTE_OPERATION" == "yes" ]; then @@ -3636,7 +3745,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot copy [$backup] to [$backup.$PROGRAM.1]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi else @@ -3646,7 +3755,7 @@ function _RotateBackupsLocal { WaitForTaskCompletion $! 3600 0 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cannot move [$backup] to [$backup.$PROGRAM.1]." "ERROR" - Logger "Command was [$cmd]." "WARN" + _LOGGER_SILENT=true Logger "Command was [$cmd]." "WARN" fi fi done @@ -3656,7 +3765,8 @@ function _RotateBackupsRemote { local backupPath="${1}" local rotateCopies="${2}" -$SSH_CMD env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ +$SSH_CMD env _REMOTE_TOKEN=$_REMOTE_TOKEN \ +env _DEBUG="'$_DEBUG'" env _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" env _LOGGER_SILENT="'$_LOGGER_SILENT'" env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _LOGGER_PREFIX="'$_LOGGER_PREFIX'" env _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" \ env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" TSTAMP="'$TSTAMP'" \ env REMOTE_FIND_CMD="'$REMOTE_FIND_CMD'" env rotateCopies="'$rotateCopies'" env backupPath="'$backupPath'" \ $COMMAND_SUDO' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID.$TSTAMP" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID.$TSTAMP" @@ -3693,7 +3803,7 @@ function joinString { function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen - local toStderr="${3:-false}" # Log to stderr instead of stdout + local toStdErr="${3:-false}" # Log to stderr instead of stdout if [ "$logValue" != "" ]; then echo -e "$logValue" >> "$LOG_FILE" @@ -3702,7 +3812,7 @@ function _Logger { fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then - if [ $toStderr == true ]; then + if [ $toStdErr == true ]; then # Force stderr color in subshell (>&2 echo -e "$stdValue")