From 54cf89cb279024e43989e9caa7f84078282d9a22 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Dec 2016 13:30:05 +0100 Subject: [PATCH 01/25] Force bash as remote shell. Also refactor remote soft deletion and fix directory ctime find --- dev/n_osync.sh | 140 +++++++++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 63 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index a597dd3..66784a2 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,7 +4,7 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120601 +PROGRAM_BUILD=2016120603 IS_STABLE=no # Execution order #__WITH_PARANOIA_DEBUG @@ -194,33 +194,33 @@ function CheckCurrentConfigAll { ###### Osync specific functions (non shared) function _CheckReplicaPathsLocal { - local replica_path="${1}" + local replicaPath="${1}" __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - if [ ! -w "$replica_path" ]; then - Logger "Local replica path [$replica_path] is not writable." "CRITICAL" + if [ ! -w "$replicaPath" ]; then + Logger "Local replica path [$replicaPath] is not writable." "CRITICAL" exit 1 fi - if [ ! -d "$replica_path" ]; then + if [ ! -d "$replicaPath" ]; then if [ "$CREATE_DIRS" == "yes" ]; then - $COMMAND_SUDO mkdir -p "$replica_path" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 + $COMMAND_SUDO mkdir -p "$replicaPath" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 if [ $? != 0 ]; then - Logger "Cannot create local replica path [$replica_path]." "CRITICAL" + Logger "Cannot create local replica path [$replicaPath]." "CRITICAL" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" exit 1 else - Logger "Created local replica path [$replica_path]." "NOTICE" + Logger "Created local replica path [$replicaPath]." "NOTICE" fi else - Logger "Local replica path [$replica_path] does not exist." "CRITICAL" + Logger "Local replica path [$replicaPath] does not exist." "CRITICAL" exit 1 fi fi } function _CheckReplicaPathsRemote { - local replica_path="${1}" + local replicaPath="${1}" __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG local cmd @@ -228,19 +228,26 @@ function _CheckReplicaPathsRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - cmd=$SSH_CMD' "if [ ! -w \"'$replica_path'\" ];then exit 1; fi" 2>&1' - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" +$SSH_CMD replicaPath="'$replicaPath'" 'bash -s' << 'ENDSSH' 2>&1 +if [ ! -w "$replicaPath" ]; then + exit 1 +fi +ENDSSH + if [ $? != 0 ]; then - Logger "Remote replica path [$replica_path] is not writable." "CRITICAL" + Logger "Remote replica path [$replicaPath] is not writable." "CRITICAL" exit 1 fi - cmd=$SSH_CMD' "if ! [ -d \"'$replica_path'\" ]; then if [ \"'$CREATE_DIRS'\" == \"yes\" ]; then '$COMMAND_SUDO' mkdir -p \"'$replica_path'\"; fi; fi" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1' - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" +$SSH_CMD replicaPath="'$replicaPath'" CREATE_DIRS="'$CREATE_DIRS'" COMMAND_SUDO="'$COMMAND_SUDO'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +if [ ! -d "$replicaPath" ]; then + if [ "$CREATE_DIRS" == "yes" ]; then + $COMMAND_SUDO mkdir -p "$replicaPath" + fi +fi +ENDSSH if [ $? != 0 ]; then - Logger "Cannot create remote replica path [$replica_path]." "CRITICAL" + Logger "Cannot create remote replica path [$replicaPath]." "CRITICAL" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" exit 1 fi @@ -275,14 +282,14 @@ function CheckReplicaPaths { } function _CheckDiskSpaceLocal { - local replica_path="${1}" + local replicaPath="${1}" __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG local diskSpace - Logger "Checking minimum disk space in [$replica_path]." "NOTICE" + Logger "Checking minimum disk space in [$replicaPath]." "NOTICE" - diskSpace=$($DF_CMD "$replica_path" | tail -1 | awk '{print $4}') + diskSpace=$($DF_CMD "$replicaPath" | tail -1 | awk '{print $4}') if [ $? != 0 ]; then Logger "Cannot get free space." "ERROR" @@ -293,16 +300,16 @@ function _CheckDiskSpaceLocal { fi if [ $diskSpace -lt $MINIMUM_SPACE ]; then - Logger "There is not enough free space on replica [$replica_path] ($diskSpace KB)." "WARN" + Logger "There is not enough free space on replica [$replicaPath] ($diskSpace KB)." "WARN" fi fi } function _CheckDiskSpaceRemote { - local replica_path="${1}" + local replicaPath="${1}" __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - Logger "Checking remote minimum disk space in [$replica_path]." "NOTICE" + Logger "Checking remote minimum disk space in [$replicaPath]." "NOTICE" local cmd local diskSpace @@ -310,11 +317,11 @@ function _CheckDiskSpaceRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - cmd=$SSH_CMD' "'$COMMAND_SUDO' '$DF_CMD' \"'$replica_path'\"" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1' - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" +$SSH_CMD replicaPath="'$replicaPath'" COMMAND_SUDO="'$COMMAND_SUDO'" DF_CMD="'$DF_CMD'" bash -s << ENDSSH > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +$COMMAND_SUDO $DF_CMD "$replicaPath" +ENDSSH if [ $? != 0 ]; then - Logger "Cannot get free space on target [$replica_path]." "ERROR" + Logger "Cannot get free space on target [$replicaPath]." "ERROR" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE" else diskSpace=$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID | tail -1 | awk '{print $4}') @@ -325,7 +332,7 @@ function _CheckDiskSpaceRemote { fi if [ $diskSpace -lt $MINIMUM_SPACE ]; then - Logger "There is not enough free space on replica [$replica_path] ($diskSpace KB)." "WARN" + Logger "There is not enough free space on replica [$replicaPath] ($diskSpace KB)." "WARN" fi fi } @@ -354,13 +361,13 @@ function CheckDiskSpace { function _CreateStateDirsLocal { - local replica_state_dir="${1}" + local replicaStateDir="${1}" __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - if ! [ -d "$replica_state_dir" ]; then - $COMMAND_SUDO mkdir -p "$replica_state_dir" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 + if [ ! -d "$replicaStateDir" ]; then + $COMMAND_SUDO mkdir -p "$replicaStateDir" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 if [ $? != 0 ]; then - Logger "Cannot create state dir [$replica_state_dir]." "CRITICAL" + Logger "Cannot create state dir [$replicaStateDir]." "CRITICAL" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" exit 1 fi @@ -368,7 +375,7 @@ function _CreateStateDirsLocal { } function _CreateStateDirsRemote { - local replica_state_dir="${1}" + local replicaStateDir="${1}" __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG local cmd @@ -376,11 +383,13 @@ function _CreateStateDirsRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - cmd=$SSH_CMD' "if ! [ -d \"'$replica_state_dir'\" ]; then '$COMMAND_SUDO' mkdir -p \"'$replica_state_dir'\"; fi" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1' - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" +$SSH_CMD replicaStateDir="'$replicaStateDir'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +if [ ! -d "$replicaStateDir" ]; then + $COMMAND_SUDO mkdir -p "$replicaStateDir" +fi +ENDSSH if [ $? != 0 ]; then - Logger "Cannot create remote state dir [$replica_state_dir]." "CRITICAL" + Logger "Cannot create remote state dir [$replicaStateDir]." "CRITICAL" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" exit 1 fi @@ -461,9 +470,11 @@ function _CheckLocksRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - cmd=$SSH_CMD' "if [ -f \"'$lockfile'\" ]; then cat \"'$lockfile'\"; fi" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'"' - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" +$SSH_CMD lockfile="'$lockFile'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +if [ -f "$lockfile" ]; then + cat "$lockfile" +fi +ENDSSH if [ $? != 0 ]; then Logger "Cannot check remote replica lock." "CRITICAL" exit 1 @@ -574,9 +585,14 @@ function _WriteLockFilesRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - cmd=$SSH_CMD' "( if [ $overwrite == true ]; then set -o noclobber; fi; echo '$SCRIPT_PID@$INSTANCE_ID' | '$COMMAND_SUDO' tee \"'$lockfile'\")" > /dev/null 2> $RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID' - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" +$SSH_CMD overwrite="'$overwrite'" SCRIPT_PID="'$SCRIPT_PID'" COMMAND_SUDO="'$COMMAND_SUDO'" lockfile="'$lockfile'" 'bash -s' << 'ENDSSH' > /dev/null 2> "$RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID" +( + if [ $overwrite == true ]; then + set -o noclobber + fi + $COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" +) +ENDSSH if [ $? != 0 ]; then Logger "Could not create lock file on remote $replicaType in [$lockfile]." "CRITICAL" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$replicaType.$SCRIPT_PID)" "NOTICE" @@ -647,9 +663,11 @@ function _UnlockReplicasRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost - cmd=$SSH_CMD' "if [ -f \"'$lockfile'\" ]; then '$COMMAND_SUDO' rm -f \"'$lockfile'\"; fi" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1' - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" +$SSH_CMD lockfile="'$lockfile'" COMMAND_SUDO="'$COMMAND_SUDO'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +if [ -f "$lockfile" ]; then + $COMMAND_SUDO rm -f "$lockfile" +fi +ENDSSH if [ $? != 0 ]; then Logger "Could not unlock remote replica." "ERROR" Logger "Command Output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE" @@ -818,7 +836,8 @@ function _getFileCtimeMtimeRemote { local cmd - cmd='cat "'$fileList'" | '$SSH_CMD' "while read -r file; do '$REMOTE_STAT_CTIME_MTIME_CMD' \"'$replicaPath'\$file\"; done | sort" > "'$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID'"' + # Quoting ' in single quote with '"'"' in order to have cmd='some stuff \'bash -c "some other stuff"\'' + cmd='cat "'$fileList'" | '$SSH_CMD' '"'"'bash -c "while read -r file; do '$REMOTE_STAT_CTIME_MTIME_CMD' \"'$replicaPath'\$file\"; done | sort"'"'"' > "'$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID'"' Logger "CMD: $cmd" "DEBUG" eval "$cmd" if [ $? != 0 ]; then @@ -1733,22 +1752,17 @@ function _SoftDeleteRemote { Logger "Removing files older than $changeTime days on $replicaType replica for $deletionType deletion." "NOTICE" fi - if [ $_LOGGER_VERBOSE == true ]; then - # Cannot launch log function from xargs, ugly hack - cmd=$SSH_CMD' "if [ -d \"'$replicaDeletionPath'\" ]; then '$COMMAND_SUDO' '$REMOTE_FIND_CMD' \"'$replicaDeletionPath'/\" -type f -ctime +'$changeTime' -print0 | xargs -0 -I {} echo Will delete file {} && '$COMMAND_SUDO' '$REMOTE_FIND_CMD' \"'$replicaDeletionPath'/\" -type d -empty -ctime '$changeTime' -print0 | xargs -0 -I {} echo Will delete directory {}; else echo \"The $replicaType replica dir [$replicaDeletionPath] does not exist. Skipping cleaning of old files.\"; fi" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1' - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" - Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "VERBOSE" - fi + #TODO: fixed find directory -ctime was missing +, test it +$SSH_CMD _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _DRYRUN="'$_DRYRUN'" replicaDeletionPath="'$replicaDeletionPath'" changeTime="'$changeTime'" COMAMND_SUDO="'$COMMAND_SUDO'" REMOTE_FIND_CMD="'$REMOTE_FIND_CMD'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 - if [ $_DRYRUN == false ]; then - cmd=$SSH_CMD' "if [ -d \"'$replicaDeletionPath'\" ]; then '$COMMAND_SUDO' '$REMOTE_FIND_CMD' \"'$replicaDeletionPath'/\" -type f -ctime +'$changeTime' -print0 | xargs -0 -I {} '$COMMAND_SUDO' rm -f \"{}\" && '$COMMAND_SUDO' '$REMOTE_FIND_CMD' \"'$replicaDeletionPath'/\" -type d -empty -ctime '$changeTime' -print0 | xargs -0 -I {} '$COMMAND_SUDO' rm -rf \"{}\"; else echo \"The $replicaType replicaDir [$replicaDeletionPath] does not exist. Skipping cleaning of old files.\"; fi" >> "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1' - - Logger "cmd: $cmd" "DEBUG" - eval "$cmd" - else - Dummy - fi +# Cannot launch log function from xargs, ugly hack +if [ -d "$replicaDeletionPath" ]; then +$COMMAND_SUDO $REMOTE_FIND_CMD "$replicaDeletionPath" -type f -ctime +"$changeTime" -print0 | xargs -0 -I {} bash -c 'export file="{}"; if [ '$_LOGGER_VERBOSE' == true ]; then echo "Will delete file {}"; if [ '$DRYRUN' == false ]; then '$COMMAND_SUDO' rm -f "$file"' +$COMMAND_SUDO $REMOTE_FIND_CMD "$replicaDeletionPath" -type d -empty -ctime +"$changeTime" -print0 | xargs -0 -I {} bash -c 'export file="{}"; if [ '$_LOGGER_VERBOSE' == true ]; then echo "Will delete directory {}"; if [ '$DRY_RUN' == false ]; then '$COMMAND_SUDO' rm -f "{}"' +else + echo "The $replicaType replica dir [$replicaDeletionPath] does not exist. Skipping cleaning of old files" +fi +ENDSSH retval=$? if [ $retval -ne 0 ]; then Logger "Error while executing cleanup on remote $replicaType replica." "ERROR" From 59b8764da6af8c6099d3bfb2fcc34737c31186a6 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Dec 2016 21:32:27 +0100 Subject: [PATCH 02/25] Merged CreateStateDirs, CheckLocks and WriteLocks into HandleLocks --- dev/n_osync.sh | 411 ++++++++++++++++++++++++------------------------- 1 file changed, 200 insertions(+), 211 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index 66784a2..b3460ab 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,7 +4,7 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120603 +PROGRAM_BUILD=2016120604 IS_STABLE=no # Execution order #__WITH_PARANOIA_DEBUG @@ -22,9 +22,7 @@ IS_STABLE=no # CheckDiskSpace yes #__WITH_PARANOIA_DEBUG # RunBeforeHook yes #__WITH_PARANOIA_DEBUG # Main no #__WITH_PARANOIA_DEBUG -# CreateStateDirs yes #__WITH_PARANOIA_DEBUG -# CheckLocks yes #__WITH_PARANOIA_DEBUG -# WriteLockFiles yes #__WITH_PARANOIA_DEBUG +# HandleLocks yes #__WITH_PARANOIA_DEBUG # Sync no #__WITH_PARANOIA_DEBUG # treeList yes #__WITH_PARANOIA_DEBUG # treeList yes #__WITH_PARANOIA_DEBUG @@ -184,7 +182,7 @@ function CheckCurrentConfigAll { if [ "$SKIP_DELETION" != "" ]; then tmp="$SKIP_DELETION" IFS=',' read -r -a SKIP_DELETION <<< "$tmp" - if [ $(arrayContains "${INITIATOR[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ] && [ $(arrayContains "${TARGET[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then + if [ $(ArrayContains "${INITIATOR[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ] && [ $(ArrayContains "${TARGET[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then Logger "Bogus skip deletion parameter [$SKIP_DELETION]." "CRITICAL" exit 1 fi @@ -359,85 +357,41 @@ function CheckDiskSpace { WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} } - -function _CreateStateDirsLocal { +function _HandleLocksLocal { local replicaStateDir="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + local lockfile="${2}" + local replicaType="${3}" + local overwrite="${4:-false}" + + __CheckArguments 4 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + + local lockfileContent + local lockPid + local lockInstanceID + local writeLocks if [ ! -d "$replicaStateDir" ]; then $COMMAND_SUDO mkdir -p "$replicaStateDir" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 if [ $? != 0 ]; then Logger "Cannot create state dir [$replicaStateDir]." "CRITICAL" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" - exit 1 + return 1 fi fi -} -function _CreateStateDirsRemote { - local replicaStateDir="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - local cmd - - CheckConnectivity3rdPartyHosts - CheckConnectivityRemoteHost - -$SSH_CMD replicaStateDir="'$replicaStateDir'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 -if [ ! -d "$replicaStateDir" ]; then - $COMMAND_SUDO mkdir -p "$replicaStateDir" -fi -ENDSSH - if [ $? != 0 ]; then - Logger "Cannot create remote state dir [$replicaStateDir]." "CRITICAL" - Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" - exit 1 - fi -} - -function CreateStateDirs { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - local pids - - _CreateStateDirsLocal "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}" & - pids="$!" - if [ "$REMOTE_OPERATION" != "yes" ]; then - _CreateStateDirsLocal "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}" & - pids="$pids;$!" - else - _CreateStateDirsRemote "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}" & - pids="$pids;$!" - fi - WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} - if [ $? -ne 0 ]; then - Logger "Cancelling task." "CRITICAL" - exit 1 - fi -} - -function _CheckLocksLocal { - local lockfile="${1}" - local replicaType="${2}" - - __CheckArguments 2 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - local lockfileContent - local lockPid - local lockInstanceID - - if [ -s "$lockfile" ]; then + # Skip the whole part if overwrite true + if [ -s "$lockfile" ] && [ $overwrite != true ]; then lockfileContent=$(cat $lockfile) Logger "Master lock pid present: $lockfileContent" "DEBUG" - lockPid=${lockfileContent%@*} + lockPid="${lockfileContent%@*}" if [ $(IsInteger $lockPid) -ne 1 ]; then Logger "Invalid pid [$lockPid] in local replica." "CRITICAL" - exit 1 + return 1 fi - lockInstanceID=${lockfileContent#*@} + lockInstanceID="${lockfileContent#*@}" if [ "$lockInstanceID" == "" ]; then Logger "Invalid instance id [$lockInstanceID] in local replica." "CRITICAL" - exit 1 + return 1 Logger "Local $replicaType lock is: [$lockPid@$lockInstanceID]." "DEBUG" @@ -445,82 +399,199 @@ function _CheckLocksLocal { kill -0 $lockPid > /dev/null 2>&1 if [ $? != 0 ]; then Logger "There is a local dead osync lock [$lockPid@$lockInstanceID] that is no longer running. Resuming." "NOTICE" - if [ "$replicaType" == "${INITIATOR[$__type]}" ]; then - # REPLICA_OVERWRITE_LOCK disables noclobber option in WriteLock functions - INITIATOR_OVERWRITE_LOCK=true - elif [ "$replicaType" == "${TARGET[$__type]}" ]; then - TARGET_OVERWRITE_LOCK=true - fi + writeLocks=true else Logger "There is already a local instance [$lockPid@$lockInstanceID] of osync running for this replica. Cannot start." "CRITICAL" - exit 1 + return 1 + fi + else + writeLocks=true + fi + + if [ $writeLocks != true ]; then + Logger "This is the final merdier" "WARN" + return 1 + else + $COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID" + if [ $? != 0 ]; then + Logger "Could not create lock file on local $replicaType in [$lockfile]." "CRITICAL" + Logger "Command output\n$($RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID)" "NOTICE" + return 1 + else + Logger "Locked local $replicaType replica in [$lockfile]." "DEBUG" fi fi } -function _CheckLocksRemote { - local lockfile="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG +function _HandleLocksRemote { + local replicaStateDir="${1}" + local lockfile="${2}" + local replicaType="${3}" + local overwrite="${4:-false}" - local cmd - local lockPid - local lockInstanceID - local lockfileContent + __CheckArguments 4 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + + local initiatorRunningPids CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost -$SSH_CMD lockfile="'$lockFile'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 -if [ -f "$lockfile" ]; then - cat "$lockfile" -fi -ENDSSH - if [ $? != 0 ]; then - Logger "Cannot check remote replica lock." "CRITICAL" - exit 1 + # Create an array of all currently running pids + # TODO: check portability + read -a initiatorRunningPids <<< $(ps -A | tail -n +2 | awk '{print $1}') + +# passing initiatorRunningPids as litteral string (has to be run through eval to be an array again) +$SSH_CMD replicaStateDir="'$replicaStateDir'" initiatorRunningPidsFlat="(${initiatorRunningPids[@]})" lockfile="'$lockfile'" replicaType="'$replicaType'" overwrite="'$overwrite'" SCRIPT_PID="'$SCRIPT_PID'" INSTANCE_ID="'$INSTANCE_ID'" FORCE_STRANGER_LOCK_RESUME="'$FORCE_STRANGER_LOCK_RESUME'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 + function ArrayContains () { + local needle="${1}" + local haystack="${@:2}" + local e + + if [ "$needle" != "" ] && [ "$haystack" != "" ]; then + for e in "${@:2}"; do + if [ "$e" == "$needle" ]; then + echo 1 + return + fi + done + fi + echo 0 + return + } + + function IsInteger { + local value="${1}" + + if [[ $value =~ ^[0-9]+$ ]]; then + echo 1 + else + echo 0 + fi + } + + ## The following lines are executed remotely + function _logger { + local value="${1}" # What to log + echo -e "$value" + } + + function Logger { + local value="${1}" # What to log + local level="${2}" # Log level: DEBUG, NOTICE, WARN, ERROR, CRITIAL + + local prefix="RTIME: $SECONDS - " + + if [ "$level" == "CRITICAL" ]; then + _logger "$prefix\e[41m$value\e[0m" + return + elif [ "$level" == "ERROR" ]; then + _logger "$prefix\e[91m$value\e[0m" + return + elif [ "$level" == "WARN" ]; then + _logger "$prefix\e[93m$value\e[0m" + return + elif [ "$level" == "NOTICE" ]; then + _logger "$prefix$value" + return + elif [ "$level" == "VERBOSE" ]; then + if [ $_LOGGER_VERBOSE == true ]; then + _logger "$prefix$value" + fi + return + elif [ "$level" == "DEBUG" ]; then + if [ "$_DEBUG" == "yes" ]; then + _logger "$prefix$value" + fi + return + else + _logger "\e[41mLogger function called without proper loglevel [$level].\e[0m" + _logger "$prefix$value" + fi + } + +function _HandleLocksRemoteSub { + #WIP do not remote log to file as output is already logged from ssh + if [ ! -d "$replicaStateDir" ]; then + $COMMAND_SUDO mkdir -p "$replicaStateDir" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 + if [ $? != 0 ]; then + Logger "Cannot create state dir [$replicaStateDir]." "CRITICAL" + Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" + return 1 + fi fi - if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then - lockfileContent="$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" - - lockPid=${lockfileContent%@*} + # Skip the whole part if overwrite true + if [ -s "$lockfile" ] && [ $overwrite != true ]; then + lockfileContent=$(cat $lockfile) + Logger "Master lock pid present: $lockfileContent" "DEBUG" + lockPid="${lockfileContent%@*}" if [ $(IsInteger $lockPid) -ne 1 ]; then - Logger "Invalid pid [$lockPid] in remote replica lock." "CRITICAL" - exit 1 + Logger "Invalid pid [$lockPid] in local replica." "CRITICAL" + return 1 fi - lockInstanceID=${lockfileContent#*@} + lockInstanceID="${lockfileContent#*@}" if [ "$lockInstanceID" == "" ]; then - Logger "Invalid instance id [$lockInstanceID] in remote replica." "CRITICAL" - exit 1 + Logger "Invalid instance id [$lockInstanceID] in local replica." "CRITICAL" + return 1 + + Logger "Local $replicaType lock is: [$lockPid@$lockInstanceID]." "DEBUG" + fi - Logger "Remote lock is: [$lockPid@$lockInstanceID]" "DEBUG" - - kill -0 $lockPid > /dev/null 2>&1 - if [ $? != 0 ]; then + # Retransform litteral array string to array + eval "initiatorRunningPids=$initiatorRunningPidsFlat" + if [ $(ArrayContains "$lockPid" "${initiatorRunningPids[@]}") -eq 0 ]; then if [ "$lockInstanceID" == "$INSTANCE_ID" ]; then - Logger "There is a remote dead osync lock [$lockPid@lockInstanceID] on target replica that corresponds to this initiator INSTANCE_ID. Pid [$lockPid] no longer running. Resuming." "NOTICE" - TARGET_OVERWRITE_LOCK=true + Logger "There is a remote dead osync lock [$lockPid@$lockInstanceID] on target replica that corresponds to this initiator INSTANCE_ID. Pid [$lockPid] no longer running. Resuming." "NOTICE" + writeLocks=true else if [ "$FORCE_STRANGER_LOCK_RESUME" == "yes" ]; then Logger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Forcing resume." "WARN" - TARGET_OVERWRITE_LOCK=true + writeLocks=true else Logger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Will not resume." "CRITICAL" - exit 1 + return 1 fi fi else Logger "There is already a local instance of osync that locks target replica [$lockPid@$lockInstanceID]. Cannot start." "CRITICAL" - exit 1 + return 1 + fi + else + writeLocks=true + fi + + if [ $writeLocks != true ]; then + return 1 + else + $COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID" + if [ $? != 0 ]; then + Logger "Could not create lock file on local $replicaType in [$lockfile]." "CRITICAL" + Logger "Command output\n$($RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID)" "NOTICE" + return 1 + else + Logger "Locked local $replicaType replica in [$lockfile]." "DEBUG" fi fi } -function CheckLocks { +_HandleLocksRemoteSub +result=$? +exit $result +ENDSSH + + if [ $? != 0 ]; then + Logger "Remote lock handling failed." "CRITICAL" + Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" + return 1 + fi +} + +function HandleLocks { __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG local pids + local overwrite=false if [ $_NOLOCKS == true ]; then return 0 @@ -528,115 +599,34 @@ function CheckLocks { # Do not bother checking for locks when FORCE_UNLOCK is set if [ $FORCE_UNLOCK == true ]; then - WriteLockFiles - if [ $? != 0 ]; then - exit 1 - fi + overwrite=true else - _CheckLocksLocal "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}" & + _HandleLocksLocal "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}" "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}" $overwrite & pids="$!" if [ "$REMOTE_OPERATION" != "yes" ]; then - _CheckLocksLocal "${TARGET[$__lockFile]}" "${INITIATOR[$__type]}" & + _HandleLocksLocal "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}" "${TARGET[$__lockFile]}" "${TARGET[$__type]}" $overwrite & pids="$pids;$!" else - _CheckLocksRemote "${TARGET[$__lockFile]}" & + _HandleLocksRemote "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}" "${TARGET[$__lockFile]}" "${TARGET[$__type]}" $overwrite & pids="$pids;$!" fi + INITIATOR_LOCK_FILE_EXISTS=true + TARGET_LOCK_FILE_EXISTS=true WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} if [ $? -ne 0 ]; then - Logger "Cancelling task." "CRITICAL" - exit 1 + IFS=';' read -r -a pidArray <<< "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_${FUNCNAME[0]}\")" + for pid in "${pidArray[@]}"; do + pid=${pid%:*} + if [ "$pid" == "$initiatorPid" ]; then + INITIATOR_LOCK_FILE_EXISTS=false + elif [ "$pid" == "$targetPid" ]; then + TARGET_LOCK_FILE_EXISTS=false + fi + done + + Logger "Cancelling task." "CRITICAL" + exit 1 fi - WriteLockFiles - fi -} - -function _WriteLockFilesLocal { - local lockfile="${1}" - local replicaType="${2}" - local overwrite="${3:-false}" - - __CheckArguments 2-3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - ( - if [ $overwrite == true ]; then - set -o noclobber - fi - $COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID" - ) - if [ $? != 0 ]; then - Logger "Could not create lock file on local $replicaType in [$lockfile]." "CRITICAL" - Logger "Command output\n$($RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID)" "NOTICE" - return 1 - else - Logger "Locked local $replicaType replica in [$lockfile]." "DEBUG" - fi -} - -function _WriteLockFilesRemote { - local lockfile="${1}" - local replicaType="${2}" - local overwrite="${3-false}" - - __CheckArguments 2-3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - local cmd - - CheckConnectivity3rdPartyHosts - CheckConnectivityRemoteHost - -$SSH_CMD overwrite="'$overwrite'" SCRIPT_PID="'$SCRIPT_PID'" COMMAND_SUDO="'$COMMAND_SUDO'" lockfile="'$lockfile'" 'bash -s' << 'ENDSSH' > /dev/null 2> "$RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID" -( - if [ $overwrite == true ]; then - set -o noclobber - fi - $COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" -) -ENDSSH - if [ $? != 0 ]; then - Logger "Could not create lock file on remote $replicaType in [$lockfile]." "CRITICAL" - Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$replicaType.$SCRIPT_PID)" "NOTICE" - return 1 - else - Logger "Locked remote $replicaType replica in [$lockfile]." "DEBUG" - fi -} - -function WriteLockFiles { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - local initiatorPid - local targetPid - local pidArray - local pid - - _WriteLockFilesLocal "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}" $INITIATOR_LOCK_OVERWRITE & - initiatorPid="$!" - - if [ "$REMOTE_OPERATION" != "yes" ]; then - _WriteLockFilesLocal "${TARGET[$__lockFile]}" "${TARGET[$__type]}" $TARGET_LOCK_OVERWRITE & - targetPid="$!" - else - _WriteLockFilesRemote "${TARGET[$__lockFile]}" "${TARGET[$__type]}" $TARGET_LOCK_OVERWRITE & - targetPid="$!" - fi - - INITIATOR_LOCK_FILE_EXISTS=true - TARGET_LOCK_FILE_EXISTS=true - WaitForTaskCompletion "$initiatorPid;$targetPid" 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} - if [ $? -ne 0 ]; then - IFS=';' read -r -a pidArray <<< "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_${FUNCNAME[0]}\")" - for pid in "${pidArray[@]}"; do - pid=${pid%:*} - if [ "$pid" == "$initiatorPid" ]; then - INITIATOR_LOCK_FILE_EXISTS=false - elif [ "$pid" == "$targetPid" ]; then - TARGET_LOCK_FILE_EXISTS=false - fi - done - - Logger "Cancelling task." "CRITICAL" - exit 1 fi } @@ -1302,7 +1292,7 @@ function deletionPropagation { Logger "Propagating deletions to $replicaType replica." "NOTICE" if [ "$replicaType" == "${INITIATOR[$__type]}" ]; then - if [ $(arrayContains "${INITIATOR[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then + if [ $(ArrayContains "${INITIATOR[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then replicaDir="${INITIATOR[$__replicaDir]}" deleteDir="${INITIATOR[$__deleteDir]}" @@ -1316,7 +1306,7 @@ function deletionPropagation { Logger "Skipping deletion on replica $replicaType." "NOTICE" fi elif [ "$replicaType" == "${TARGET[$__type]}" ]; then - if [ $(arrayContains "${TARGET[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then + if [ $(ArrayContains "${TARGET[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then replicaDir="${TARGET[$__replicaDir]}" deleteDir="${TARGET[$__deleteDir]}" @@ -2041,8 +2031,7 @@ function Init { function Main { __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - CreateStateDirs - CheckLocks + HandleLocks Sync } From ae16cefe54411a0e5e59e61899ea6966c91964b2 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Dec 2016 22:41:44 +0100 Subject: [PATCH 03/25] Refactored CheckDiskSpace & CheckReplicaPath into CheckReplicas --- dev/n_osync.sh | 302 +++++++++++++++++++++++++++++-------------------- 1 file changed, 180 insertions(+), 122 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index b3460ab..bb2e18e 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,9 +4,13 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120604 +PROGRAM_BUILD=2016120605 IS_STABLE=no +#TODO: replace _Logger & Logger in remote functions with ofunctions version dedicated to remote logging +#TODO: replace ArrayContains, IsNumeric, HumanToNumeric with ofunctions version via merge +#TODO: deal with _VERBOSE / _SILENT switches in remote Logger + # Execution order #__WITH_PARANOIA_DEBUG # Function Name Is parallel #__WITH_PARANOIA_DEBUG @@ -18,8 +22,7 @@ IS_STABLE=no # PostInit no #__WITH_PARANOIA_DEBUG # GetRemoteOS no #__WITH_PARANOIA_DEBUG # InitRemoteOSDependingSettings no #__WITH_PARANOIA_DEBUG -# CheckReplicaPaths yes #__WITH_PARANOIA_DEBUG -# CheckDiskSpace yes #__WITH_PARANOIA_DEBUG +# CheckReplicas yes #__WITH_PARANOIA_DEBUG # RunBeforeHook yes #__WITH_PARANOIA_DEBUG # Main no #__WITH_PARANOIA_DEBUG # HandleLocks yes #__WITH_PARANOIA_DEBUG @@ -191,14 +194,11 @@ function CheckCurrentConfigAll { ###### Osync specific functions (non shared) -function _CheckReplicaPathsLocal { +function _CheckReplicasLocal { local replicaPath="${1}" __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - if [ ! -w "$replicaPath" ]; then - Logger "Local replica path [$replicaPath] is not writable." "CRITICAL" - exit 1 - fi + local diskSpace if [ ! -d "$replicaPath" ]; then if [ "$CREATE_DIRS" == "yes" ]; then @@ -206,18 +206,38 @@ function _CheckReplicaPathsLocal { if [ $? != 0 ]; then Logger "Cannot create local replica path [$replicaPath]." "CRITICAL" Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" - exit 1 + return 1 else Logger "Created local replica path [$replicaPath]." "NOTICE" fi else Logger "Local replica path [$replicaPath] does not exist." "CRITICAL" - exit 1 + return 1 + fi + fi + + if [ ! -w "$replicaPath" ]; then + Logger "Local replica path [$replicaPath] is not writable." "CRITICAL" + return 1 + fi + + Logger "Checking minimum disk space in local replica [$replicaPath]." "NOTICE" + diskSpace=$($DF_CMD "$replicaPath" | tail -1 | awk '{print $4}') + if [ $? != 0 ]; then + Logger "Cannot get free space." "ERROR" + else + # Ugly fix for df in some busybox environments that can only show human formats + if [ $(IsInteger $diskSpace) -eq 0 ]; then + diskSpace=$(HumanToNumeric $diskSpace) + fi + + if [ $diskSpace -lt $MINIMUM_SPACE ]; then + Logger "There is not enough free space on local replica [$replicaPath] ($diskSpace KB)." "WARN" fi fi } -function _CheckReplicaPathsRemote { +function _CheckReplicasRemote { local replicaPath="${1}" __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG @@ -226,32 +246,147 @@ function _CheckReplicaPathsRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost -$SSH_CMD replicaPath="'$replicaPath'" 'bash -s' << 'ENDSSH' 2>&1 -if [ ! -w "$replicaPath" ]; then - exit 1 -fi -ENDSSH +$SSH_CMD replicaPath="'$replicaPath'" CREATE_DIRS="'$CREATE_DIRS'" COMMAND_SUDO="'$COMMAND_SUDO'" DF_CMD="'$DF_CMD'" MINIMUM_SPACE="'$MINIMUM_SPACE'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 + ## The following lines are executed remotely + function _logger { + local value="${1}" # What to log + echo -e "$value" + } - if [ $? != 0 ]; then + function Logger { + local value="${1}" # What to log + local level="${2}" # Log level: DEBUG, NOTICE, WARN, ERROR, CRITIAL + + local prefix="RTIME: $SECONDS - " + + if [ "$level" == "CRITICAL" ]; then + _logger "$prefix\e[41m$value\e[0m" + return + elif [ "$level" == "ERROR" ]; then + _logger "$prefix\e[91m$value\e[0m" + return + elif [ "$level" == "WARN" ]; then + _logger "$prefix\e[93m$value\e[0m" + return + elif [ "$level" == "NOTICE" ]; then + _logger "$prefix$value" + return + elif [ "$level" == "VERBOSE" ]; then + if [ $_LOGGER_VERBOSE == true ]; then + _logger "$prefix$value" + fi + return + elif [ "$level" == "DEBUG" ]; then + if [ "$_DEBUG" == "yes" ]; then + _logger "$prefix$value" + fi + return + else + _logger "\e[41mLogger function called without proper loglevel [$level].\e[0m" + _logger "$prefix$value" + fi + } + +function IsInteger { + local value="${1}" + + if [[ $value =~ ^[0-9]+$ ]]; then + echo 1 + else + echo 0 + fi +} + +# Converts human readable sizes into integer kilobyte sizes +# Usage numericSize="$(HumanToNumeric $humanSize)" +function HumanToNumeric { + local value="${1}" + + local notation + local suffix + local suffixPresent + local multiplier + + notation=(K M G T P E) + for suffix in "${notation[@]}"; do + multiplier=$((multiplier+1)) + if [[ "$value" == *"$suffix"* ]]; then + suffixPresent=$suffix + break; + fi + done + + if [ "$suffixPresent" != "" ]; then + value=${value%$suffix*} + value=${value%.*} + # /1024 since we convert to kilobytes instead of bytes + value=$((value*(1024**multiplier/1024))) + else + value=${value%.*} + fi + + echo $value +} + +function _CheckReplicasRemoteSub { + + if [ ! -d "$replicaPath" ]; then + if [ "$CREATE_DIRS" == "yes" ]; then + $COMMAND_SUDO mkdir -p "$replicaPath" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 + if [ $? != 0 ]; then + Logger "Cannot create remote replica path [$replicaPath]." "CRITICAL" + Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" + exit 1 + else + Logger "Created remote replica path [$replicaPath]." "NOTICE" + fi + else + Logger "Remote replica path [$replicaPath] does not exist." "CRITICAL" + exit 1 + fi + fi + + if [ ! -w "$replicaPath" ]; then Logger "Remote replica path [$replicaPath] is not writable." "CRITICAL" exit 1 fi -$SSH_CMD replicaPath="'$replicaPath'" CREATE_DIRS="'$CREATE_DIRS'" COMMAND_SUDO="'$COMMAND_SUDO'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 -if [ ! -d "$replicaPath" ]; then - if [ "$CREATE_DIRS" == "yes" ]; then - $COMMAND_SUDO mkdir -p "$replicaPath" - fi -fi -ENDSSH + Logger "Checking minimum disk space in remote replica [$replicaPath]." "NOTICE" + diskSpace=$($DF_CMD "$replicaPath" | tail -1 | awk '{print $4}') if [ $? != 0 ]; then - Logger "Cannot create remote replica path [$replicaPath]." "CRITICAL" - Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" - exit 1 + Logger "Cannot get free space." "ERROR" + else + # Ugly fix for df in some busybox environments that can only show human formats + if [ $(IsInteger $diskSpace) -eq 0 ]; then + diskSpace=$(HumanToNumeric $diskSpace) + fi + + if [ $diskSpace -lt $MINIMUM_SPACE ]; then + Logger "There is not enough free space on remote replica [$replicaPath] ($diskSpace KB)." "WARN" + fi + fi +} +_CheckReplicasRemoteSub +exit $? +ENDSSH + result=$? + if [ $result != 0 ]; then + Logger "Failed to check remote replica.." "CRITICAL" + fi + if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then + ( + _LOGGER_PREFIX="" + Logger "$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE" + ) + fi + if [ $result != 0 ]; then + return 1 + else + return 0 fi } -function CheckReplicaPaths { +function CheckReplicas { __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG local pids @@ -263,13 +398,13 @@ function CheckReplicaPaths { fi fi - _CheckReplicaPathsLocal "${INITIATOR[$__replicaDir]}" & + _CheckReplicasLocal "${INITIATOR[$__replicaDir]}" & pids="$!" if [ "$REMOTE_OPERATION" != "yes" ]; then - _CheckReplicaPathsLocal "${TARGET[$__replicaDir]}" & + _CheckReplicasLocal "${TARGET[$__replicaDir]}" & pids="$pids;$!" else - _CheckReplicaPathsRemote "${TARGET[$__replicaDir]}" & + _CheckReplicasRemote "${TARGET[$__replicaDir]}" & pids="$pids;$!" fi WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} @@ -279,84 +414,6 @@ function CheckReplicaPaths { fi } -function _CheckDiskSpaceLocal { - local replicaPath="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - local diskSpace - - Logger "Checking minimum disk space in [$replicaPath]." "NOTICE" - - diskSpace=$($DF_CMD "$replicaPath" | tail -1 | awk '{print $4}') - - if [ $? != 0 ]; then - Logger "Cannot get free space." "ERROR" - else - # Ugly fix for df in some busybox environments that can only show human formats - if [ $(IsInteger $diskSpace) -eq 0 ]; then - diskSpace=$(HumanToNumeric $diskSpace) - fi - - if [ $diskSpace -lt $MINIMUM_SPACE ]; then - Logger "There is not enough free space on replica [$replicaPath] ($diskSpace KB)." "WARN" - fi - fi -} - -function _CheckDiskSpaceRemote { - local replicaPath="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - Logger "Checking remote minimum disk space in [$replicaPath]." "NOTICE" - - local cmd - local diskSpace - - CheckConnectivity3rdPartyHosts - CheckConnectivityRemoteHost - -$SSH_CMD replicaPath="'$replicaPath'" COMMAND_SUDO="'$COMMAND_SUDO'" DF_CMD="'$DF_CMD'" bash -s << ENDSSH > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 -$COMMAND_SUDO $DF_CMD "$replicaPath" -ENDSSH - if [ $? != 0 ]; then - Logger "Cannot get free space on target [$replicaPath]." "ERROR" - Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE" - else - diskSpace=$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID | tail -1 | awk '{print $4}') - - # Ugly fix for df in some busybox environments that can only show human formats - if [ $(IsInteger $diskSpace) -eq 0 ]; then - diskSpace=$(HumanToNumeric $diskSpace) - fi - - if [ $diskSpace -lt $MINIMUM_SPACE ]; then - Logger "There is not enough free space on replica [$replicaPath] ($diskSpace KB)." "WARN" - fi - fi -} - -function CheckDiskSpace { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - - local pids - - if [ $MINIMUM_SPACE -eq 0 ]; then - Logger "Skipped minimum space check." "NOTICE" - return 0 - fi - - _CheckDiskSpaceLocal "${INITIATOR[$__replicaDir]}" & - pids="$!" - if [ "$REMOTE_OPERATION" != "yes" ]; then - _CheckDiskSpaceLocal "${TARGET[$__replicaDir]}" & - pids="$pids;$!" - else - _CheckDiskSpaceRemote "${TARGET[$__replicaDir]}" & - pids="$pids;$!" - fi - WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} -} - function _HandleLocksLocal { local replicaStateDir="${1}" local lockfile="${2}" @@ -582,7 +639,14 @@ ENDSSH if [ $? != 0 ]; then Logger "Remote lock handling failed." "CRITICAL" - Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" + fi + if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then + ( + _LOGGER_PREFIX="" + Logger "$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE" + ) + fi + if [ $? != 0 ]; then return 1 fi } @@ -1122,8 +1186,6 @@ function _deleteRemote { local deletionListFromReplica - local loggerPrefix - if [ "$replicaType" == "${INITIATOR[$__type]}" ]; then deletionListFromReplica="${TARGET[$__type]}" elif [ "$replicaType" == "${TARGET[$__type]}" ]; then @@ -1259,10 +1321,10 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$ ENDSSH if [ -s "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" ]; then - loggerPrefix="$_LOGGER_PREFIX" + ( _LOGGER_PREFIX="" Logger "$(cat $RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID)" "ERROR" - _LOGGER_PREFIX="$loggerPrefix" + ) fi ## Copy back the deleted failed file list @@ -1821,9 +1883,7 @@ function _SummaryFromFile { function Summary { __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - local loggerPrefix - - loggerPrefix="$_LOGGER_PREFIX" + ( _LOGGER_PREFIX="" Logger "Attrib updates: INITIATOR << >> TARGET" "ALWAYS" @@ -1842,8 +1902,7 @@ function Summary { _SummaryFromFile "${TARGET[$__replicaDir]}" "$RUN_DIR/$PROGRAM.delete.target.$SCRIPT_PID" "- >>" fi _SummaryFromFile "${INITIATOR[$__replicaDir]}" "$RUN_DIR/$PROGRAM.delete.initiator.$SCRIPT_PID" "- <<" - - _LOGGER_PREFIX="$loggerPrefix" + ) } function Init { @@ -2031,7 +2090,7 @@ function Init { function Main { __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - HandleLocks + #HandleLocks Sync } @@ -2343,8 +2402,7 @@ else SOFT_MAX_EXEC_TIME=0 HARD_MAX_EXEC_TIME=0 fi - CheckReplicaPaths - CheckDiskSpace + CheckReplicas RunBeforeHook Main if [ $? == 0 ]; then From 9735a83b35722f63e437dc057b5d3e75cc93935c Mon Sep 17 00:00:00 2001 From: deajan Date: Tue, 6 Dec 2016 22:51:19 +0100 Subject: [PATCH 04/25] Reverted test disable HandleLocks --- dev/n_osync.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index bb2e18e..a5634df 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -2090,7 +2090,7 @@ function Init { function Main { __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG - #HandleLocks + HandleLocks Sync } From 226bf33e298f6e1bc25e39838a9f99d958e291f2 Mon Sep 17 00:00:00 2001 From: deajan Date: Tue, 6 Dec 2016 23:24:02 +0100 Subject: [PATCH 05/25] Code compliance on ArrayContains --- dev/ofunctions.sh | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index 830cf52..2a14d88 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -1,7 +1,7 @@ #### MINIMAL-FUNCTION-SET BEGIN #### _OFUNCTIONS_VERSION=2.0 -_OFUNCTIONS_BUILD=2016120401 +_OFUNCTIONS_BUILD=2016120601 ## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr ## To use in a program, define the following variables: @@ -1006,17 +1006,21 @@ function urlDecode { ## Modified version of http://stackoverflow.com/a/8574392 ## Usage: arrayContains "needle" "${haystack[@]}" -arrayContains () { +function ArrayContains () { + local needle="${1}" + local haystack="${2}" local e - if [ "$2" == "" ]; then - echo 0 && return 0 + if [ "$needle" != "" ] && [ "$haystack" != "" ]; then + for e in "${@:2}"; do + if [ "$e" == "$needle" ]; then + echo 1 + return + fi + done fi - - for e in "${@:2}"; do - [[ "$e" == "$1" ]] && echo 1 && return 1 - done - echo 0 && return 0 + echo 0 + return } function GetLocalOS { From f14903cce57069bed3ffee342f7f9d4fa93b115a Mon Sep 17 00:00:00 2001 From: deajan Date: Wed, 7 Dec 2016 09:06:28 +0100 Subject: [PATCH 06/25] Remote functions should not log to files --- dev/n_osync.sh | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index a5634df..8c8e353 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,7 +4,7 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120605 +PROGRAM_BUILD=2016120701 IS_STABLE=no #TODO: replace _Logger & Logger in remote functions with ofunctions version dedicated to remote logging @@ -332,10 +332,9 @@ function _CheckReplicasRemoteSub { if [ ! -d "$replicaPath" ]; then if [ "$CREATE_DIRS" == "yes" ]; then - $COMMAND_SUDO mkdir -p "$replicaPath" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 + $COMMAND_SUDO mkdir -p "$replicaPath" if [ $? != 0 ]; then Logger "Cannot create remote replica path [$replicaPath]." "CRITICAL" - Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" exit 1 else Logger "Created remote replica path [$replicaPath]." "NOTICE" @@ -569,10 +568,9 @@ $SSH_CMD replicaStateDir="'$replicaStateDir'" initiatorRunningPidsFlat="(${initi function _HandleLocksRemoteSub { #WIP do not remote log to file as output is already logged from ssh if [ ! -d "$replicaStateDir" ]; then - $COMMAND_SUDO mkdir -p "$replicaStateDir" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 + $COMMAND_SUDO mkdir -p "$replicaStateDir" if [ $? != 0 ]; then Logger "Cannot create state dir [$replicaStateDir]." "CRITICAL" - Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "ERROR" return 1 fi fi @@ -621,10 +619,9 @@ function _HandleLocksRemoteSub { if [ $writeLocks != true ]; then return 1 else - $COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID" + $COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" if [ $? != 0 ]; then Logger "Could not create lock file on local $replicaType in [$lockfile]." "CRITICAL" - Logger "Command output\n$($RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID)" "NOTICE" return 1 else Logger "Locked local $replicaType replica in [$lockfile]." "DEBUG" From 7e44139325846999181a603f9d0723319d38d18a Mon Sep 17 00:00:00 2001 From: deajan Date: Wed, 7 Dec 2016 11:45:34 +0100 Subject: [PATCH 07/25] Minor adjustment to _Logger --- dev/ofunctions.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index 2a14d88..6474bde 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -1,7 +1,7 @@ #### MINIMAL-FUNCTION-SET BEGIN #### _OFUNCTIONS_VERSION=2.0 -_OFUNCTIONS_BUILD=2016120601 +_OFUNCTIONS_BUILD=2016120701 ## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr ## To use in a program, define the following variables: @@ -73,8 +73,10 @@ if [ -w /var/log ]; then LOG_FILE="/var/log/$PROGRAM.log" elif ([ "$HOME" != "" ] && [ -w "$HOME" ]); then LOG_FILE="$HOME/$PROGRAM.log" -else +elif [ -w . ]; then LOG_FILE="./$PROGRAM.log" +else + LOG_FILE="/tmp/$PROGRAM.log" fi ## Default directory where to store temporary run files @@ -101,15 +103,18 @@ function Dummy { sleep $SLEEP_TIME } +#### MINIMAL-FUNCTION-SET BEGIN #### # Sub function of Logger function _Logger { local logValue="${1}" # Log to file local stdValue="${2}" # Log to screeen local toStderr="${3:-false}" # Log to stderr instead of stdout - echo -e "$logValue" >> "$LOG_FILE" - # Current log file - echo -e "$logValue" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" + if [ "$logValue" != "" ]; then + echo -e "$logValue" >> "$LOG_FILE" + # Current log file + echo -e "$logValue" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" + fi if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then if [ $toStderr == true ]; then From 731fc81abf86a732ddd741f8fdc46653d7367a55 Mon Sep 17 00:00:00 2001 From: deajan Date: Wed, 7 Dec 2016 21:30:10 +0100 Subject: [PATCH 08/25] Made ofunctions "includable" --- dev/bootstrap.sh | 27 ++++ dev/merge.sh | 177 +++++++++++++++-------- dev/n_osync.sh | 361 ++++++++++++---------------------------------- dev/ofunctions.sh | 152 +++++++++++++------ 4 files changed, 345 insertions(+), 372 deletions(-) create mode 100755 dev/bootstrap.sh diff --git a/dev/bootstrap.sh b/dev/bootstrap.sh new file mode 100755 index 0000000..d595e6a --- /dev/null +++ b/dev/bootstrap.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +## dev pre-processor bootstrap rev 2016120701 +## Yeah !!! A really tech sounding name... In fact it's just include emulation in bash + +outputFileName="$0" + +source "merge.sh" +__PREPROCESSOR_PROGRAM=osync +__PREPROCESSOR_Constants + +cp "n_$__PREPROCESSOR_PROGRAM.sh" "$outputFileName.tmp.sh" +if [ $? != 0 ]; then + QuickLogger "Cannot copy original file [n_$__PREPROCESSOR_PROGRAM.sh] to [$outputFileName.tmp.sh]." "stderr" + exit 1 +fi +for subset in "${__PREPROCESSOR_SUBSETS[@]}"; do + __PREPROCESSOR_MergeSubset "$subset" "${subset//SUBSET/SUBSET END}" "ofunctions.sh" "$outputFileName.tmp.sh" +done +chmod +x "$0.tmp.sh" +if [ $? != 0 ]; then + QuickLogger "Cannot make [$outputFileName] executable.." "stderr" + exit 1 +fi + +"$outputFileName.tmp.sh" "$@" + diff --git a/dev/merge.sh b/dev/merge.sh index 994e635..a31236d 100755 --- a/dev/merge.sh +++ b/dev/merge.sh @@ -1,142 +1,195 @@ #!/usr/bin/env bash -## MERGE 2016112001 +## MERGE 2016120701 ## Merges ofunctions.sh and n_program.sh into program.sh ## Adds installer -PROGRAM=osync -VERSION=$(grep "PROGRAM_VERSION=" n_$PROGRAM.sh) -VERSION=${VERSION#*=} +function __PREPROCESSOR_Merge { + PROGRAM=osync + VERSION=$(grep "PROGRAM_VERSION=" n_$PROGRAM.sh) + VERSION=${VERSION#*=} -PARANOIA_DEBUG_LINE="__WITH_PARANOIA_DEBUG" -PARANOIA_DEBUG_BEGIN="#__BEGIN_WITH_PARANOIA_DEBUG" -PARANOIA_DEBUG_END="#__END_WITH_PARANOIA_DEBUG" -MINIMUM_FUNCTION_BEGIN="#### MINIMAL-FUNCTION-SET BEGIN ####" -MINIMUM_FUNCTION_END="#### MINIMAL-FUNCTION-SET END ####" + __PREPROCESSOR_Constants -source "ofunctions.sh" -if [ $? != 0 ]; then - echo "Please run $0 in dev directory with ofunctions.sh" - exit 1 -fi + source "ofunctions.sh" + if [ $? != 0 ]; then + echo "Please run $0 in dev directory with ofunctions.sh" + exit 1 + fi -function Unexpand { - unexpand n_$PROGRAM.sh > tmp_$PROGRAM.sh + __PREPROCESSOR_Unexpand "n_$PROGRAM.sh" "debug_$PROGRAM.sh" + + for subset in "${__PREPROCESSOR_SUBSETS[@]}"; do + __PREPROCESSOR_MergeSubset "$subset" "${subset//SUBSET/SUBSET END}" "ofunctions.sh" "debug_$PROGRAM.sh" + done + + #if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then + # MergeAll + #else + # MergeMinimum + #fi + __PREPROCESSOR_CleanDebug + __PREPROCESSOR_CopyCommons + rm -f tmp_$PROGRAM.sh + if [ $? != 0 ]; then + QuickLogger "Cannot remove tmp_$PROGRAM.sh" "stderr" + exit 1 + fi } -function MergeAll { +function __PREPROCESSOR_Constants { + PARANOIA_DEBUG_LINE="#__WITH_PARANOIA_DEBUG" + PARANOIA_DEBUG_BEGIN="#__BEGIN_WITH_PARANOIA_DEBUG" + PARANOIA_DEBUG_END="#__END_WITH_PARANOIA_DEBUG" + + __PREPROCESSOR_SUBSETS=( + '#### OFUNCTIONS FULL SUBSET ####' + '#### OFUNCTIONS MINIMAL SUBSET ####' + '#### DEBUG SUBSET ####' + '#### TrapError SUBSET ####' + '#### RemoteLogger SUBSET ####' + '#### IsInteger SUBSET ####' + '#### HumanToNumeric SUBSET ####' + '#### ArrayContains SUBSET ####' + ) +} + +function __PREPROCESSOR_Unexpand { + local source="${1}" + local destination="${2}" + + unexpand "$source" > "$destination" + if [ $? != 0 ]; then + QuickLogger "Cannot unexpand [$source] to [$destination]." "stderr" + exit 1 + fi +} + +function __PREPROCESSOR_MergeAll { sed "/source \"\.\/ofunctions.sh\"/r ofunctions.sh" tmp_$PROGRAM.sh | grep -v 'source "./ofunctions.sh"' > debug_$PROGRAM.sh if [ $? != 0 ]; then - QuickLogger "Cannot sed ofunctions" "stdout" - exit 1 - fi - chmod +x debug_$PROGRAM.sh - if [ $? != 0 ]; then - QuickLogger "Cannot chmod $PROGRAM.sh" "stdout" + QuickLogger "Cannot sed ofunctions" "stderr" exit 1 fi } -function MergeMinimum { +function __PREPROCESSOR_MergeMinimum { sed -n "/$MINIMUM_FUNCTION_BEGIN/,/$MINIMUM_FUNCTION_END/p" ofunctions.sh > tmp_minimal.sh if [ $? != 0 ]; then - QuickLogger "Cannot sed minimum functions." "stdout" + QuickLogger "Cannot sed minimum functions." "stderr" exit 1 fi sed "/source \"\.\/ofunctions.sh\"/r tmp_minimal.sh" tmp_$PROGRAM.sh | grep -v 'source "./ofunctions.sh"' | grep -v "$PARANOIA_DEBUG_LINE" > debug_$PROGRAM.sh if [ $? != 0 ]; then - QuickLogger "Cannot remove PARANOIA_DEBUG code from tmp_minimum.." "stdout" + QuickLogger "Cannot remove PARANOIA_DEBUG code from tmp_minimum." "stderr" exit 1 fi rm -f tmp_minimal.sh if [ $? != 0 ]; then - QuickLogger "Cannot remove tmp_minimal.sh" "stdout" + QuickLogger "Cannot remove tmp_minimal.sh" "stderr" exit 1 fi chmod +x debug_$PROGRAM.sh if [ $? != 0 ]; then - QuickLogger "Cannot chmod debug_$PROGRAM.sh" "stdout" + QuickLogger "Cannot chmod debug_$PROGRAM.sh" "stderr" exit 1 fi } +function __PREPROCESSOR_MergeSubset { + local subsetBegin="${1}" + local subsetEnd="${2}" + local subsetFile="${3}" + local mergedFile="${4}" -function CleanDebug { + sed -n "/$subsetBegin/,/$subsetEnd/p" "$subsetFile" > "$subsetFile.$subsetBegin" + if [ $? != 0 ]; then + QuickLogger "Cannot sed subset [$subsetBegin -- $subsetEnd] in [$subsetFile]." "stderr" + exit 1 + fi + sed "/include $subsetBegin/r $subsetFile.$subsetBegin" "$mergedFile" | grep -v -E "$subsetBegin\$|$subsetEnd\$" > "$mergedFile.tmp" + if [ $? != 0 ]; then + QuickLogger "Cannot add subset [$subsetBegin] to [$mergedFile]." "stderr" + exit 1 + fi + rm -f "$subsetFile.$subsetBegin" + if [ $? != 0 ]; then + QuickLogger "Cannot remove temporary subset [$subsetFile.$subsetBeign]." "stderr" + exit 1 + fi -# sed explanation -#/pattern1/{ # if pattern1 is found -# p # print it -# :a # loop -# N # and accumulate lines -# /pattern2/!ba # until pattern2 is found -# s/.*\n// # delete the part before pattern2 -#} -#p -# sed -n '/'$PARANOIA_DEBUG_BEGIN'/{p; :a; N; /'$PARANOIA_DEBUG_END'/!ba; s/.*\n//}; p' debug_$PROGRAM.sh | grep -v "$PARANOIA_DEBUG_LINE" > ../$PROGRAM.sh + rm -f "$mergedFile" + if [ $? != 0 ]; then + QuickLogger "Cannot remove merged original file [$mergedFile]." "stderr" + exit 1 + fi - # Way simpler version of the above, compatible with BSD + mv "$mergedFile.tmp" "$mergedFile" + if [ $? != 0 ]; then + QuickLogger "Cannot move merged tmp file to original [$mergedFile]." "stderr" + exit 1 + fi +} + +function __PREPROCESSOR_CleanDebug { sed '/'$PARANOIA_DEBUG_BEGIN'/,/'$PARANOIA_DEBUG_END'/d' debug_$PROGRAM.sh | grep -v "$PARANOIA_DEBUG_LINE" > ../$PROGRAM.sh if [ $? != 0 ]; then - QuickLogger "Cannot remove PARANOIA_DEBUG code from standard build." "stdout" + QuickLogger "Cannot remove PARANOIA_DEBUG code from standard build." "stderr" exit 1 fi - chmod +x ../$PROGRAM.sh + chmod +x "debug_$PROGRAM.sh" if [ $? != 0 ]; then - QuickLogger "Cannot chmod $PROGRAM.sh" "stdout" + QuickLogger "Cannot chmod debug_$PROGRAM.sh" "stderr" + exit 1 + fi + chmod +x "../$PROGRAM.sh" + if [ $? != 0 ]; then + QuickLogger "Cannot chmod $PROGRAM.sh" "stderr" exit 1 fi } -function CopyCommons { +function __PREPROCESSOR_CopyCommons { sed "s/\[prgname\]/$PROGRAM/g" common_install.sh > ../tmp_install.sh if [ $? != 0 ]; then - QuickLogger "Cannot assemble install." "stdout" + QuickLogger "Cannot assemble install." "stderr" exit 1 fi sed "s/\[version\]/$VERSION/g" ../tmp_install.sh > ../install.sh if [ $? != 0 ]; then - QuickLogger "Cannot change install version." "stdout" + QuickLogger "Cannot change install version." "stderr" exit 1 fi if [ -f "common_batch.sh" ]; then sed "s/\[prgname\]/$PROGRAM/g" common_batch.sh > ../$PROGRAM-batch.sh if [ $? != 0 ]; then - QuickLogger "Cannot assemble batch runner." "stdout" + QuickLogger "Cannot assemble batch runner." "stderr" exit 1 fi chmod +x ../$PROGRAM-batch.sh if [ $? != 0 ]; then - QuickLogger "Cannot chmod $PROGRAM-batch.sh" "stdout" + QuickLogger "Cannot chmod $PROGRAM-batch.sh" "stderr" exit 1 fi fi chmod +x ../install.sh if [ $? != 0 ]; then - QuickLogger "Cannot chmod install.sh" "stdout" + QuickLogger "Cannot chmod install.sh" "stderr" exit 1 fi rm -f ../tmp_install.sh if [ $? != 0 ]; then - QuickLogger "Cannot chmod $PROGRAM.sh" "stdout" + QuickLogger "Cannot chmod $PROGRAM.sh" "stderr" exit 1 fi } -Unexpand -if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then - MergeAll -else - MergeMinimum -fi -CleanDebug -CopyCommons -rm -f tmp_$PROGRAM.sh -if [ $? != 0 ]; then - QuickLogger "Cannot remove tmp_$PROGRAM.sh" "stdout" - exit 1 +# If sourced don't do anything +if [ "$(basename $0)" == "merge.sh" ]; then + __PREPROCESSOR_Merge fi diff --git a/dev/n_osync.sh b/dev/n_osync.sh index 8c8e353..100d942 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,12 +4,11 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120701 +PROGRAM_BUILD=2016120702 IS_STABLE=no -#TODO: replace _Logger & Logger in remote functions with ofunctions version dedicated to remote logging -#TODO: replace ArrayContains, IsNumeric, HumanToNumeric with ofunctions version via merge -#TODO: deal with _VERBOSE / _SILENT switches in remote Logger +#TODO: update waitfor parallelexec and checkarguments +#TODO: update coding style checkarguments # Execution order #__WITH_PARANOIA_DEBUG # Function Name Is parallel #__WITH_PARANOIA_DEBUG @@ -44,7 +43,7 @@ IS_STABLE=no # UnlockReplicas yes #__WITH_PARANOIA_DEBUG # CleanUp no #__WITH_PARANOIA_DEBUG -source "./ofunctions.sh" +include #### OFUNCTIONS FULL SUBSET #### _LOGGER_PREFIX="time" ## Working directory. This directory exists in any replica and contains state files, backups, soft deleted files etc @@ -117,7 +116,7 @@ function TrapQuit { } function CheckEnvironment { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG if [ "$REMOTE_OPERATION" == "yes" ]; then if ! type ssh > /dev/null 2>&1 ; then @@ -139,7 +138,7 @@ function CheckEnvironment { # Only gets checked in config file mode where all values should be present function CheckCurrentConfig { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG # Check all variables that should contain "yes" or "no" declare -a yes_no_vars=(CREATE_DIRS SUDO_EXEC SSH_COMPRESSION SSH_IGNORE_KNOWN_HOSTS REMOTE_HOST_PING PRESERVE_PERMISSIONS PRESERVE_OWNER PRESERVE_GROUP PRESERVE_EXECUTABILITY PRESERVE_ACL PRESERVE_XATTR COPY_SYMLINKS KEEP_DIRLINKS PRESERVE_HARDLINKS CHECKSUM RSYNC_COMPRESS CONFLICT_BACKUP CONFLICT_BACKUP_MULTIPLE SOFT_DELETE RESUME_SYNC FORCE_STRANGER_LOCK_RESUME PARTIAL DELTA_COPIES STOP_ON_CMD_ERROR RUN_AFTER_CMD_ON_ERROR) @@ -158,7 +157,7 @@ function CheckCurrentConfig { # Gets checked in quicksync and config file mode function CheckCurrentConfigAll { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local tmp @@ -196,7 +195,7 @@ function CheckCurrentConfigAll { function _CheckReplicasLocal { local replicaPath="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG local diskSpace @@ -239,121 +238,45 @@ function _CheckReplicasLocal { function _CheckReplicasRemote { local replicaPath="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG local cmd CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost -$SSH_CMD replicaPath="'$replicaPath'" CREATE_DIRS="'$CREATE_DIRS'" COMMAND_SUDO="'$COMMAND_SUDO'" DF_CMD="'$DF_CMD'" MINIMUM_SPACE="'$MINIMUM_SPACE'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 - ## The following lines are executed remotely - function _logger { - local value="${1}" # What to log - echo -e "$value" - } - - function Logger { - local value="${1}" # What to log - local level="${2}" # Log level: DEBUG, NOTICE, WARN, ERROR, CRITIAL - - local prefix="RTIME: $SECONDS - " - - if [ "$level" == "CRITICAL" ]; then - _logger "$prefix\e[41m$value\e[0m" - return - elif [ "$level" == "ERROR" ]; then - _logger "$prefix\e[91m$value\e[0m" - return - elif [ "$level" == "WARN" ]; then - _logger "$prefix\e[93m$value\e[0m" - return - elif [ "$level" == "NOTICE" ]; then - _logger "$prefix$value" - return - elif [ "$level" == "VERBOSE" ]; then - if [ $_LOGGER_VERBOSE == true ]; then - _logger "$prefix$value" - fi - return - elif [ "$level" == "DEBUG" ]; then - if [ "$_DEBUG" == "yes" ]; then - _logger "$prefix$value" - fi - return - else - _logger "\e[41mLogger function called without proper loglevel [$level].\e[0m" - _logger "$prefix$value" - fi - } - -function IsInteger { - local value="${1}" - - if [[ $value =~ ^[0-9]+$ ]]; then - echo 1 - else - echo 0 - fi -} - -# Converts human readable sizes into integer kilobyte sizes -# Usage numericSize="$(HumanToNumeric $humanSize)" -function HumanToNumeric { - local value="${1}" - - local notation - local suffix - local suffixPresent - local multiplier - - notation=(K M G T P E) - for suffix in "${notation[@]}"; do - multiplier=$((multiplier+1)) - if [[ "$value" == *"$suffix"* ]]; then - suffixPresent=$suffix - break; - fi - done - - if [ "$suffixPresent" != "" ]; then - value=${value%$suffix*} - value=${value%.*} - # /1024 since we convert to kilobytes instead of bytes - value=$((value*(1024**multiplier/1024))) - else - value=${value%.*} - fi - - echo $value -} - +$SSH_CMD _DEBUG="'$_DEBUG'" _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" _LOGGER_SILENT="'$_LOGGER_SILENT'" _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _LOGGER_PREFIX="'$_LOGGER_PREFIX'" _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" replicaPath="'$replicaPath'" CREATE_DIRS="'$CREATE_DIRS'" COMMAND_SUDO="'$COMMAND_SUDO'" DF_CMD="'$DF_CMD'" MINIMUM_SPACE="'$MINIMUM_SPACE'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +include #### DEBUG SUBSET #### +include #### TrapError SUBSET #### +include #### IsInteger SUBSET #### +include #### HumanToNumeric SUBSET #### +include #### RemoteLogger SUBSET #### function _CheckReplicasRemoteSub { if [ ! -d "$replicaPath" ]; then if [ "$CREATE_DIRS" == "yes" ]; then $COMMAND_SUDO mkdir -p "$replicaPath" if [ $? != 0 ]; then - Logger "Cannot create remote replica path [$replicaPath]." "CRITICAL" + RemoteLogger "Cannot create remote replica path [$replicaPath]." "CRITICAL" exit 1 else - Logger "Created remote replica path [$replicaPath]." "NOTICE" + RemoteLogger "Created remote replica path [$replicaPath]." "NOTICE" fi else - Logger "Remote replica path [$replicaPath] does not exist." "CRITICAL" + RemoteLogger "Remote replica path [$replicaPath] does not exist." "CRITICAL" exit 1 fi fi if [ ! -w "$replicaPath" ]; then - Logger "Remote replica path [$replicaPath] is not writable." "CRITICAL" + RemoteLogger "Remote replica path [$replicaPath] is not writable." "CRITICAL" exit 1 fi - Logger "Checking minimum disk space in remote replica [$replicaPath]." "NOTICE" + RemoteLogger "Checking minimum disk space in remote replica [$replicaPath]." "NOTICE" diskSpace=$($DF_CMD "$replicaPath" | tail -1 | awk '{print $4}') if [ $? != 0 ]; then - Logger "Cannot get free space." "ERROR" + RemoteLogger "Cannot get free space." "ERROR" else # Ugly fix for df in some busybox environments that can only show human formats if [ $(IsInteger $diskSpace) -eq 0 ]; then @@ -361,7 +284,7 @@ function _CheckReplicasRemoteSub { fi if [ $diskSpace -lt $MINIMUM_SPACE ]; then - Logger "There is not enough free space on remote replica [$replicaPath] ($diskSpace KB)." "WARN" + RemoteLogger "There is not enough free space on remote replica [$replicaPath] ($diskSpace KB)." "WARN" fi fi } @@ -386,7 +309,7 @@ ENDSSH } function CheckReplicas { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local pids @@ -406,7 +329,7 @@ function CheckReplicas { _CheckReplicasRemote "${TARGET[$__replicaDir]}" & pids="$pids;$!" fi - WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} + WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then Logger "Cancelling task." "CRITICAL" exit 1 @@ -419,7 +342,7 @@ function _HandleLocksLocal { local replicaType="${3}" local overwrite="${4:-false}" - __CheckArguments 4 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 4 $# "$@" #__WITH_PARANOIA_DEBUG local lockfileContent local lockPid @@ -485,7 +408,7 @@ function _HandleLocksRemote { local replicaType="${3}" local overwrite="${4:-false}" - __CheckArguments 4 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 4 $# "$@" #__WITH_PARANOIA_DEBUG local initiatorRunningPids @@ -497,80 +420,19 @@ function _HandleLocksRemote { read -a initiatorRunningPids <<< $(ps -A | tail -n +2 | awk '{print $1}') # passing initiatorRunningPids as litteral string (has to be run through eval to be an array again) -$SSH_CMD replicaStateDir="'$replicaStateDir'" initiatorRunningPidsFlat="(${initiatorRunningPids[@]})" lockfile="'$lockfile'" replicaType="'$replicaType'" overwrite="'$overwrite'" SCRIPT_PID="'$SCRIPT_PID'" INSTANCE_ID="'$INSTANCE_ID'" FORCE_STRANGER_LOCK_RESUME="'$FORCE_STRANGER_LOCK_RESUME'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 - function ArrayContains () { - local needle="${1}" - local haystack="${@:2}" - local e - - if [ "$needle" != "" ] && [ "$haystack" != "" ]; then - for e in "${@:2}"; do - if [ "$e" == "$needle" ]; then - echo 1 - return - fi - done - fi - echo 0 - return - } - - function IsInteger { - local value="${1}" - - if [[ $value =~ ^[0-9]+$ ]]; then - echo 1 - else - echo 0 - fi - } - - ## The following lines are executed remotely - function _logger { - local value="${1}" # What to log - echo -e "$value" - } - - function Logger { - local value="${1}" # What to log - local level="${2}" # Log level: DEBUG, NOTICE, WARN, ERROR, CRITIAL - - local prefix="RTIME: $SECONDS - " - - if [ "$level" == "CRITICAL" ]; then - _logger "$prefix\e[41m$value\e[0m" - return - elif [ "$level" == "ERROR" ]; then - _logger "$prefix\e[91m$value\e[0m" - return - elif [ "$level" == "WARN" ]; then - _logger "$prefix\e[93m$value\e[0m" - return - elif [ "$level" == "NOTICE" ]; then - _logger "$prefix$value" - return - elif [ "$level" == "VERBOSE" ]; then - if [ $_LOGGER_VERBOSE == true ]; then - _logger "$prefix$value" - fi - return - elif [ "$level" == "DEBUG" ]; then - if [ "$_DEBUG" == "yes" ]; then - _logger "$prefix$value" - fi - return - else - _logger "\e[41mLogger function called without proper loglevel [$level].\e[0m" - _logger "$prefix$value" - fi - } +$SSH_CMD _DEBUG="'$_DEBUG'" _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" _LOGGER_SILENT="'$_LOGGER_SILENT'" _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _LOGGER_PREFIX="'$_LOGGER_PREFIX'" _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" replicaStateDir="'$replicaStateDir'" initiatorRunningPidsFlat="(${initiatorRunningPids[@]})" lockfile="'$lockfile'" replicaType="'$replicaType'" overwrite="'$overwrite'" SCRIPT_PID="'$SCRIPT_PID'" INSTANCE_ID="'$INSTANCE_ID'" FORCE_STRANGER_LOCK_RESUME="'$FORCE_STRANGER_LOCK_RESUME'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +include #### DEBUG SUBSET #### +include #### TrapError SUBSET #### +incldue #### ArrayContains SUBSET #### +include #### IsInteger SUBSET #### +include #### RemoteLogger SUBSET #### function _HandleLocksRemoteSub { #WIP do not remote log to file as output is already logged from ssh if [ ! -d "$replicaStateDir" ]; then $COMMAND_SUDO mkdir -p "$replicaStateDir" if [ $? != 0 ]; then - Logger "Cannot create state dir [$replicaStateDir]." "CRITICAL" + RemoteLogger "Cannot create state dir [$replicaStateDir]." "CRITICAL" return 1 fi fi @@ -578,18 +440,18 @@ function _HandleLocksRemoteSub { # Skip the whole part if overwrite true if [ -s "$lockfile" ] && [ $overwrite != true ]; then lockfileContent=$(cat $lockfile) - Logger "Master lock pid present: $lockfileContent" "DEBUG" + RemoteLogger "Master lock pid present: $lockfileContent" "DEBUG" lockPid="${lockfileContent%@*}" if [ $(IsInteger $lockPid) -ne 1 ]; then - Logger "Invalid pid [$lockPid] in local replica." "CRITICAL" + RemoteLogger "Invalid pid [$lockPid] in local replica." "CRITICAL" return 1 fi lockInstanceID="${lockfileContent#*@}" if [ "$lockInstanceID" == "" ]; then - Logger "Invalid instance id [$lockInstanceID] in local replica." "CRITICAL" + RemoteLogger "Invalid instance id [$lockInstanceID] in local replica." "CRITICAL" return 1 - Logger "Local $replicaType lock is: [$lockPid@$lockInstanceID]." "DEBUG" + RemoteLogger "Local $replicaType lock is: [$lockPid@$lockInstanceID]." "DEBUG" fi @@ -597,19 +459,19 @@ function _HandleLocksRemoteSub { eval "initiatorRunningPids=$initiatorRunningPidsFlat" if [ $(ArrayContains "$lockPid" "${initiatorRunningPids[@]}") -eq 0 ]; then if [ "$lockInstanceID" == "$INSTANCE_ID" ]; then - Logger "There is a remote dead osync lock [$lockPid@$lockInstanceID] on target replica that corresponds to this initiator INSTANCE_ID. Pid [$lockPid] no longer running. Resuming." "NOTICE" + RemoteLogger "There is a remote dead osync lock [$lockPid@$lockInstanceID] on target replica that corresponds to this initiator INSTANCE_ID. Pid [$lockPid] no longer running. Resuming." "NOTICE" writeLocks=true else if [ "$FORCE_STRANGER_LOCK_RESUME" == "yes" ]; then - Logger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Forcing resume." "WARN" + RemoteLogger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Forcing resume." "WARN" writeLocks=true else - Logger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Will not resume." "CRITICAL" + RemoteLogger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Will not resume." "CRITICAL" return 1 fi fi else - Logger "There is already a local instance of osync that locks target replica [$lockPid@$lockInstanceID]. Cannot start." "CRITICAL" + RemoteLogger "There is already a local instance of osync that locks target replica [$lockPid@$lockInstanceID]. Cannot start." "CRITICAL" return 1 fi else @@ -621,10 +483,10 @@ function _HandleLocksRemoteSub { else $COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" if [ $? != 0 ]; then - Logger "Could not create lock file on local $replicaType in [$lockfile]." "CRITICAL" + RemoteLogger "Could not create lock file on local $replicaType in [$lockfile]." "CRITICAL" return 1 else - Logger "Locked local $replicaType replica in [$lockfile]." "DEBUG" + RemoteLogger "Locked local $replicaType replica in [$lockfile]." "DEBUG" fi fi } @@ -649,7 +511,7 @@ ENDSSH } function HandleLocks { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local pids local overwrite=false @@ -673,7 +535,7 @@ function HandleLocks { fi INITIATOR_LOCK_FILE_EXISTS=true TARGET_LOCK_FILE_EXISTS=true - WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} + WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false if [ $? -ne 0 ]; then IFS=';' read -r -a pidArray <<< "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_${FUNCNAME[0]}\")" for pid in "${pidArray[@]}"; do @@ -693,7 +555,7 @@ function HandleLocks { function _UnlockReplicasLocal { local lockfile="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG if [ -f "$lockfile" ]; then $COMMAND_SUDO rm "$lockfile" @@ -707,7 +569,7 @@ function _UnlockReplicasLocal { function _UnlockReplicasRemote { local lockfile="${1}" - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG local cmd= @@ -728,7 +590,7 @@ ENDSSH } function UnlockReplicas { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local pids @@ -752,7 +614,7 @@ function UnlockReplicas { fi if [ "$pids" != "" ]; then - WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false ${FUNCNAME[0]} + WaitForTaskCompletion $pids 720 1800 $SLEEP_TIME $KEEP_LOGGING true true false fi } @@ -768,7 +630,7 @@ function treeList { local replicaType="${2}" # replica type: initiator, target local treeFilename="${3}" # filename to output tree (will be prefixed with $replicaType) - __CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 3 $# "$@" #__WITH_PARANOIA_DEBUG local escapedReplicaPath local rsyncCmd @@ -816,7 +678,7 @@ function treeList { # deleteList(replicaType): Creates a list of files vanished from last run on replica $1 (initiator/target) function deleteList { local replicaType="${1}" # replica type: initiator, target - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG local cmd @@ -865,7 +727,7 @@ function _getFileCtimeMtimeLocal { local replicaPath="${1}" # Contains replica path local replicaType="${2}" # Initiator / Target local fileList="${3}" # Contains list of files to get time attrs - __CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 3 $# "$@" #__WITH_PARANOIA_DEBUG echo -n "" > "$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" while read -r file; do $STAT_CTIME_MTIME_CMD "$replicaPath$file" | sort >> "$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID"; done < "$fileList" @@ -883,7 +745,7 @@ function _getFileCtimeMtimeRemote { local replicaPath="${1}" # Contains replica path local replicaType="${2}" local fileList="${3}" - __CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 3 $# "$@" #__WITH_PARANOIA_DEBUG local cmd @@ -905,7 +767,7 @@ function _getFileCtimeMtimeRemote { function syncAttrs { local initiatorReplica="${1}" local targetReplica="${2}" - __CheckArguments 2 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG local rsyncCmd local retval @@ -932,7 +794,7 @@ function syncAttrs { fi Logger "RSYNC_CMD: $rsyncCmd" "DEBUG" eval "$rsyncCmd" - WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false retval=$? if [ $retval != 0 ] && [ $retval != 24 ]; then @@ -964,7 +826,7 @@ function syncAttrs { _getFileCtimeMtimeRemote "${TARGET[$__replicaDir]}" "${TARGET[$__type]}" "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}-cleaned.$SCRIPT_PID" & pids="$pids;$!" fi - WaitForTaskCompletion $pids $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $pids $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false # If target gets updated first, then sync_attr must update initiators attrs first # For join, remove leading replica paths @@ -1012,7 +874,7 @@ function syncAttrs { Logger "RSYNC_CMD: $rsyncCmd" "DEBUG" eval "$rsyncCmd" - WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false retval=$? if [ $retval != 0 ] && [ $retval != 24 ]; then @@ -1033,7 +895,7 @@ function syncAttrs { function syncUpdate { local sourceReplica="${1}" # Contains replica type of source: initiator, target local destinationReplica="${2}" # Contains replica type of destination: initiator, target - __CheckArguments 2 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG local rsyncCmd local retval @@ -1096,7 +958,7 @@ function _deleteLocal { local replicaType="${1}" # Replica type local replicaDir="${2}" # Full path to replica local deletionDir="${3}" # deletion dir in format .[workdir]/deleted - __CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 3 $# "$@" #__WITH_PARANOIA_DEBUG local parentdir local previousFile="" @@ -1173,7 +1035,7 @@ function _deleteRemote { local replicaType="${1}" # Replica type local replicaDir="${2}" # Full path to replica local deletionDir="${3}" # deletion dir in format .[workdir]/deleted - __CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 3 $# "$@" #__WITH_PARANOIA_DEBUG local escDestDir local rsyncCmd @@ -1211,47 +1073,10 @@ function _deleteRemote { exit 1 fi -$SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$_DRYRUN _LOGGER_VERBOSE=$_LOGGER_VERBOSE COMMAND_SUDO=$COMMAND_SUDO FILE_LIST="$(EscapeSpaces "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}/$deletionListFromReplica${INITIATOR[$__deletedListFile]}")" REPLICA_DIR="$(EscapeSpaces "$replicaDir")" SOFT_DELETE=$SOFT_DELETE DELETION_DIR="$(EscapeSpaces "$deletionDir")" FAILED_DELETE_LIST="$failedDeleteList" SUCCESS_DELETE_LIST="$successDeleteList" 'bash -s' << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" 2>&1 - - ## The following lines are executed remotely - function _logger { - local value="${1}" # What to log - echo -e "$value" - } - - function Logger { - local value="${1}" # What to log - local level="${2}" # Log level: DEBUG, NOTICE, WARN, ERROR, CRITIAL - - local prefix="RTIME: $SECONDS - " - - if [ "$level" == "CRITICAL" ]; then - _logger "$prefix\e[41m$value\e[0m" - return - elif [ "$level" == "ERROR" ]; then - _logger "$prefix\e[91m$value\e[0m" - return - elif [ "$level" == "WARN" ]; then - _logger "$prefix\e[93m$value\e[0m" - return - elif [ "$level" == "NOTICE" ]; then - _logger "$prefix$value" - return - elif [ "$level" == "VERBOSE" ]; then - if [ $_LOGGER_VERBOSE == true ]; then - _logger "$prefix$value" - fi - return - elif [ "$level" == "DEBUG" ]; then - if [ "$_DEBUG" == "yes" ]; then - _logger "$prefix$value" - fi - return - else - _logger "\e[41mLogger function called without proper loglevel [$level].\e[0m" - _logger "$prefix$value" - fi - } +$SSH_CMD _DEBUG="'$_DEBUG'" _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" _LOGGER_SILENT="'$_LOGGER_SILENT'" _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _LOGGER_PREFIX="'$_LOGGER_PREFIX'" _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$_DRYRUN COMMAND_SUDO=$COMMAND_SUDO FILE_LIST="$(EscapeSpaces "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}/$deletionListFromReplica${INITIATOR[$__deletedListFile]}")" REPLICA_DIR="$(EscapeSpaces "$replicaDir")" SOFT_DELETE=$SOFT_DELETE DELETION_DIR="$(EscapeSpaces "$deletionDir")" FAILED_DELETE_LIST="$failedDeleteList" SUCCESS_DELETE_LIST="$successDeleteList" 'bash -s' << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" 2>&1 +include #### DEBUG SUBSET #### +include #### TrapError SUBSET #### +include #### RemoteLogger SUBSET #### ## Empty earlier failed delete list > "$FAILED_DELETE_LIST" @@ -1263,7 +1088,7 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$ if [ ! -d "$REPLICA_DIR$DELETION_DIR" ] && [ $_DRYRUN == false ]; then $COMMAND_SUDO mkdir -p "$REPLICA_DIR$DELETION_DIR" if [ $? != 0 ]; then - Logger "Cannot create remote replica deletion directory in [$REPLICA_DIR$DELETION_DIR]." "ERROR" + RemoteLogger "Cannot create remote replica deletion directory in [$REPLICA_DIR$DELETION_DIR]." "ERROR" exit 1 fi fi @@ -1282,15 +1107,15 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$ # In order to keep full path on soft deletion, create parent directories before move parentdir="$(dirname "$files")" if [ "$parentdir" != "." ]; then - Logger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR/$parentdir]." "VERBOSE" + RemoteLogger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR/$parentdir]." "VERBOSE" $COMMAND_SUDO mkdir -p "$REPLICA_DIR$DELETION_DIR/$parentdir" $COMMAND_SUDO mv -f "$REPLICA_DIR$files" "$REPLICA_DIR$DELETION_DIR/$parentdir" else - Logger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR]." "VERBOSE" + RemoteLogger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR]." "VERBOSE" $COMMAND_SUDO mv -f "$REPLICA_DIR$files" "$REPLICA_DIR$DELETION_DIR" fi if [ $? != 0 ]; then - Logger "Cannot move [$REPLICA_DIR$files] to deletion directory." "ERROR" + RemoteLogger "Cannot move [$REPLICA_DIR$files] to deletion directory." "ERROR" # Using $files instead of $REPLICA_DIR$files here so the list is ready for next run echo "$files" >> "$FAILED_DELETE_LIST" else @@ -1301,10 +1126,10 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$ else if [ $_DRYRUN == false ]; then if [ -e "$REPLICA_DIR$files" ] || [ -e "$REPLICA_DIR$files" ]; then - Logger "Deleting [$REPLICA_DIR$files]." "VERBOSE" + RemoteLogger "Deleting [$REPLICA_DIR$files]." "VERBOSE" $COMMAND_SUDO rm -rf "$REPLICA_DIR$files" if [ $? != 0 ]; then - Logger "Cannot delete [$REPLICA_DIR$files]." "ERROR" + RemoteLogger "Cannot delete [$REPLICA_DIR$files]." "ERROR" echo "$files" >> "$FAILED_DELETE_LIST" else echo "$files" >> "$SUCCESS_DELETE_LIST" @@ -1343,7 +1168,7 @@ ENDSSH # delete_Propagation(replica type) function deletionPropagation { local replicaType="${1}" # Contains replica type: initiator, target where to delete - __CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG local replicaDir local deleteDir @@ -1403,7 +1228,7 @@ function deletionPropagation { ###### Step 5a & 5b: Create after run file list of replicas function Sync { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local resumeCount local resumeInitiator @@ -1476,7 +1301,7 @@ function Sync { targetPid="$!" fi - WaitForTaskCompletion "$initiatorPid;$targetPid" $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion "$initiatorPid;$targetPid" $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then IFS=';' read -r -a pidArray <<< "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_${FUNCNAME[0]}\")" initiatorFail=false @@ -1521,7 +1346,7 @@ function Sync { targetPid="$!" fi - WaitForTaskCompletion "$initiatorPid;$targetPid" $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion "$initiatorPid;$targetPid" $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then IFS=';' read -r -a pidArray <<< "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_${FUNCNAME[0]}\")" initiatorFail=false @@ -1558,7 +1383,7 @@ function Sync { if [ "$resumeInitiator" == "${SYNC_ACTION[2]}" ] || [ "$resumeTarget" == "${SYNC_ACTION[2]}" ]; then if [[ "$RSYNC_ATTR_ARGS" == *"-X"* ]] || [[ "$RSYNC_ATTR_ARGS" == *"-A"* ]]; then syncAttrs "${INITIATOR[$__replicaDir]}" "$TARGET_SYNC_DIR" - WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then echo "${SYNC_ACTION[2]}" > "${INITIATOR[$__initiatorLastActionFile]}" echo "${SYNC_ACTION[2]}" > "${INITIATOR[$__targetLastActionFile]}" @@ -1583,7 +1408,7 @@ function Sync { if [ "$CONFLICT_PREVALANCE" == "${TARGET[$__type]}" ]; then if [ "$resumeTarget" == "${SYNC_ACTION[3]}" ]; then syncUpdate "${TARGET[$__type]}" "${INITIATOR[$__type]}" & - WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then echo "${SYNC_ACTION[3]}" > "${INITIATOR[$__targetLastActionFile]}" resumeTarget="${SYNC_ACTION[3]}" @@ -1595,7 +1420,7 @@ function Sync { fi if [ "$resumeInitiator" == "${SYNC_ACTION[3]}" ]; then syncUpdate "${INITIATOR[$__type]}" "${TARGET[$__type]}" - WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then echo "${SYNC_ACTION[3]}" > "${INITIATOR[$__initiatorLastActionFile]}" resumeInitiator="${SYNC_ACTION[3]}" @@ -1608,7 +1433,7 @@ function Sync { else if [ "$resumeInitiator" == "${SYNC_ACTION[3]}" ]; then syncUpdate "${INITIATOR[$__type]}" "${TARGET[$__type]}" - WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then echo "${SYNC_ACTION[3]}" > "${INITIATOR[$__initiatorLastActionFile]}" resumeInitiator="${SYNC_ACTION[3]}" @@ -1620,7 +1445,7 @@ function Sync { fi if [ "$resumeTarget" == "${SYNC_ACTION[3]}" ]; then syncUpdate "${TARGET[$__type]}" "${INITIATOR[$__type]}" - WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then echo "${SYNC_ACTION[3]}" > "${INITIATOR[$__targetLastActionFile]}" resumeTarget="${SYNC_ACTION[3]}" @@ -1645,7 +1470,7 @@ function Sync { targetPid="$!" fi - WaitForTaskCompletion "$initiatorPid;$targetPid" $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion "$initiatorPid;$targetPid" $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then IFS=';' read -r -a pidArray <<< "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_${FUNCNAME[0]}\")" initiatorFail=false @@ -1691,7 +1516,7 @@ function Sync { targetPid="$!" fi - WaitForTaskCompletion "$initiatorPid;$targetPid" $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion "$initiatorPid;$targetPid" $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ]; then IFS=';' read -r -a pidArray <<< "$(eval echo \"\$WAIT_FOR_TASK_COMPLETION_${FUNCNAME[0]}\")" initiatorFail=false @@ -1734,7 +1559,7 @@ function _SoftDeleteLocal { local changeTime="${3}" # Delete files older than changeTime days local deletionType="${4}" # Trivial deletion type string - __CheckArguments 4 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 4 $# "$@" #__WITH_PARANOIA_DEBUG local retval @@ -1783,7 +1608,7 @@ function _SoftDeleteRemote { local changeTime="${3}" # Delete files older than changeTime days local deletionType="${4}" # Trivial deletion type string - __CheckArguments 4 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 4 $# "$@" #__WITH_PARANOIA_DEBUG local retval @@ -1822,7 +1647,7 @@ ENDSSH } function SoftDelete { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local pids @@ -1838,7 +1663,7 @@ function SoftDelete { _SoftDeleteRemote "${TARGET[$__type]}" "${TARGET[$__replicaDir]}${TARGET[$__backupDir]}" $CONFLICT_BACKUP_DAYS "conflict backup" & pids="$pids;$!" fi - WaitForTaskCompletion $pids $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $pids $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ] && [ "$(eval echo \"\$HARD_MAX_EXEC_TIME_REACHED_${FUNCNAME[0]}\")" == true ]; then exit 1 fi @@ -1856,7 +1681,7 @@ function SoftDelete { _SoftDeleteRemote "${TARGET[$__type]}" "${TARGET[$__replicaDir]}${TARGET[$__deleteDir]}" $SOFT_DELETE_DAYS "softdelete" & pids="$pids;$!" fi - WaitForTaskCompletion $pids $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false ${FUNCNAME[0]} + WaitForTaskCompletion $pids $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false if [ $? != 0 ] && [ "$(eval echo \"\$HARD_MAX_EXEC_TIME_REACHED_${FUNCNAME[0]}\")" == true ]; then exit 1 fi @@ -1868,7 +1693,7 @@ function _SummaryFromFile { local summaryFile="${2}" local direction="${3}" - __CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 3 $# "$@" #__WITH_PARANOIA_DEBUG if [ -f "$summaryFile" ]; then while read -r file; do @@ -1878,7 +1703,7 @@ function _SummaryFromFile { } function Summary { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG ( _LOGGER_PREFIX="" @@ -1903,7 +1728,7 @@ function Summary { } function Init { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG # Set error exit code if a piped command fails set -o pipefail @@ -2085,14 +1910,14 @@ function Init { } function Main { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG HandleLocks Sync } function Usage { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG if [ "$IS_STABLE" != "yes" ]; then echo -e "\e[93mThis is an unstable dev build. Please use with caution.\e[0m" @@ -2135,7 +1960,7 @@ function Usage { } function SyncOnChanges { - __CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local cmd local retval @@ -2173,7 +1998,7 @@ function SyncOnChanges { if [ "$LOCAL_OS" == "MacOSX" ]; then fswatch --exclude $OSYNC_DIR $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE -1 "$INITIATOR_SYNC_DIR" > /dev/null & # Mac fswatch doesn't have timeout switch, replacing wait $! with WaitForTaskCompletion without warning nor spinner and increased SLEEP_TIME to avoid cpu hogging. This sims wait $! with timeout - WaitForTaskCompletion $! 0 $MAX_WAIT 1 0 true false true ${FUNCNAME[0]} + WaitForTaskCompletion $! 0 $MAX_WAIT 1 0 true false true else inotifywait --exclude $OSYNC_DIR $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE -qq -r -e create -e modify -e delete -e move -e attrib --timeout "$MAX_WAIT" "$INITIATOR_SYNC_DIR" & wait $! diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index 6474bde..e1fb189 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -1,6 +1,7 @@ -#### MINIMAL-FUNCTION-SET BEGIN #### +#### OFUNCTIONS FULL SUBSET #### +#### OFUNCTIONS MINI SUBSET #### -_OFUNCTIONS_VERSION=2.0 +_OFUNCTIONS_VERSION=2.1 _OFUNCTIONS_BUILD=2016120701 ## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr @@ -41,6 +42,7 @@ fi ERROR_ALERT=false WARN_ALERT=false +#### DEBUG SUBSET #### ## allow function call checks #__WITH_PARANOIA_DEBUG if [ "$_PARANOIA_DEBUG" == "yes" ];then #__WITH_PARANOIA_DEBUG _DEBUG=yes #__WITH_PARANOIA_DEBUG @@ -58,6 +60,7 @@ fi if [ "$SLEEP_TIME" == "" ]; then # Leave the possibity to set SLEEP_TIME as environment variable when runinng with bash -x in order to avoid spamming console SLEEP_TIME=.05 fi +#### DEBUG SUBSET END #### SCRIPT_PID=$$ @@ -98,12 +101,13 @@ ALERT_LOG_FILE="$RUN_DIR/$PROGRAM.$SCRIPT_PID.last.log" function Dummy { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG sleep $SLEEP_TIME } -#### MINIMAL-FUNCTION-SET BEGIN #### +#### Logger SUBSET #### +#### RemoteLogger SUBSET #### # Sub function of Logger function _Logger { local logValue="${1}" # Log to file @@ -127,6 +131,58 @@ function _Logger { fi } +# Remote logger similar to below Logger, without log to file and alert flags +function RemoteLogger { + local value="${1}" # Sentence to log (in double quotes) + local level="${2}" # Log level + + if [ "$_LOGGER_PREFIX" == "time" ]; then + prefix="TIME: $SECONDS - " + elif [ "$_LOGGER_PREFIX" == "date" ]; then + prefix="$(date) - " + else + prefix="" + fi + + if [ "$level" == "CRITICAL" ]; then + _Logger "" "$prefix\e[41m$value\e[0m" true + return + elif [ "$level" == "ERROR" ]; then + _Logger "" "$prefix\e[91m$value\e[0m" true + return + elif [ "$level" == "WARN" ]; then + _Logger "" "$prefix\e[33m$value\e[0m" true + return + elif [ "$level" == "NOTICE" ]; then + if [ $_LOGGER_ERR_ONLY != true ]; then + _Logger "" "$prefix$value" + fi + return + elif [ "$level" == "VERBOSE" ]; then + if [ $_LOGGER_VERBOSE == true ]; then + _Logger "" "$prefix$value" + fi + return + elif [ "$level" == "ALWAYS" ]; then + _Logger "" "$prefix$value" + return + elif [ "$level" == "DEBUG" ]; then + if [ "$_DEBUG" == "yes" ]; then + _Logger "" "$prefix$value" + return + fi + elif [ "$level" == "PARANOIA_DEBUG" ]; then #__WITH_PARANOIA_DEBUG + if [ "$_PARANOIA_DEBUG" == "yes" ]; then #__WITH_PARANOIA_DEBUG + _Logger "" "$prefix\e[35m$value\e[0m" #__WITH_PARANOIA_DEBUG + return #__WITH_PARANOIA_DEBUG + fi #__WITH_PARANOIA_DEBUG + else + _Logger "\e[41mLogger function called without proper loglevel [$level].\e[0m" + _Logger "Value was: $prefix$value" + fi +} +#### RemoteLogger SUBSET END #### + # General log function with log levels: # Environment variables @@ -198,13 +254,14 @@ function Logger { _Logger "Value was: $prefix$value" fi } +#### Logger SUBSET END #### # QuickLogger subfunction, can be called directly function _QuickLogger { local value="${1}" local destination="${2}" # Destination: stdout, log, both - __CheckArguments 2 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG if ([ "$destination" == "log" ] || [ "$destination" == "both" ]); then echo -e "$(date) - $value" >> "$LOG_FILE" @@ -217,7 +274,7 @@ function _QuickLogger { function QuickLogger { local value="${1}" - __CheckArguments 1 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG if [ $_LOGGER_SILENT == true ]; then _QuickLogger "$value" "log" @@ -266,7 +323,7 @@ function KillAllChilds { local pids="${1}" # List of parent pids to kill separated by semi-colon local self="${2:-false}" # Should parent be killed too ? - __CheckArguments 1 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG local errorcount=0 @@ -284,7 +341,7 @@ function KillAllChilds { function SendAlert { local runAlert="${1:-false}" # Specifies if current message is sent while running or at the end of a run - __CheckArguments 0-1 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0-1 $# "$@" #__WITH_PARANOIA_DEBUG local attachment local attachmentFile @@ -367,7 +424,7 @@ function SendEmail { local smtpUser="${9}" local smtpPassword="${10}" - __CheckArguments 3-10 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 3-10 $# "$@" #__WITH_PARANOIA_DEBUG local mail_no_attachment= local attachment_command= @@ -504,6 +561,7 @@ function SendEmail { Logger "Cannot send mail (neither mutt, mail, sendmail, sendemail, mailsend (windows) or pfSense mail.php could be used)." "ERROR" # Is not marked critical because execution must continue } +#### TrapError SUBSET #### function TrapError { local job="$0" local line="$1" @@ -513,11 +571,12 @@ function TrapError { echo -e "\e[45m/!\ ERROR in ${job}: Near line ${line}, exit code ${code}\e[0m" fi } +#### TrapError SUBSET END #### function LoadConfigFile { local configFile="${1}" - __CheckArguments 1 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 1 $# "$@" #__WITH_PARANOIA_DEBUG if [ ! -f "$configFile" ]; then @@ -578,7 +637,7 @@ function joinString { # Fills a global variable called WAIT_FOR_TASK_COMPLETION_$callerName that contains list of failed pids in format pid1:result1;pid2:result2 # Also sets a global variable called HARD_MAX_EXEC_TIME_REACHED_$callerName to true if hardMaxTime is reached -# Standard wait $! emulation would be WaitForTaskCompletion $! 0 0 1 0 true false true false "${FUNCNAME[0]}" +# Standard wait $! emulation would be WaitForTaskCompletion $! 0 0 1 0 true false true false function WaitForTaskCompletion { local pids="${1}" # pids to wait for, separated by semi-colon @@ -589,10 +648,10 @@ function WaitForTaskCompletion { local counting="${6:-true}" # Count time since function has been launched (true), or since script has been launched (false) local spinner="${7:-true}" # Show spinner (true), don't show anything (false) local noErrorLog="${8:-false}" # Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true) - local callerName="${9}" # Name of the function who called this function for debugging purposes, generally ${FUNCNAME[0]} + local callerName="${FUNCNAME[1]}" Logger "${FUNCNAME[0]} called by [$callerName]." "PARANOIA_DEBUG" #__WITH_PARANOIA_DEBUG - __CheckArguments 9 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 8 $# "$@" #__WITH_PARANOIA_DEBUG local log_ttime=0 # local time instance for comparaison @@ -735,9 +794,9 @@ function ParallelExec { local counting="${8:-true}" # Count time since function has been launched (true), or since script has been launched (false) local spinner="${9:-false}" # Show spinner (true), don't show spinner (false) local noErrorLog="${10:-false}" # Log errors when reaching soft / hard max time (false), don't log errors on those triggers (true) - local callerName="${11:-false}" # Name of the function who called this function for debugging purposes, generally ${FUNCNAME[0]} - __CheckArguments 2-11 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + local callerName="${FUNCNAME[1]}" + __CheckArguments 2-10 $# "$@" #__WITH_PARANOIA_DEBUG local log_ttime=0 # local time instance for comparaison @@ -876,7 +935,7 @@ function ParallelExec { } function CleanUp { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG if [ "$_DEBUG" != "yes" ]; then rm -f "$RUN_DIR/$PROGRAM."*".$SCRIPT_PID" @@ -944,6 +1003,7 @@ function IsNumeric { fi } +#### IsInteger SUBSET #### function IsInteger { local value="${1}" @@ -953,7 +1013,9 @@ function IsInteger { echo 0 fi } +#### IsInteger SUBSET END #### +#### HumanToNumeric SUBSET #### # Converts human readable sizes into integer kilobyte sizes # Usage numericSize="$(HumanToNumeric $humanSize)" function HumanToNumeric { @@ -984,6 +1046,7 @@ function HumanToNumeric { echo $value } +#### HumanToNumeric SUBSET END #### ## from https://gist.github.com/cdown/1163649 function urlEncode { @@ -1009,6 +1072,7 @@ function urlDecode { printf '%b' "${urlEncoded//%/\\x}" } +#### ArrayContains SUBSET #### ## Modified version of http://stackoverflow.com/a/8574392 ## Usage: arrayContains "needle" "${haystack[@]}" function ArrayContains () { @@ -1027,9 +1091,10 @@ function ArrayContains () { echo 0 return } +#### ArrayContains SUBSET END #### function GetLocalOS { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local localOsVar @@ -1086,10 +1151,10 @@ function GetLocalOS { Logger "Local OS: [$localOsVar]." "DEBUG" } -#### MINIMAL-FUNCTION-SET END #### +#### OFUNCTIONS MINI SUBSET END #### function GetRemoteOS { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG if [ "$REMOTE_OPERATION" != "yes" ]; then return 0 @@ -1172,7 +1237,7 @@ ENDSSH function RunLocalCommand { local command="${1}" # Command to run local hardMaxTime="${2}" # Max time to wait for command to compleet - __CheckArguments 2 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG if [ $_DRYRUN == true ]; then Logger "Dryrun: Local command [$command] not run." "NOTICE" @@ -1204,7 +1269,7 @@ function RunLocalCommand { function RunRemoteCommand { local command="${1}" # Command to run local hardMaxTime="${2}" # Max time to wait for command to compleet - __CheckArguments 2 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost @@ -1237,7 +1302,7 @@ function RunRemoteCommand { } function RunBeforeHook { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local pids @@ -1256,7 +1321,7 @@ function RunBeforeHook { } function RunAfterHook { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local pids @@ -1275,7 +1340,7 @@ function RunAfterHook { } function CheckConnectivityRemoteHost { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local retval @@ -1294,7 +1359,7 @@ function CheckConnectivityRemoteHost { } function CheckConnectivity3rdPartyHosts { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local remote3rdPartySuccess local retval @@ -1332,16 +1397,17 @@ function __CheckArguments { if [ "$_DEBUG" == "yes" ]; then local numberOfArguments="${1}" # Number of arguments the tested function should have, can be a number of a range, eg 0-2 for zero to two arguments local numberOfGivenArguments="${2}" # Number of arguments that have been passed - local functionName="${3}" # Function name that called __CheckArguments local minArgs local maxArgs - # All arguments of the function to check are passed as array in ${4} (the function call waits for $@) + # All arguments of the function to check are passed as array in ${3} (the function call waits for $@) # If any of the arguments contains spaces, bash things there are two aguments - # In order to avoid this, we need to iterate over ${4} and count + # In order to avoid this, we need to iterate over ${3} and count - local iterate=4 + callerName="${FUNCNAME[1]}" + + local iterate=3 local fetchArguments=true local argList="" local countedArguments @@ -1351,12 +1417,12 @@ function __CheckArguments { if [ "$argument" = "" ]; then fetchArguments=false else - argList="$argList[Argument $(($iterate-3)): $argument] " + argList="$argList[Argument $(($iterate-2)): $argument] " iterate=$(($iterate+1)) fi done - countedArguments=$((iterate-4)) + countedArguments=$((iterate-3)) if [ $(IsInteger "$numberOfArguments") -eq 1 ]; then minArgs=$numberOfArguments @@ -1365,13 +1431,15 @@ function __CheckArguments { IFS='-' read minArgs maxArgs <<< "$numberOfArguments" fi - Logger "Entering function [$functionName]." "PARANOIA_DEBUG" + Logger "Entering function [$callerName]." "PARANOIA_DEBUG" if ! ([ $countedArguments -ge $minArgs ] && [ $countedArguments -le $maxArgs ]); then Logger "Function $functionName may have inconsistent number of arguments. Expected min: $minArgs, max: $maxArgs, count: $countedArguments, bash seen: $numberOfGivenArguments. see log file." "ERROR" - Logger "Arguments passed: $argList" "ERROR" + Logger "$callerName arguments: $argList" "ERROR" else - Logger "Arguments passed: $argList" "PARANOIA_DEBUG" + if [ ! -z "$argList" ]; then + Logger "$callerName arguments: $argList" "PARANOIA_DEBUG" + fi fi fi } @@ -1381,7 +1449,7 @@ function __CheckArguments { function RsyncPatternsAdd { local patternType="${1}" # exclude or include local pattern="${2}" - __CheckArguments 2 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG local rest @@ -1411,7 +1479,7 @@ function RsyncPatternsAdd { function RsyncPatternsFromAdd { local patternType="${1}" local patternFrom="${2}" - __CheckArguments 2 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 2 $# "$@" #__WITH_PARANOIA_DEBUG ## Check if the exclude list has a full path, and if not, add the config file path if there is one if [ "$(basename $patternFrom)" == "$patternFrom" ]; then @@ -1424,7 +1492,7 @@ function RsyncPatternsFromAdd { } function RsyncPatterns { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG if [ "$RSYNC_PATTERN_FIRST" == "exclude" ]; then if [ "$RSYNC_EXCLUDE_PATTERN" != "" ]; then @@ -1459,7 +1527,7 @@ function RsyncPatterns { } function PreInit { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG local compressionString @@ -1504,7 +1572,7 @@ function PreInit { } function PostInit { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG # Define remote commands if [ -f "$SSH_RSA_PRIVATE_KEY" ]; then @@ -1524,7 +1592,7 @@ function PostInit { } function InitLocalOSDependingSettings { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG ## If running under Msys, some commands do not run the same way ## Using mingw version of find instead of windows one @@ -1560,7 +1628,7 @@ function InitLocalOSDependingSettings { } function InitRemoteOSDependingSettings { - __CheckArguments 0 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG + __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG if [ "$REMOTE_OS" == "msys" ]; then REMOTE_FIND_CMD=$(dirname $BASH)/find @@ -1700,4 +1768,4 @@ function ParentPid { fi } -## END Generic functions +#### OFUNCTIONS FULL SUBSET END #### From c8e2c4e4387113c00260a3968b643e81f16e3dff Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 08:56:13 +0100 Subject: [PATCH 09/25] Fixed typo --- dev/n_osync.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index 100d942..af95ec9 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,11 +4,13 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120702 +PROGRAM_BUILD=2016120801 IS_STABLE=no #TODO: update waitfor parallelexec and checkarguments #TODO: update coding style checkarguments +#TODO: update common install with includes +#TODO: revamp quicklogger # Execution order #__WITH_PARANOIA_DEBUG # Function Name Is parallel #__WITH_PARANOIA_DEBUG @@ -423,7 +425,7 @@ function _HandleLocksRemote { $SSH_CMD _DEBUG="'$_DEBUG'" _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" _LOGGER_SILENT="'$_LOGGER_SILENT'" _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _LOGGER_PREFIX="'$_LOGGER_PREFIX'" _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" replicaStateDir="'$replicaStateDir'" initiatorRunningPidsFlat="(${initiatorRunningPids[@]})" lockfile="'$lockfile'" replicaType="'$replicaType'" overwrite="'$overwrite'" SCRIPT_PID="'$SCRIPT_PID'" INSTANCE_ID="'$INSTANCE_ID'" FORCE_STRANGER_LOCK_RESUME="'$FORCE_STRANGER_LOCK_RESUME'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 include #### DEBUG SUBSET #### include #### TrapError SUBSET #### -incldue #### ArrayContains SUBSET #### +include #### ArrayContains SUBSET #### include #### IsInteger SUBSET #### include #### RemoteLogger SUBSET #### From 80cf34ceddb3c518ee9f4afdef6542c2bb787821 Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 08:56:35 +0100 Subject: [PATCH 10/25] Removed unnecessary code --- dev/merge.sh | 43 ++----------------------------------------- 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/dev/merge.sh b/dev/merge.sh index a31236d..c6d4bb2 100755 --- a/dev/merge.sh +++ b/dev/merge.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -## MERGE 2016120701 +## MERGE 2016120801 ## Merges ofunctions.sh and n_program.sh into program.sh ## Adds installer @@ -24,11 +24,6 @@ function __PREPROCESSOR_Merge { __PREPROCESSOR_MergeSubset "$subset" "${subset//SUBSET/SUBSET END}" "ofunctions.sh" "debug_$PROGRAM.sh" done - #if [ "$PROGRAM" == "osync" ] || [ "$PROGRAM" == "obackup" ]; then - # MergeAll - #else - # MergeMinimum - #fi __PREPROCESSOR_CleanDebug __PREPROCESSOR_CopyCommons rm -f tmp_$PROGRAM.sh @@ -66,40 +61,6 @@ function __PREPROCESSOR_Unexpand { fi } -function __PREPROCESSOR_MergeAll { - - sed "/source \"\.\/ofunctions.sh\"/r ofunctions.sh" tmp_$PROGRAM.sh | grep -v 'source "./ofunctions.sh"' > debug_$PROGRAM.sh - if [ $? != 0 ]; then - QuickLogger "Cannot sed ofunctions" "stderr" - exit 1 - fi -} - -function __PREPROCESSOR_MergeMinimum { - sed -n "/$MINIMUM_FUNCTION_BEGIN/,/$MINIMUM_FUNCTION_END/p" ofunctions.sh > tmp_minimal.sh - if [ $? != 0 ]; then - QuickLogger "Cannot sed minimum functions." "stderr" - exit 1 - fi - sed "/source \"\.\/ofunctions.sh\"/r tmp_minimal.sh" tmp_$PROGRAM.sh | grep -v 'source "./ofunctions.sh"' | grep -v "$PARANOIA_DEBUG_LINE" > debug_$PROGRAM.sh - if [ $? != 0 ]; then - QuickLogger "Cannot remove PARANOIA_DEBUG code from tmp_minimum." "stderr" - exit 1 - fi - rm -f tmp_minimal.sh - if [ $? != 0 ]; then - QuickLogger "Cannot remove tmp_minimal.sh" "stderr" - exit 1 - fi - - chmod +x debug_$PROGRAM.sh - if [ $? != 0 ]; then - QuickLogger "Cannot chmod debug_$PROGRAM.sh" "stderr" - exit 1 - fi - -} - function __PREPROCESSOR_MergeSubset { local subsetBegin="${1}" local subsetEnd="${2}" @@ -116,7 +77,7 @@ function __PREPROCESSOR_MergeSubset { QuickLogger "Cannot add subset [$subsetBegin] to [$mergedFile]." "stderr" exit 1 fi - rm -f "$subsetFile.$subsetBegin" + #rm -f "$subsetFile.$subsetBegin" if [ $? != 0 ]; then QuickLogger "Cannot remove temporary subset [$subsetFile.$subsetBeign]." "stderr" exit 1 From ce6b674ba3ef0192518735bb85e61c99f3918c31 Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 08:58:56 +0100 Subject: [PATCH 11/25] Minor function renames --- dev/ofunctions.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index e1fb189..0926a4d 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -2,7 +2,7 @@ #### OFUNCTIONS MINI SUBSET #### _OFUNCTIONS_VERSION=2.1 -_OFUNCTIONS_BUILD=2016120701 +_OFUNCTIONS_BUILD=2016120801 ## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr ## To use in a program, define the following variables: @@ -1049,7 +1049,7 @@ function HumanToNumeric { #### HumanToNumeric SUBSET END #### ## from https://gist.github.com/cdown/1163649 -function urlEncode { +function UrlEncode { local length="${#1}" local LANG=C @@ -1066,7 +1066,7 @@ function urlEncode { done } -function urlDecode { +function UrlDecode { local urlEncoded="${1//+/ }" printf '%b' "${urlEncoded//%/\\x}" @@ -1074,7 +1074,7 @@ function urlDecode { #### ArrayContains SUBSET #### ## Modified version of http://stackoverflow.com/a/8574392 -## Usage: arrayContains "needle" "${haystack[@]}" +## Usage: [ $(ArrayContains "needle" "${haystack[@]}") -eq 1 ] function ArrayContains () { local needle="${1}" local haystack="${2}" From b0e589ad78957172ec25843481190b017e6a6af8 Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 09:00:58 +0100 Subject: [PATCH 12/25] Re-enabled tmp file deletion after debug --- dev/merge.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/merge.sh b/dev/merge.sh index c6d4bb2..2fd6625 100755 --- a/dev/merge.sh +++ b/dev/merge.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -## MERGE 2016120801 +## MERGE 2016120802 ## Merges ofunctions.sh and n_program.sh into program.sh ## Adds installer @@ -77,7 +77,7 @@ function __PREPROCESSOR_MergeSubset { QuickLogger "Cannot add subset [$subsetBegin] to [$mergedFile]." "stderr" exit 1 fi - #rm -f "$subsetFile.$subsetBegin" + rm -f "$subsetFile.$subsetBegin" if [ $? != 0 ]; then QuickLogger "Cannot remove temporary subset [$subsetFile.$subsetBeign]." "stderr" exit 1 From 31b1f0791a0c1a6336f9e44960a3cf855a9f9697 Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 10:58:59 +0100 Subject: [PATCH 13/25] Added comment --- dev/ofunctions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index 0926a4d..ce30e18 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -288,7 +288,7 @@ function KillChilds { local pid="${1}" # Parent pid to kill childs local self="${2:-false}" # Should parent be killed too ? - + # Warning: pgrep does not exist in cygwin, have this checked in CheckEnvironment if children="$(pgrep -P "$pid")"; then for child in $children; do Logger "Launching KillChilds \"$child\" true" "DEBUG" #__WITH_PARANOIA_DEBUG From d6b5fcc20f9ea47f085f05f31f67397a86f6ca74 Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 10:59:07 +0100 Subject: [PATCH 14/25] Added pgrep test --- dev/n_osync.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index af95ec9..8664b2e 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -136,6 +136,11 @@ function CheckEnvironment { Logger "rsync not present. Sync cannot start." "CRITICAL" exit 1 fi + + if ! type pgrep > /dev/null 2>&1 ; then + Logger "pgrep not present. Sync cannot start." "CRITICAL" + exit 1 + fi } # Only gets checked in config file mode where all values should be present From 15c49f3aa420b8e6f63782fc86d89b02399d7a4b Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 11:04:51 +0100 Subject: [PATCH 15/25] Removed typo --- dev/n_osync.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index 8664b2e..e728b84 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -300,7 +300,7 @@ exit $? ENDSSH result=$? if [ $result != 0 ]; then - Logger "Failed to check remote replica.." "CRITICAL" + Logger "Failed to check remote replica." "CRITICAL" fi if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then ( From 97eee22944321cc658bde2151224084bc650c1f4 Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 11:36:55 +0100 Subject: [PATCH 16/25] Added env for csh... Fuck you csh ! --- dev/n_osync.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index e728b84..a4f92e8 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,13 +4,14 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120801 +PROGRAM_BUILD=2016120802 IS_STABLE=no #TODO: update waitfor parallelexec and checkarguments #TODO: update coding style checkarguments #TODO: update common install with includes #TODO: revamp quicklogger +#TODO: is debug subset relevant ? # Execution order #__WITH_PARANOIA_DEBUG # Function Name Is parallel #__WITH_PARANOIA_DEBUG @@ -252,7 +253,8 @@ function _CheckReplicasRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost -$SSH_CMD _DEBUG="'$_DEBUG'" _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" _LOGGER_SILENT="'$_LOGGER_SILENT'" _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _LOGGER_PREFIX="'$_LOGGER_PREFIX'" _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" replicaPath="'$replicaPath'" CREATE_DIRS="'$CREATE_DIRS'" COMMAND_SUDO="'$COMMAND_SUDO'" DF_CMD="'$DF_CMD'" MINIMUM_SPACE="'$MINIMUM_SPACE'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +$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'" \ +env replicaPath="'$replicaPath'" env CREATE_DIRS="'$CREATE_DIRS'" env COMMAND_SUDO="'$COMMAND_SUDO'" env DF_CMD="'$DF_CMD'" env MINIMUM_SPACE="'$MINIMUM_SPACE'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 include #### DEBUG SUBSET #### include #### TrapError SUBSET #### include #### IsInteger SUBSET #### @@ -427,7 +429,9 @@ function _HandleLocksRemote { read -a initiatorRunningPids <<< $(ps -A | tail -n +2 | awk '{print $1}') # passing initiatorRunningPids as litteral string (has to be run through eval to be an array again) -$SSH_CMD _DEBUG="'$_DEBUG'" _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" _LOGGER_SILENT="'$_LOGGER_SILENT'" _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _LOGGER_PREFIX="'$_LOGGER_PREFIX'" _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" replicaStateDir="'$replicaStateDir'" initiatorRunningPidsFlat="(${initiatorRunningPids[@]})" lockfile="'$lockfile'" replicaType="'$replicaType'" overwrite="'$overwrite'" SCRIPT_PID="'$SCRIPT_PID'" INSTANCE_ID="'$INSTANCE_ID'" FORCE_STRANGER_LOCK_RESUME="'$FORCE_STRANGER_LOCK_RESUME'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +$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'" \ +env replicaStateDir="'$replicaStateDir'" env initiatorRunningPidsFlat="\"(${initiatorRunningPids[@]})\"" env lockfile="'$lockfile'" env replicaType="'$replicaType'" env overwrite="'$overwrite'" env SCRIPT_PID="'$SCRIPT_PID'" \ +env INSTANCE_ID="'$INSTANCE_ID'" env FORCE_STRANGER_LOCK_RESUME="'$FORCE_STRANGER_LOCK_RESUME'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 include #### DEBUG SUBSET #### include #### TrapError SUBSET #### include #### ArrayContains SUBSET #### @@ -583,7 +587,8 @@ function _UnlockReplicasRemote { CheckConnectivity3rdPartyHosts CheckConnectivityRemoteHost -$SSH_CMD lockfile="'$lockfile'" COMMAND_SUDO="'$COMMAND_SUDO'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +#TODO: missing logger entry +$SSH_CMD env lockfile="'$lockfile'" env COMMAND_SUDO="'$COMMAND_SUDO'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 if [ -f "$lockfile" ]; then $COMMAND_SUDO rm -f "$lockfile" fi @@ -1080,7 +1085,10 @@ function _deleteRemote { exit 1 fi -$SSH_CMD _DEBUG="'$_DEBUG'" _PARANOIA_DEBUG="'$_PARANOIA_DEBUG'" _LOGGER_SILENT="'$_LOGGER_SILENT'" _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _LOGGER_PREFIX="'$_LOGGER_PREFIX'" _LOGGER_ERR_ONLY="'$_LOGGER_ERR_ONLY'" ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$_DRYRUN COMMAND_SUDO=$COMMAND_SUDO FILE_LIST="$(EscapeSpaces "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}/$deletionListFromReplica${INITIATOR[$__deletedListFile]}")" REPLICA_DIR="$(EscapeSpaces "$replicaDir")" SOFT_DELETE=$SOFT_DELETE DELETION_DIR="$(EscapeSpaces "$deletionDir")" FAILED_DELETE_LIST="$failedDeleteList" SUCCESS_DELETE_LIST="$successDeleteList" 'bash -s' << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" 2>&1 +$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'" \ +env sync_on_changes=$sync_on_changes env _DRYRUN="'$_DRYRUN'" env COMMAND_SUDO="'$COMMAND_SUDO'" \ +env FILE_LIST="'$(EscapeSpaces "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}/$deletionListFromReplica${INITIATOR[$__deletedListFile]}")'" env REPLICA_DIR="'$(EscapeSpaces "$replicaDir")'" env SOFT_DELETE="'$SOFT_DELETE'" \ +env DELETION_DIR="'$(EscapeSpaces "$deletionDir")'" env FAILED_DELETE_LIST="'$failedDeleteList'" env SUCCESS_DELETE_LIST="'$successDeleteList'" 'bash -s' << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" 2>&1 include #### DEBUG SUBSET #### include #### TrapError SUBSET #### include #### RemoteLogger SUBSET #### @@ -1634,7 +1642,8 @@ function _SoftDeleteRemote { fi #TODO: fixed find directory -ctime was missing +, test it -$SSH_CMD _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" _DRYRUN="'$_DRYRUN'" replicaDeletionPath="'$replicaDeletionPath'" changeTime="'$changeTime'" COMAMND_SUDO="'$COMMAND_SUDO'" REMOTE_FIND_CMD="'$REMOTE_FIND_CMD'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 +#TODO: missing logger vars +$SSH_CMD env _LOGGER_VERBOSE="'$_LOGGER_VERBOSE'" env _DRYRUN="'$_DRYRUN'" env replicaDeletionPath="'$replicaDeletionPath'" env changeTime="'$changeTime'" env COMAMND_SUDO="'$COMMAND_SUDO'" env REMOTE_FIND_CMD="'$REMOTE_FIND_CMD'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" 2>&1 # Cannot launch log function from xargs, ugly hack if [ -d "$replicaDeletionPath" ]; then From 61adfc6c6f50fff65213f0fc3babca74aca20a1b Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 21:59:52 +0100 Subject: [PATCH 17/25] Workaround for FreeBSD 11 get ctime default shell --- dev/n_osync.sh | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index a4f92e8..6be064a 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,7 +4,7 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120802 +PROGRAM_BUILD=2016120804 IS_STABLE=no #TODO: update waitfor parallelexec and checkarguments @@ -47,6 +47,10 @@ IS_STABLE=no # CleanUp no #__WITH_PARANOIA_DEBUG include #### OFUNCTIONS FULL SUBSET #### + +# Hopefully multishell compatible (bash & csh seem to like it) +[ "$_OFUNCTIONS_BOOTSTRAP" != true ] && echo "Please use bootstrap.sh to load this dev version of $(basename $0)" && exit 1 + _LOGGER_PREFIX="time" ## Working directory. This directory exists in any replica and contains state files, backups, soft deleted files etc @@ -748,7 +752,7 @@ function _getFileCtimeMtimeLocal { if [ -f "$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" ]; then Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID)" "VERBOSE" fi - exit 1 + return 1 fi } @@ -761,16 +765,32 @@ function _getFileCtimeMtimeRemote { local cmd + #TODO WIP # Quoting ' in single quote with '"'"' in order to have cmd='some stuff \'bash -c "some other stuff"\'' - cmd='cat "'$fileList'" | '$SSH_CMD' '"'"'bash -c "while read -r file; do '$REMOTE_STAT_CTIME_MTIME_CMD' \"'$replicaPath'\$file\"; done | sort"'"'"' > "'$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID'"' + #cmd='cat "'$fileList'" | '$SSH_CMD' '"'"'bash -c "while read -r file; do '$REMOTE_STAT_CTIME_MTIME_CMD' \"'$replicaPath'\$file\"; done | sort"'"'"' > "'$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID'"' + cmd='cat "'$fileList'" | '$SSH_CMD' "cat > \".$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID\""' Logger "CMD: $cmd" "DEBUG" eval "$cmd" + if [ $? != 0 ]; then + Logger "Sending ctime required file list failed with [$retval] on $replicaType. Stopping execution." "CRITICAL" + if [ -f "$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" ]; then + Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID)" "VERBOSE" + fi + return 1 + fi + +$SSH_CMD env PROGRAM="'$PROGRAM'" env SCRIPT_PID="'$SCRIPT_PID'" env replicaPath="'$replicaPath'" env replicaType="'$replicaType'" env REMOTE_STAT_CTIME_MTIME_CMD="'$REMOTE_STAT_CTIME_MTIME_CMD'" 'bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" + while read -r file; do $REMOTE_STAT_CTIME_MTIME_CMD "$replicaPath$file" | sort; done < ".$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" + if [ -f ".$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" ]; then + rm -f ".$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" + fi +ENDSSH if [ $? != 0 ]; then Logger "Getting file attributes failed [$retval] on $replicaType. Stopping execution." "CRITICAL" if [ -f "$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" ]; then Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID)" "VERBOSE" fi - exit 1 + return 1 fi } @@ -814,7 +834,7 @@ function syncAttrs { if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then Logger "Rsync output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE" fi - exit 1 + return 1 else if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then Logger "List:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "VERBOSE" @@ -839,6 +859,10 @@ function syncAttrs { pids="$pids;$!" fi WaitForTaskCompletion $pids $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME $SLEEP_TIME $KEEP_LOGGING false true false + if [ $? != 0 ]; then + Logger "Getting ctime attributes failed." "CRITICAL" + return 1 + fi # If target gets updated first, then sync_attr must update initiators attrs first # For join, remove leading replica paths @@ -894,7 +918,7 @@ function syncAttrs { if [ -f "$RUN_DIR/$PROGRAM.attr-update.$destReplica.$SCRIPT_PID" ]; then Logger "Rsync output:\n$(cat $RUN_DIR/$PROGRAM.attr-update.$destReplica.$SCRIPT_PID)" "NOTICE" fi - exit 1 + return 1 else if [ -f "$RUN_DIR/$PROGRAM.attr-update.$destReplica.$SCRIPT_PID" ]; then Logger "List:\n$(cat $RUN_DIR/$PROGRAM.attr-update.$destReplica.$SCRIPT_PID)" "VERBOSE" From a543099eeda0964c1e402b9641450cc25e19772e Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 22:06:36 +0100 Subject: [PATCH 18/25] Added msys2 detection and bootstrap safe code --- dev/ofunctions.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index ce30e18..598a230 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -2,7 +2,8 @@ #### OFUNCTIONS MINI SUBSET #### _OFUNCTIONS_VERSION=2.1 -_OFUNCTIONS_BUILD=2016120801 +_OFUNCTIONS_BUILD=2016120802 +_OFUNCTIONS_BOOTSTRAP=true ## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr ## To use in a program, define the following variables: @@ -1127,7 +1128,7 @@ function GetLocalOS { *"BSD"*) LOCAL_OS="BSD" ;; - *"MINGW32"*|*"CYGWIN"*) + *"MINGW32"*|*"MSYS"*|*"CYGWIN"*) LOCAL_OS="msys" ;; *"Microsoft"*) @@ -1203,7 +1204,7 @@ ENDSSH *"BSD"*) REMOTE_OS="BSD" ;; - *"MINGW32"*|*"CYGWIN"*) + *"MINGW32"*|*"MSYS"*|*"CYGWIN"*) REMOTE_OS="msys" ;; *"Microsoft"*) From 435b59751323b2ff563a817dae0cad55e2f20eae Mon Sep 17 00:00:00 2001 From: deajan Date: Thu, 8 Dec 2016 22:10:54 +0100 Subject: [PATCH 19/25] Workaround for FreeBSD inotifywait only wants one exclude --- dev/n_osync.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index 6be064a..3e74595 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,7 +4,7 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120804 +PROGRAM_BUILD=2016120805 IS_STABLE=no #TODO: update waitfor parallelexec and checkarguments @@ -2036,11 +2036,11 @@ function SyncOnChanges { Logger "#### Monitoring now." "NOTICE" if [ "$LOCAL_OS" == "MacOSX" ]; then - fswatch --exclude $OSYNC_DIR $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE -1 "$INITIATOR_SYNC_DIR" > /dev/null & + fswatch --exclude $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE "$OSYNC_DIR" -1 "$INITIATOR_SYNC_DIR" > /dev/null & # Mac fswatch doesn't have timeout switch, replacing wait $! with WaitForTaskCompletion without warning nor spinner and increased SLEEP_TIME to avoid cpu hogging. This sims wait $! with timeout WaitForTaskCompletion $! 0 $MAX_WAIT 1 0 true false true else - inotifywait --exclude $OSYNC_DIR $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE -qq -r -e create -e modify -e delete -e move -e attrib --timeout "$MAX_WAIT" "$INITIATOR_SYNC_DIR" & + inotifywait --exclude $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE "$OSYNC_DIR" -qq -r -e create -e modify -e delete -e move -e attrib --timeout "$MAX_WAIT" "$INITIATOR_SYNC_DIR" & wait $! fi retval=$? From be0d0ab8d956da36b043ee3d2c6fd3bee33d5407 Mon Sep 17 00:00:00 2001 From: deajan Date: Fri, 9 Dec 2016 11:04:56 +0100 Subject: [PATCH 20/25] Fixed daemon exclusions --- dev/n_osync.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index 3e74595..bb68891 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,7 +4,7 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120805 +PROGRAM_BUILD=2016120901 IS_STABLE=no #TODO: update waitfor parallelexec and checkarguments @@ -2036,11 +2036,11 @@ function SyncOnChanges { Logger "#### Monitoring now." "NOTICE" if [ "$LOCAL_OS" == "MacOSX" ]; then - fswatch --exclude $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE "$OSYNC_DIR" -1 "$INITIATOR_SYNC_DIR" > /dev/null & + fswatch $RSYNC_EXCLUDDE_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude "$OSYNC_DIR" -1 "$INITIATOR_SYNC_DIR" > /dev/null & # Mac fswatch doesn't have timeout switch, replacing wait $! with WaitForTaskCompletion without warning nor spinner and increased SLEEP_TIME to avoid cpu hogging. This sims wait $! with timeout WaitForTaskCompletion $! 0 $MAX_WAIT 1 0 true false true else - inotifywait --exclude $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE "$OSYNC_DIR" -qq -r -e create -e modify -e delete -e move -e attrib --timeout "$MAX_WAIT" "$INITIATOR_SYNC_DIR" & + inotifywait $RSYNC_EXCLUDE_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude "$OSYNC_DIR" -qq -r -e create -e modify -e delete -e move -e attrib --timeout "$MAX_WAIT" "$INITIATOR_SYNC_DIR" & wait $! fi retval=$? From a08ce8904b7167a1e3313350c14a17860d6936dc Mon Sep 17 00:00:00 2001 From: deajan Date: Fri, 9 Dec 2016 17:10:04 +0100 Subject: [PATCH 21/25] Reverted bogus var name change --- dev/n_osync.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index bb68891..5c41430 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,7 +4,7 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120901 +PROGRAM_BUILD=2016120902 IS_STABLE=no #TODO: update waitfor parallelexec and checkarguments @@ -2036,11 +2036,11 @@ function SyncOnChanges { Logger "#### Monitoring now." "NOTICE" if [ "$LOCAL_OS" == "MacOSX" ]; then - fswatch $RSYNC_EXCLUDDE_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude "$OSYNC_DIR" -1 "$INITIATOR_SYNC_DIR" > /dev/null & + fswatch $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude "$OSYNC_DIR" -1 "$INITIATOR_SYNC_DIR" > /dev/null & # Mac fswatch doesn't have timeout switch, replacing wait $! with WaitForTaskCompletion without warning nor spinner and increased SLEEP_TIME to avoid cpu hogging. This sims wait $! with timeout WaitForTaskCompletion $! 0 $MAX_WAIT 1 0 true false true else - inotifywait $RSYNC_EXCLUDE_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude "$OSYNC_DIR" -qq -r -e create -e modify -e delete -e move -e attrib --timeout "$MAX_WAIT" "$INITIATOR_SYNC_DIR" & + inotifywait $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude "$OSYNC_DIR" -qq -r -e create -e modify -e delete -e move -e attrib --timeout "$MAX_WAIT" "$INITIATOR_SYNC_DIR" & wait $! fi retval=$? From d15069a85bf52b502383d847ae7c4af1095a6d32 Mon Sep 17 00:00:00 2001 From: deajan Date: Fri, 9 Dec 2016 19:01:58 +0100 Subject: [PATCH 22/25] More FreeBSD acl fix --- dev/n_osync.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dev/n_osync.sh b/dev/n_osync.sh index 5c41430..75efc3e 100755 --- a/dev/n_osync.sh +++ b/dev/n_osync.sh @@ -4,7 +4,7 @@ PROGRAM="osync" # Rsync based two way sync engine with fault tolerance AUTHOR="(C) 2013-2016 by Orsiris de Jong" CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr" PROGRAM_VERSION=1.2-beta3 -PROGRAM_BUILD=2016120902 +PROGRAM_BUILD=2016120903 IS_STABLE=no #TODO: update waitfor parallelexec and checkarguments @@ -791,6 +791,9 @@ ENDSSH Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID)" "VERBOSE" fi return 1 + else + # Ugly fix for csh in FreeBSD 11 that adds leading and trailing '\"' + sed -i.tmp -e 's/^\\"//' -e 's/\\"$//' "$RUN_DIR/$PROGRAM.ctime_mtime.$replicaType.$SCRIPT_PID" fi } From 229a9800cc832d4a47825a0bcac001c4756c88f7 Mon Sep 17 00:00:00 2001 From: deajan Date: Fri, 9 Dec 2016 19:19:52 +0100 Subject: [PATCH 23/25] Make difference between msys and cygwin --- dev/ofunctions.sh | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/dev/ofunctions.sh b/dev/ofunctions.sh index 598a230..d12508a 100644 --- a/dev/ofunctions.sh +++ b/dev/ofunctions.sh @@ -2,7 +2,7 @@ #### OFUNCTIONS MINI SUBSET #### _OFUNCTIONS_VERSION=2.1 -_OFUNCTIONS_BUILD=2016120802 +_OFUNCTIONS_BUILD=2016120901 _OFUNCTIONS_BOOTSTRAP=true ## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr @@ -1128,9 +1128,12 @@ function GetLocalOS { *"BSD"*) LOCAL_OS="BSD" ;; - *"MINGW32"*|*"MSYS"*|*"CYGWIN"*) + *"MINGW32"*|*"MSYS"*) LOCAL_OS="msys" ;; + *"CYGWIN"*) + LOCAL_OS="Cygwin" + ;; *"Microsoft"*) LOCAL_OS="WinNT10" ;; @@ -1204,9 +1207,12 @@ ENDSSH *"BSD"*) REMOTE_OS="BSD" ;; - *"MINGW32"*|*"MSYS"*|*"CYGWIN"*) + *"MINGW32"*|*"MSYS"*) REMOTE_OS="msys" ;; + *"CYGWIN"*) + REMOTE_OS="Cygwin" + ;; *"Microsoft"*) REMOTE_OS="WinNT10" ;; @@ -1599,7 +1605,7 @@ function InitLocalOSDependingSettings { ## Using mingw version of find instead of windows one ## Getting running processes is quite different ## Ping command is not the same - if [ "$LOCAL_OS" == "msys" ]; then + if [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then FIND_CMD=$(dirname $BASH)/find PING_CMD='$SYSTEMROOT\system32\ping -n 2' else @@ -1607,7 +1613,7 @@ function InitLocalOSDependingSettings { PING_CMD="ping -c 2 -i .2" fi - if [ "$LOCAL_OS" == "BusyBox" ] || [ "$LOCAL_OS" == "Android" ] || [ "$LOCAL_OS" == "msys" ]; then + if [ "$LOCAL_OS" == "BusyBox" ] || [ "$LOCAL_OS" == "Android" ] || [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then PROCESS_STATE_CMD="echo none" DF_CMD="df" else @@ -1631,7 +1637,7 @@ function InitLocalOSDependingSettings { function InitRemoteOSDependingSettings { __CheckArguments 0 $# "$@" #__WITH_PARANOIA_DEBUG - if [ "$REMOTE_OS" == "msys" ]; then + if [ "$REMOTE_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then REMOTE_FIND_CMD=$(dirname $BASH)/find else REMOTE_FIND_CMD=find @@ -1668,7 +1674,7 @@ function InitRemoteOSDependingSettings { if [ "$PRESERVE_EXECUTABILITY" != "no" ]; then RSYNC_ATTR_ARGS=$RSYNC_ATTR_ARGS" --executability" fi - if [ "$LOCAL_OS" != "MacOSX" ] && [ "$REMOTE_OS" != "MacOSX" ] && [ "$LOCAL_OS" != "msys" ] && [ "$REMOTE_OS" != "MacOSX" ]; then + if [ "$LOCAL_OS" != "MacOSX" ] && [ "$REMOTE_OS" != "MacOSX" ] && [ "$LOCAL_OS" != "msys" ] && [ "$LOCAL_OS" != "Cygwin" ] && [ "$REMOTE_OS" != "MacOSX" ]; then if [ "$PRESERVE_ACL" == "yes" ]; then RSYNC_ATTR_ARGS=$RSYNC_ATTR_ARGS" -A" fi From 738c11e315e0d1ed3b42414ecab7acb68466e5fa Mon Sep 17 00:00:00 2001 From: deajan Date: Fri, 9 Dec 2016 19:22:14 +0100 Subject: [PATCH 24/25] Disabled symlink tests on msys --- dev/tests/run_tests.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dev/tests/run_tests.sh b/dev/tests/run_tests.sh index f26a317..7448bad 100755 --- a/dev/tests/run_tests.sh +++ b/dev/tests/run_tests.sh @@ -7,7 +7,7 @@ ## On CYGWIN / MSYS, ACL and extended attributes aren't supported -# osync test suite 2016120601 +# osync test suite 2016120901 # 4 tests: # quicklocal @@ -221,7 +221,7 @@ function oneTimeSetUp () { osyncDaemonParameters[$__local]="$CONF_DIR/$LOCAL_CONF --on-changes" - if [ "$LOCAL_OS" != "msys" ]; then + if [ "$LOCAL_OS" != "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then osyncParameters[$__quickRemote]="--initiator=$INITIATOR_DIR --target=ssh://localhost:$SSH_PORT/$TARGET_DIR --rsakey=${HOME}/.ssh/id_rsa_local --instance-id=quickremote" osyncParameters[$__confRemote]="$CONF_DIR/$REMOTE_CONF" @@ -734,7 +734,7 @@ function test_softdeletion_cleanup () { touch "$file.new" - if [ "$TRAVIS_RUN" == true ] || [ "$LOCAL_OS" == "BSD" ] || [ "$LOCAL_OS" == "MacOSX" ] || [ "$LOCAL_OS" == "WinNT10" ] || [ "LOCAL_OS" == "msys" ]; then + if [ "$TRAVIS_RUN" == true ] || [ "$LOCAL_OS" == "BSD" ] || [ "$LOCAL_OS" == "MacOSX" ] || [ "$LOCAL_OS" == "WinNT10" ] || [ "LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then echo "Skipping changing ctime on file because travis / bsd / macos / Win10 / msys / cygwin does not support debugfs" else CreateOldFile "$file.old" @@ -749,7 +749,7 @@ function test_softdeletion_cleanup () { [ -f "$file.new" ] assertEquals "New softdeleted / backed up file [$file.new] exists." "0" $? - if [ "$TRAVIS_RUN" == true ] || [ "$LOCAL_OS" == "BSD" ] || [ "$LOCAL_OS" == "MacOSX" ] || [ "$LOCAL_OS" == "WinNT10" ] || [ "$LOCAL_OS" == "msys" ]; then + if [ "$TRAVIS_RUN" == true ] || [ "$LOCAL_OS" == "BSD" ] || [ "$LOCAL_OS" == "MacOSX" ] || [ "$LOCAL_OS" == "WinNT10" ] || [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then [ ! -f "$file.old" ] assertEquals "Old softdeleted / backed up file [$file.old] is deleted permanently." "0" $? else @@ -1264,8 +1264,8 @@ function test_UpgradeConfRun () { } function test_DaemonMode () { - if [ "$LOCAL_OS" == "WinNT10" ] || [ "$LOCAL_OS" == "msys" ]; then - echo "Skipping daemon mode test as Win10 does not have inotifywait support." + if [ "$LOCAL_OS" == "WinNT10" ] || [ "$LOCAL_OS" == "msys" ] || [ "$LOCAL_OS" == "Cygwin" ]; then + echo "Skipping daemon mode test as [$LOCAL_OS] does not have inotifywait support." return 0 fi From 4c61d0c53d80a28462bf80ca3ebd613e5282244e Mon Sep 17 00:00:00 2001 From: deajan Date: Fri, 9 Dec 2016 19:25:23 +0100 Subject: [PATCH 25/25] Ye --- dev/tests/run_tests.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/tests/run_tests.sh b/dev/tests/run_tests.sh index 7448bad..77b8de5 100755 --- a/dev/tests/run_tests.sh +++ b/dev/tests/run_tests.sh @@ -535,6 +535,11 @@ function test_handle_symlinks () { return 0 fi + if [ "$LOCAL_OS" == "msys" ]; then + echo "Skipping symlink tests because msys handles them strangely or not at all." + return 0 + fi + # Check with and without copySymlinks copySymlinks="no"