2015-11-12 00:37:43 +00:00
#!/usr/bin/env bash
2017-06-01 15:45:02 +00:00
#TODO treeList, deleteList, _getFileCtimeMtime, conflictList should be called without having statedir informed. Just give the full path ?
2017-07-27 20:50:48 +00:00
#Check dryruns with nosuffix mode for timestampList
2018-10-01 18:28:46 +00:00
#WIP: currently TRAVIS_RUN debug lines in n_osync and run_tests for conflictLog
2017-05-31 16:02:18 +00:00
2015-11-12 00:37:43 +00:00
PROGRAM = "osync" # Rsync based two way sync engine with fault tolerance
2018-06-30 17:40:24 +00:00
AUTHOR = "(C) 2013-2018 by Orsiris de Jong"
2015-11-12 00:37:43 +00:00
CONTACT = "http://www.netpower.fr/osync - ozy@netpower.fr"
2018-08-08 09:31:11 +00:00
PROGRAM_VERSION = 1.3.0-beta1
2018-10-07 11:23:45 +00:00
PROGRAM_BUILD = 2018100703
2017-05-30 07:15:48 +00:00
IS_STABLE = no
2016-12-06 21:41:44 +00:00
2017-02-10 09:35:17 +00:00
##### Execution order #__WITH_PARANOIA_DEBUG
##### Function Name Is parallel #__WITH_PARANOIA_DEBUG
2016-08-28 16:26:12 +00:00
# GetLocalOS no #__WITH_PARANOIA_DEBUG
2016-12-04 10:10:02 +00:00
# InitLocalOSDependingSettings no #__WITH_PARANOIA_DEBUG
2016-08-28 16:26:12 +00:00
# CheckEnvironment no #__WITH_PARANOIA_DEBUG
# PreInit no #__WITH_PARANOIA_DEBUG
# Init no #__WITH_PARANOIA_DEBUG
# PostInit no #__WITH_PARANOIA_DEBUG
# GetRemoteOS no #__WITH_PARANOIA_DEBUG
2016-12-04 10:10:02 +00:00
# InitRemoteOSDependingSettings no #__WITH_PARANOIA_DEBUG
2016-12-06 21:41:44 +00:00
# CheckReplicas yes #__WITH_PARANOIA_DEBUG
2016-08-28 16:26:12 +00:00
# RunBeforeHook yes #__WITH_PARANOIA_DEBUG
# Main no #__WITH_PARANOIA_DEBUG
2016-12-06 20:32:27 +00:00
# HandleLocks yes #__WITH_PARANOIA_DEBUG
2016-08-28 16:26:12 +00:00
# Sync no #__WITH_PARANOIA_DEBUG
2016-10-16 12:25:29 +00:00
# treeList yes #__WITH_PARANOIA_DEBUG
# deleteList yes #__WITH_PARANOIA_DEBUG
2017-06-03 11:51:49 +00:00
# timestampList yes #__WITH_PARANOIA_DEBUG
# conflictList no #__WITH_PARANOIA_DEBUG
2016-10-16 12:25:29 +00:00
# syncAttrs no #__WITH_PARANOIA_DEBUG
# syncUpdate no #__WITH_PARANOIA_DEBUG
# syncUpdate no #__WITH_PARANOIA_DEBUG
# deletionPropagation yes #__WITH_PARANOIA_DEBUG
# treeList yes #__WITH_PARANOIA_DEBUG
2017-06-03 11:51:49 +00:00
# timestampList yes #__WITH_PARANOIA_DEBUG
2016-08-28 16:26:12 +00:00
# SoftDelete yes #__WITH_PARANOIA_DEBUG
# RunAfterHook yes #__WITH_PARANOIA_DEBUG
# UnlockReplicas yes #__WITH_PARANOIA_DEBUG
# CleanUp no #__WITH_PARANOIA_DEBUG
2016-08-02 08:01:48 +00:00
2016-12-07 20:30:10 +00:00
include #### OFUNCTIONS FULL SUBSET ####
2018-07-02 15:29:50 +00:00
# If using "include" statements, make sure the script does not get executed unless it's loaded by bootstrap.sh which will replace includes with actual code
2016-12-11 13:57:02 +00:00
include #### _OFUNCTIONS_BOOTSTRAP SUBSET ####
2016-12-08 20:59:52 +00:00
[ " $_OFUNCTIONS_BOOTSTRAP " != true ] && echo " Please use bootstrap.sh to load this dev version of $( basename $0 ) " && exit 1
2016-08-04 09:52:28 +00:00
_LOGGER_PREFIX = "time"
2016-08-02 08:01:48 +00:00
2016-02-17 12:51:42 +00:00
## Working directory. This directory exists in any replica and contains state files, backups, soft deleted files etc
2015-11-12 00:37:43 +00:00
OSYNC_DIR = ".osync_workdir"
2016-12-03 08:53:44 +00:00
# The catch CRTL+C behavior can be changed at script entry point with SOFT_STOP=0
2015-11-12 00:37:43 +00:00
function TrapStop {
2016-12-03 08:53:44 +00:00
if [ $SOFT_STOP -eq 2 ] ; then
2015-11-12 00:37:43 +00:00
Logger " /!\ WARNING: Manual exit of osync is really not recommended. Sync will be in inconsistent state." "WARN"
Logger " /!\ WARNING: If you are sure, please hit CTRL+C another time to quit." "WARN"
2016-02-21 10:11:28 +00:00
SOFT_STOP = 1
2015-11-12 00:37:43 +00:00
return 1
fi
2016-12-03 08:53:44 +00:00
if [ $SOFT_STOP -lt 2 ] ; then
Logger " /!\ WARNING: CTRL+C hit. Exiting osync. Please wait while replicas get unlocked..." "WARN"
SOFT_STOP = 0
2016-08-18 21:28:25 +00:00
exit 2
2015-11-12 00:37:43 +00:00
fi
}
function TrapQuit {
2016-08-04 09:52:28 +00:00
local exitcode
2016-02-21 10:11:28 +00:00
2016-11-15 20:27:32 +00:00
# Get ERROR / WARN alert flags from subprocesses that call Logger
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM .Logger.warn. $SCRIPT_PID . $TSTAMP " ] ; then
2016-11-15 20:27:32 +00:00
WARN_ALERT = true
fi
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM .Logger.error. $SCRIPT_PID . $TSTAMP " ] ; then
2016-11-15 20:27:32 +00:00
ERROR_ALERT = true
fi
2016-08-29 11:54:24 +00:00
if [ $ERROR_ALERT = = true ] ; then
2015-11-12 00:37:43 +00:00
UnlockReplicas
2016-04-06 18:51:29 +00:00
if [ " $RUN_AFTER_CMD_ON_ERROR " = = "yes" ] ; then
RunAfterHook
fi
2015-11-12 00:37:43 +00:00
Logger " $PROGRAM finished with errors. " "ERROR"
2015-12-15 12:40:50 +00:00
if [ " $_DEBUG " != "yes" ]
then
SendAlert
else
2015-12-21 13:09:17 +00:00
Logger "Debug mode, no alert mail will be sent." "NOTICE"
2015-12-15 12:40:50 +00:00
fi
2016-08-30 10:28:26 +00:00
exitcode = 1
elif [ $WARN_ALERT = = true ] ; then
UnlockReplicas
2016-04-06 18:51:29 +00:00
if [ " $RUN_AFTER_CMD_ON_ERROR " = = "yes" ] ; then
RunAfterHook
fi
2015-11-12 00:37:43 +00:00
Logger " $PROGRAM finished with warnings. " "WARN"
2016-08-30 10:28:26 +00:00
if [ " $_DEBUG " != "yes" ]
then
SendAlert
else
Logger "Debug mode, no alert mail will be sent." "NOTICE"
fi
2016-08-18 21:28:25 +00:00
exitcode = 2 # Warning exit code must not force daemon mode to quit
2015-11-12 00:37:43 +00:00
else
UnlockReplicas
2016-08-22 06:32:24 +00:00
RunAfterHook
2016-12-04 09:58:53 +00:00
Logger " $PROGRAM finished. " "ALWAYS"
2015-11-12 00:37:43 +00:00
exitcode = 0
fi
2016-12-12 18:23:58 +00:00
CleanUp
2017-05-30 07:09:25 +00:00
KillChilds $SCRIPT_PID > /dev/null 2>& 1
2015-11-12 00:37:43 +00:00
exit $exitcode
}
function CheckEnvironment {
2016-12-11 19:54:40 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-11 19:54:40 +00:00
if [ " $REMOTE_OPERATION " = = "yes" ] ; then
if ! type ssh > /dev/null 2>& 1 ; then
Logger "ssh not present. Cannot start sync." "CRITICAL"
exit 1
fi
2016-10-19 10:28:11 +00:00
2016-10-19 10:44:52 +00:00
if [ " $SSH_PASSWORD_FILE " != "" ] && ! type sshpass > /dev/null 2>& 1 ; then
2016-10-19 10:28:11 +00:00
Logger "sshpass not present. Cannot use password authentication." "CRITICAL"
exit 1
fi
2016-12-11 19:54:40 +00:00
fi
2015-11-12 00:37:43 +00:00
2016-12-11 19:54:40 +00:00
if ! type rsync > /dev/null 2>& 1 ; then
Logger "rsync not present. Sync cannot start." "CRITICAL"
exit 1
fi
2016-12-08 09:59:07 +00:00
2016-12-11 19:54:40 +00:00
if ! type pgrep > /dev/null 2>& 1 ; then
Logger "pgrep not present. Sync cannot start." "CRITICAL"
exit 1
fi
2017-02-07 21:19:05 +00:00
if [ " $SUDO_EXEC " = = "yes" ] ; then
if ! type sudo > /dev/null 2>& 1 ; then
Logger "sudo not present. Sync cannot start." "CRITICAL"
exit 1
fi
fi
2015-11-12 00:37:43 +00:00
}
2016-12-03 08:53:44 +00:00
# Only gets checked in config file mode where all values should be present
2015-11-28 11:03:28 +00:00
function CheckCurrentConfig {
2018-10-01 08:08:22 +00:00
local fullCheck = " ${ 1 :- true } "
__CheckArguments 1 $# " $@ " #__WITH_PARANOIA_DEBUG
# Full check is for initiator driven runs
if [ $fullCheck = = true ] ; then
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)
declare -a num_vars = ( MINIMUM_SPACE BANDWIDTH SOFT_MAX_EXEC_TIME HARD_MAX_EXEC_TIME KEEP_LOGGING MIN_WAIT MAX_WAIT CONFLICT_BACKUP_DAYS SOFT_DELETE_DAYS RESUME_TRY MAX_EXEC_TIME_PER_CMD_BEFORE MAX_EXEC_TIME_PER_CMD_AFTER)
# target-helper runs need less configuration
else
declare -a yes_no_vars = ( SUDO_EXEC SSH_COMPRESSION SSH_IGNORE_KNOWN_HOSTS REMOTE_HOST_PING STOP_ON_CMD_ERROR RUN_AFTER_CMD_ON_ERROR)
declare -a num_vars = ( KEEP_LOGGING MIN_WAIT MAX_WAIT)
fi
2016-12-11 19:54:40 +00:00
# Check all variables that should contain "yes" or "no"
for i in " ${ yes_no_vars [@] } " ; do
test = " if [ \"\$ $i \" != \"yes\" ] && [ \"\$ $i \" != \"no\" ]; then Logger \"Bogus $i value [\$ $i ] defined in config file. Correct your config file or update it using the update script if using and old version.\" \"CRITICAL\"; exit 1; fi "
eval " $test "
done
# Check all variables that should contain a numerical value >= 0
for i in " ${ num_vars [@] } " ; do
2016-11-13 14:53:16 +00:00
test = " if [ $( IsNumericExpand \" \$ $i \" ) -eq 0 ]; then Logger \"Bogus $i value [\$ $i ] defined in config file. Correct your config file or update it using the update script if using and old version.\" \"CRITICAL\"; exit 1; fi "
2016-12-11 19:54:40 +00:00
eval " $test "
done
2016-08-28 16:22:37 +00:00
}
2016-12-03 08:53:44 +00:00
# Gets checked in quicksync and config file mode
2016-08-28 16:22:37 +00:00
function CheckCurrentConfigAll {
2016-12-11 19:54:40 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-08-28 16:22:37 +00:00
2016-11-16 14:47:42 +00:00
local tmp
2016-12-11 19:54:40 +00:00
if [ " $INSTANCE_ID " = = "" ] ; then
Logger "No INSTANCE_ID defined in config file." "CRITICAL"
exit 1
fi
2015-11-28 11:03:28 +00:00
if [ " $INITIATOR_SYNC_DIR " = = "" ] ; then
Logger "No INITIATOR_SYNC_DIR set in config file." "CRITICAL"
exit 1
fi
if [ " $TARGET_SYNC_DIR " = = "" ] ; then
Logger "Not TARGET_SYNC_DIR set in config file." "CRITICAL"
exit 1
fi
2016-10-19 10:28:11 +00:00
if [ " $REMOTE_OPERATION " = = "yes" ] && ( [ ! -f " $SSH_RSA_PRIVATE_KEY " ] && [ ! -f " $SSH_PASSWORD_FILE " ] ) ; then
Logger " Cannot find rsa private key [ $SSH_RSA_PRIVATE_KEY ] nor password file [ $SSH_PASSWORD_FILE ]. No authentication method provided. " "CRITICAL"
2016-08-28 15:58:03 +00:00
exit 1
fi
2016-10-21 10:38:03 +00:00
2016-11-16 14:47:42 +00:00
if [ " $SKIP_DELETION " != "" ] ; then
tmp = " $SKIP_DELETION "
IFS = ',' read -r -a SKIP_DELETION <<< " $tmp "
2016-12-06 20:32:27 +00:00
if [ $( ArrayContains " ${ INITIATOR [ $__type ] } " " ${ SKIP_DELETION [@] } " ) -eq 0 ] && [ $( ArrayContains " ${ TARGET [ $__type ] } " " ${ SKIP_DELETION [@] } " ) -eq 0 ] ; then
2016-11-16 14:47:42 +00:00
Logger " Bogus skip deletion parameter [ $SKIP_DELETION ]. " "CRITICAL"
exit 1
fi
2016-10-21 10:38:03 +00:00
fi
2015-11-28 11:03:28 +00:00
}
2015-11-12 00:37:43 +00:00
###### Osync specific functions (non shared)
2016-12-06 21:41:44 +00:00
function _CheckReplicasLocal {
2016-12-06 12:30:05 +00:00
local replicaPath = " ${ 1 } "
2016-12-15 10:24:45 +00:00
local replicaType = " ${ 2 } "
__CheckArguments 2 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-08-02 08:01:48 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-12-06 21:41:44 +00:00
local diskSpace
2015-11-12 00:37:43 +00:00
2016-12-06 12:30:05 +00:00
if [ ! -d " $replicaPath " ] ; then
2015-11-12 00:37:43 +00:00
if [ " $CREATE_DIRS " = = "yes" ] ; then
2016-12-19 12:19:21 +00:00
mkdir -p " $replicaPath " >> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " 2>& 1
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger " Cannot create local replica path [ $replicaPath ]. " "CRITICAL" $retval
2016-12-15 10:24:45 +00:00
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2016-12-06 21:41:44 +00:00
return 1
2015-11-12 00:37:43 +00:00
else
2016-12-06 12:30:05 +00:00
Logger " Created local replica path [ $replicaPath ]. " "NOTICE"
2015-11-12 00:37:43 +00:00
fi
else
2017-02-03 08:52:24 +00:00
Logger " Local replica path [ $replicaPath ] does not exist / is not writable. " "CRITICAL"
2016-12-06 21:41:44 +00:00
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}' )
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot get free space." "ERROR" $retval
2016-12-06 21:41:44 +00:00
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"
2015-11-12 00:37:43 +00:00
fi
fi
}
2016-12-06 21:41:44 +00:00
function _CheckReplicasRemote {
2016-12-06 12:30:05 +00:00
local replicaPath = " ${ 1 } "
2016-12-15 10:24:45 +00:00
local replicaType = " ${ 2 } "
2016-12-15 11:01:10 +00:00
__CheckArguments 2 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-08-02 08:01:48 +00:00
local cmd
2016-02-18 15:21:17 +00:00
2015-11-12 00:37:43 +00:00
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
2016-08-02 08:01:48 +00:00
2017-02-08 12:52:04 +00:00
$SSH_CMD env _REMOTE_TOKEN = " $_REMOTE_TOKEN " \
env _DEBUG = " ' $_DEBUG ' " env _PARANOIA_DEBUG = " ' $_PARANOIA_DEBUG ' " env _LOGGER_SILENT = " ' $_LOGGER_SILENT ' " env _LOGGER_VERBOSE = " ' $_LOGGER_VERBOSE ' " env _LOGGER_PREFIX = " ' $_LOGGER_PREFIX ' " env _LOGGER_ERR_ONLY = " ' $_LOGGER_ERR_ONLY ' " \
2018-09-30 14:08:12 +00:00
env PROGRAM = " ' $PROGRAM ' " env SCRIPT_PID = " ' $SCRIPT_PID ' " env TSTAMP = " ' $TSTAMP ' " \
2017-06-07 10:48:52 +00:00
env replicaPath = " ' $replicaPath ' " env CREATE_DIRS = " ' $CREATE_DIRS ' " env DF_CMD = " ' $DF_CMD ' " env MINIMUM_SPACE = " ' $MINIMUM_SPACE ' " \
env LC_ALL = C $COMMAND_SUDO ' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME [ 0] } .$replicaType .$SCRIPT_PID .$TSTAMP " 2>&1
2016-12-07 20:30:10 +00:00
include #### DEBUG SUBSET ####
include #### TrapError SUBSET ####
include #### IsInteger SUBSET ####
include #### HumanToNumeric SUBSET ####
include #### RemoteLogger SUBSET ####
2016-12-19 12:19:21 +00:00
2016-12-06 21:41:44 +00:00
function _CheckReplicasRemoteSub {
if [ ! -d " $replicaPath " ] ; then
if [ " $CREATE_DIRS " = = "yes" ] ; then
2016-12-19 12:19:21 +00:00
mkdir -p " $replicaPath "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
RemoteLogger " Cannot create remote replica path [ $replicaPath ]. " "CRITICAL" $retval
2016-12-06 21:41:44 +00:00
exit 1
else
2016-12-07 20:30:10 +00:00
RemoteLogger " Created remote replica path [ $replicaPath ]. " "NOTICE"
2016-12-06 21:41:44 +00:00
fi
else
2017-02-03 08:52:24 +00:00
RemoteLogger " Remote replica path [ $replicaPath ] does not exist / is not writable. " "CRITICAL"
2016-08-20 08:43:22 +00:00
exit 1
fi
fi
2015-11-12 00:37:43 +00:00
2016-12-06 21:41:44 +00:00
if [ ! -w " $replicaPath " ] ; then
2016-12-07 20:30:10 +00:00
RemoteLogger " Remote replica path [ $replicaPath ] is not writable. " "CRITICAL"
2016-08-18 21:28:25 +00:00
exit 1
fi
2015-11-12 00:37:43 +00:00
2016-12-07 20:30:10 +00:00
RemoteLogger " Checking minimum disk space in remote replica [ $replicaPath ]. " "NOTICE"
2016-12-06 12:30:05 +00:00
diskSpace = $( $DF_CMD " $replicaPath " | tail -1 | awk '{print $4}' )
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
RemoteLogger "Cannot get free space." "ERROR" $retval
2016-11-18 11:49:48 +00:00
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
2016-12-07 20:30:10 +00:00
RemoteLogger " There is not enough free space on remote replica [ $replicaPath ] ( $diskSpace KB). " "WARN"
2016-11-18 11:49:48 +00:00
fi
2015-11-12 00:37:43 +00:00
fi
}
2016-12-06 21:41:44 +00:00
_CheckReplicasRemoteSub
exit $?
2016-12-06 12:30:05 +00:00
ENDSSH
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Failed to check remote replica." "CRITICAL" $retval
2016-12-06 21:41:44 +00:00
fi
2016-12-15 10:24:45 +00:00
if [ -s " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
2016-12-06 21:41:44 +00:00
(
_LOGGER_PREFIX = ""
2016-12-15 10:24:45 +00:00
Logger " $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "NOTICE"
2016-12-06 21:41:44 +00:00
)
fi
2016-12-11 13:26:48 +00:00
if [ $retval -ne 0 ] ; then
return $retval
2015-11-12 00:37:43 +00:00
else
2016-12-06 21:41:44 +00:00
return 0
2015-11-12 00:37:43 +00:00
fi
}
2016-12-06 21:41:44 +00:00
function CheckReplicas {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2018-10-07 10:59:56 +00:00
local initiatorPid
local targetPid
2016-12-11 13:26:48 +00:00
local retval
2016-08-03 22:52:05 +00:00
2016-12-06 21:41:44 +00:00
if [ " $REMOTE_OPERATION " != "yes" ] ; then
if [ " ${ INITIATOR [ $__replicaDir ] } " = = " ${ TARGET [ $__replicaDir ] } " ] ; then
Logger " Initiator and target path [ ${ INITIATOR [ $__replicaDir ] } ] cannot be the same. " "CRITICAL"
exit 1
fi
2016-08-03 22:02:20 +00:00
fi
2016-12-15 10:24:45 +00:00
_CheckReplicasLocal " ${ INITIATOR [ $__replicaDir ] } " " ${ INITIATOR [ $__type ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2015-11-12 00:37:43 +00:00
if [ " $REMOTE_OPERATION " != "yes" ] ; then
2016-12-15 10:24:45 +00:00
_CheckReplicasLocal " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2015-11-12 00:37:43 +00:00
else
2016-12-15 10:24:45 +00:00
_CheckReplicasRemote " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2015-11-12 00:37:43 +00:00
fi
2018-10-07 10:59:56 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 720 1800 true $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cancelling task." "CRITICAL" $retval
2016-12-06 21:41:44 +00:00
exit 1
fi
2015-11-12 00:37:43 +00:00
}
2016-12-06 20:32:27 +00:00
function _HandleLocksLocal {
2016-12-06 12:30:05 +00:00
local replicaStateDir = " ${ 1 } "
2016-12-06 20:32:27 +00:00
local lockfile = " ${ 2 } "
local replicaType = " ${ 3 } "
local overwrite = " ${ 4 :- false } "
2016-12-07 20:30:10 +00:00
__CheckArguments 4 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-12-06 20:32:27 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-12-06 20:32:27 +00:00
local lockfileContent
local lockPid
local lockInstanceID
2017-11-22 14:02:17 +00:00
local writeLocks = false
2015-11-12 00:37:43 +00:00
2016-12-06 12:30:05 +00:00
if [ ! -d " $replicaStateDir " ] ; then
2016-12-19 12:19:21 +00:00
mkdir -p " $replicaStateDir " > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " 2>& 1
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger " Cannot create state dir [ $replicaStateDir ]. " "CRITICAL" $retval
2016-12-15 10:24:45 +00:00
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2016-12-06 20:32:27 +00:00
return 1
2016-08-02 08:01:48 +00:00
fi
2015-11-12 00:37:43 +00:00
fi
2016-12-06 20:32:27 +00:00
# Skip the whole part if overwrite true
if [ -s " $lockfile " ] && [ $overwrite != true ] ; then
2016-11-17 11:13:56 +00:00
lockfileContent = $( cat $lockfile )
Logger " Master lock pid present: $lockfileContent " "DEBUG"
2016-12-06 20:32:27 +00:00
lockPid = " ${ lockfileContent %@* } "
2016-11-17 11:13:56 +00:00
if [ $( IsInteger $lockPid ) -ne 1 ] ; then
Logger " Invalid pid [ $lockPid ] in local replica. " "CRITICAL"
2016-12-06 20:32:27 +00:00
return 1
2016-11-17 11:13:56 +00:00
fi
2016-12-06 20:32:27 +00:00
lockInstanceID = " ${ lockfileContent #*@ } "
2016-11-17 11:13:56 +00:00
if [ " $lockInstanceID " = = "" ] ; then
Logger " Invalid instance id [ $lockInstanceID ] in local replica. " "CRITICAL"
2016-12-06 20:32:27 +00:00
return 1
2016-11-17 12:29:34 +00:00
Logger " Local $replicaType lock is: [ $lockPid @ $lockInstanceID ]. " "DEBUG"
2016-11-17 11:13:56 +00:00
fi
kill -0 $lockPid > /dev/null 2>& 1
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
2016-11-17 12:29:34 +00:00
Logger " There is a local dead osync lock [ $lockPid @ $lockInstanceID ] that is no longer running. Resuming. " "NOTICE"
2016-12-06 20:32:27 +00:00
writeLocks = true
2015-11-12 00:37:43 +00:00
else
2016-12-11 13:26:48 +00:00
Logger " There is already a local instance [ $lockPid @ $lockInstanceID ] of osync running for this replica. Cannot start. " "CRITICAL" $retval
2016-12-06 20:32:27 +00:00
return 1
fi
else
writeLocks = true
fi
if [ $writeLocks != true ] ; then
return 1
else
2016-12-19 12:19:21 +00:00
echo " $SCRIPT_PID @ $INSTANCE_ID " > " $lockfile " 2> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger " Could not create lock file on local $replicaType in [ $lockfile ]. " "CRITICAL" $retval
2016-12-15 10:24:45 +00:00
Logger " Command output\n $( $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2016-12-06 20:32:27 +00:00
return 1
else
Logger " Locked local $replicaType replica in [ $lockfile ]. " "DEBUG"
2015-11-12 00:37:43 +00:00
fi
fi
}
2016-12-06 20:32:27 +00:00
function _HandleLocksRemote {
local replicaStateDir = " ${ 1 } "
local lockfile = " ${ 2 } "
local replicaType = " ${ 3 } "
local overwrite = " ${ 4 :- false } "
2015-11-12 00:37:43 +00:00
2016-12-07 20:30:10 +00:00
__CheckArguments 4 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-12-06 20:32:27 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-12-06 20:32:27 +00:00
local initiatorRunningPids
2016-02-18 15:21:17 +00:00
2015-11-12 00:37:43 +00:00
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
2016-12-06 20:32:27 +00:00
# Create an array of all currently running pids
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)
2017-02-08 12:52:04 +00:00
$SSH_CMD env _REMOTE_TOKEN = " $_REMOTE_TOKEN " \
env _DEBUG = " ' $_DEBUG ' " env _PARANOIA_DEBUG = " ' $_PARANOIA_DEBUG ' " env _LOGGER_SILENT = " ' $_LOGGER_SILENT ' " env _LOGGER_VERBOSE = " ' $_LOGGER_VERBOSE ' " env _LOGGER_PREFIX = " ' $_LOGGER_PREFIX ' " env _LOGGER_ERR_ONLY = " ' $_LOGGER_ERR_ONLY ' " \
2018-09-30 14:08:12 +00:00
env PROGRAM = " ' $PROGRAM ' " env SCRIPT_PID = " ' $SCRIPT_PID ' " env TSTAMP = " ' $TSTAMP ' " \
2016-12-12 10:16:53 +00:00
env replicaStateDir = " ' $replicaStateDir ' " env initiatorRunningPidsFlat = " \"( ${ initiatorRunningPids [@] } )\" " env lockfile = " ' $lockfile ' " env replicaType = " ' $replicaType ' " env overwrite = " ' $overwrite ' " \
2017-06-07 10:48:52 +00:00
env INSTANCE_ID = " ' $INSTANCE_ID ' " env FORCE_STRANGER_LOCK_RESUME = " ' $FORCE_STRANGER_LOCK_RESUME ' " \
env LC_ALL = C $COMMAND_SUDO ' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME [ 0] } .$replicaType .$SCRIPT_PID .$TSTAMP " 2>&1
2016-12-07 20:30:10 +00:00
include #### DEBUG SUBSET ####
include #### TrapError SUBSET ####
2016-12-08 07:56:13 +00:00
include #### ArrayContains SUBSET ####
2016-12-07 20:30:10 +00:00
include #### IsInteger SUBSET ####
include #### RemoteLogger SUBSET ####
2015-11-12 00:37:43 +00:00
2016-12-06 20:32:27 +00:00
function _HandleLocksRemoteSub {
2017-11-22 14:02:17 +00:00
local writeLocks = false
2016-12-06 20:32:27 +00:00
if [ ! -d " $replicaStateDir " ] ; then
2016-12-19 12:19:21 +00:00
mkdir -p " $replicaStateDir "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
RemoteLogger " Cannot create state dir [ $replicaStateDir ]. " "CRITICAL" $retval
2016-12-06 20:32:27 +00:00
return 1
fi
fi
2016-11-17 11:13:56 +00:00
2016-12-06 20:32:27 +00:00
# Skip the whole part if overwrite true
if [ -s " $lockfile " ] && [ $overwrite != true ] ; then
lockfileContent = $( cat $lockfile )
2016-12-07 20:30:10 +00:00
RemoteLogger " Master lock pid present: $lockfileContent " "DEBUG"
2016-12-06 20:32:27 +00:00
lockPid = " ${ lockfileContent %@* } "
2016-11-17 11:13:56 +00:00
if [ $( IsInteger $lockPid ) -ne 1 ] ; then
2016-12-07 20:30:10 +00:00
RemoteLogger " Invalid pid [ $lockPid ] in local replica. " "CRITICAL"
2016-12-06 20:32:27 +00:00
return 1
2016-11-17 11:13:56 +00:00
fi
2016-12-06 20:32:27 +00:00
lockInstanceID = " ${ lockfileContent #*@ } "
2016-11-17 11:13:56 +00:00
if [ " $lockInstanceID " = = "" ] ; then
2016-12-07 20:30:10 +00:00
RemoteLogger " Invalid instance id [ $lockInstanceID ] in local replica. " "CRITICAL"
2016-12-06 20:32:27 +00:00
return 1
2015-11-12 00:37:43 +00:00
2016-12-07 20:30:10 +00:00
RemoteLogger " Local $replicaType lock is: [ $lockPid @ $lockInstanceID ]. " "DEBUG"
2015-11-12 00:37:43 +00:00
2016-12-06 20:32:27 +00:00
fi
# Retransform litteral array string to array
eval " initiatorRunningPids= $initiatorRunningPidsFlat "
if [ $( ArrayContains " $lockPid " " ${ initiatorRunningPids [@] } " ) -eq 0 ] ; then
2016-11-17 11:13:56 +00:00
if [ " $lockInstanceID " = = " $INSTANCE_ID " ] ; then
2016-12-07 20:30:10 +00:00
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"
2016-12-06 20:32:27 +00:00
writeLocks = true
2015-11-12 00:37:43 +00:00
else
if [ " $FORCE_STRANGER_LOCK_RESUME " = = "yes" ] ; then
2016-12-07 20:30:10 +00:00
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"
2016-12-06 20:32:27 +00:00
writeLocks = true
2015-11-12 00:37:43 +00:00
else
2016-12-07 20:30:10 +00:00
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"
2016-12-06 20:32:27 +00:00
return 1
2015-11-12 00:37:43 +00:00
fi
fi
else
2016-12-07 20:30:10 +00:00
RemoteLogger " There is already a local instance of osync that locks target replica [ $lockPid @ $lockInstanceID ]. Cannot start. " "CRITICAL"
2016-12-06 20:32:27 +00:00
return 1
fi
else
writeLocks = true
fi
if [ $writeLocks != true ] ; then
return 1
else
2016-12-19 12:19:21 +00:00
echo " $SCRIPT_PID @ $INSTANCE_ID " > " $lockfile "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
RemoteLogger " Could not create lock file on local $replicaType in [ $lockfile ]. " "CRITICAL" $retval
2016-12-06 20:32:27 +00:00
return 1
else
2016-12-07 20:30:10 +00:00
RemoteLogger " Locked local $replicaType replica in [ $lockfile ]. " "DEBUG"
2015-11-12 00:37:43 +00:00
fi
fi
}
2016-12-06 20:32:27 +00:00
_HandleLocksRemoteSub
2016-12-11 13:36:26 +00:00
exit $?
2016-12-06 20:32:27 +00:00
ENDSSH
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Remote lock handling failed." "CRITICAL" $retval
2016-12-06 21:41:44 +00:00
fi
2016-12-15 10:24:45 +00:00
if [ -s " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
2016-12-06 21:41:44 +00:00
(
_LOGGER_PREFIX = ""
2016-12-15 10:24:45 +00:00
Logger " $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "NOTICE"
2016-12-06 21:41:44 +00:00
)
fi
2016-12-11 13:26:48 +00:00
if [ $retval -ne 0 ] ; then
2016-12-06 20:32:27 +00:00
return 1
fi
}
function HandleLocks {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-11 13:26:48 +00:00
local retval
2017-11-23 15:58:29 +00:00
local initiatorPid
local targetPid
2016-12-06 20:32:27 +00:00
local overwrite = false
2016-08-03 22:52:05 +00:00
2017-11-23 15:58:29 +00:00
# Assume lock files are created successfully unless stated otherwise
local initiatorLockSuccess = true
local targetLockSuccess = true
2016-08-29 11:54:24 +00:00
if [ $_NOLOCKS = = true ] ; then
2015-11-12 00:37:43 +00:00
return 0
fi
# Do not bother checking for locks when FORCE_UNLOCK is set
2016-08-29 11:54:24 +00:00
if [ $FORCE_UNLOCK = = true ] ; then
2016-12-06 20:32:27 +00:00
overwrite = true
2018-01-02 19:02:57 +00:00
fi
2017-11-23 15:58:29 +00:00
2018-01-02 19:02:57 +00:00
_HandleLocksLocal " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } " " ${ INITIATOR [ $__lockFile ] } " " ${ INITIATOR [ $__type ] } " $overwrite &
initiatorPid = $!
if [ " $REMOTE_OPERATION " != "yes" ] ; then
_HandleLocksLocal " ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__stateDir ] } " " ${ TARGET [ $__lockFile ] } " " ${ TARGET [ $__type ] } " $overwrite &
targetPid = $!
else
_HandleLocksRemote " ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__stateDir ] } " " ${ TARGET [ $__lockFile ] } " " ${ TARGET [ $__type ] } " $overwrite &
targetPid = $!
fi
2018-10-07 10:59:56 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 720 1800 true $SLEEP_TIME $KEEP_LOGGING
2018-01-02 19:02:57 +00:00
retval = $?
if [ $retval -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
initiatorLockSuccess = false
elif [ " $pid " = = " $targetPid " ] ; then
targetLockSuccess = false
2017-11-23 15:58:29 +00:00
fi
2018-01-02 19:02:57 +00:00
done
2017-11-23 15:58:29 +00:00
2018-01-02 19:02:57 +00:00
#WIP refactor the following
if [ $initiatorLockSuccess = = true ] ; then
INITIATOR_LOCK_FILE_EXISTS = true
fi
if [ $targetLockSuccess = = true ] ; then
TARGET_LOCK_FILE_EXISTS = true
2016-11-17 11:13:56 +00:00
fi
2018-01-02 19:02:57 +00:00
Logger "Cancelling task." "CRITICAL" $retval
exit 1
2016-08-18 21:28:25 +00:00
fi
2018-01-02 19:02:57 +00:00
if [ $initiatorLockSuccess = = true ] ; then
INITIATOR_LOCK_FILE_EXISTS = true
fi
if [ $targetLockSuccess = = true ] ; then
TARGET_LOCK_FILE_EXISTS = true
fi
2016-08-02 08:01:48 +00:00
}
2015-11-12 00:37:43 +00:00
function _UnlockReplicasLocal {
local lockfile = " ${ 1 } "
2016-12-15 10:24:45 +00:00
local replicaType = " ${ 2 } "
__CheckArguments 2 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-11 13:26:48 +00:00
local retval
2015-11-12 00:37:43 +00:00
if [ -f " $lockfile " ] ; then
2017-08-14 20:21:41 +00:00
rm -f " $lockfile "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
2016-12-15 10:24:45 +00:00
Logger " Could not unlock local $replicaType replica. " "ERROR" $retval
2015-11-12 00:37:43 +00:00
else
2016-12-15 10:24:45 +00:00
Logger " Removed local $replicaType replica lock. " "DEBUG"
2015-11-12 00:37:43 +00:00
fi
fi
}
function _UnlockReplicasRemote {
local lockfile = " ${ 1 } "
2016-12-15 10:24:45 +00:00
local replicaType = " ${ 2 } "
__CheckArguments 2 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-11 13:26:48 +00:00
local retval
local cmd
2016-02-18 15:21:17 +00:00
2015-11-12 00:37:43 +00:00
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
2017-02-08 12:52:04 +00:00
$SSH_CMD env _REMOTE_TOKEN = " $_REMOTE_TOKEN " \
env _DEBUG = " ' $_DEBUG ' " env _PARANOIA_DEBUG = " ' $_PARANOIA_DEBUG ' " env _LOGGER_SILENT = " ' $_LOGGER_SILENT ' " env _LOGGER_VERBOSE = " ' $_LOGGER_VERBOSE ' " env _LOGGER_PREFIX = " ' $_LOGGER_PREFIX ' " env _LOGGER_ERR_ONLY = " ' $_LOGGER_ERR_ONLY ' " \
2018-09-30 14:08:12 +00:00
env PROGRAM = " ' $PROGRAM ' " env SCRIPT_PID = " ' $SCRIPT_PID ' " env TSTAMP = " ' $TSTAMP ' " env lockfile = " ' $lockfile ' " \
2017-06-07 10:48:52 +00:00
env LC_ALL = C $COMMAND_SUDO ' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME [ 0] } .$replicaType .$SCRIPT_PID .$TSTAMP " 2>&1
2016-12-06 12:30:05 +00:00
if [ -f " $lockfile " ] ; then
2016-12-19 12:19:21 +00:00
rm -f " $lockfile "
2016-12-06 12:30:05 +00:00
fi
ENDSSH
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
2016-12-15 10:24:45 +00:00
Logger " Could not unlock $replicaType remote replica. " "ERROR" $retval
Logger " Command Output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2015-11-12 00:37:43 +00:00
else
2016-12-15 10:24:45 +00:00
Logger " Removed remote $replicaType replica lock. " "DEBUG"
2015-11-12 00:37:43 +00:00
fi
}
function UnlockReplicas {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2018-10-07 10:59:56 +00:00
local initiatorPid
local targetPid
2016-08-03 22:52:05 +00:00
2016-08-29 11:54:24 +00:00
if [ $_NOLOCKS = = true ] ; then
2015-11-12 00:37:43 +00:00
return 0
fi
2016-08-28 16:22:37 +00:00
if [ $INITIATOR_LOCK_FILE_EXISTS = = true ] ; then
2016-12-15 10:24:45 +00:00
_UnlockReplicasLocal " ${ INITIATOR [ $__lockFile ] } " " ${ INITIATOR [ $__type ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2016-08-28 16:22:37 +00:00
fi
2016-07-27 10:04:27 +00:00
2016-08-28 16:22:37 +00:00
if [ $TARGET_LOCK_FILE_EXISTS = = true ] ; then
if [ " $REMOTE_OPERATION " != "yes" ] ; then
2016-12-15 10:24:45 +00:00
_UnlockReplicasLocal " ${ TARGET [ $__lockFile ] } " " ${ TARGET [ $__type ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2016-08-28 16:22:37 +00:00
else
2016-12-15 10:24:45 +00:00
_UnlockReplicasRemote " ${ TARGET [ $__lockFile ] } " " ${ TARGET [ $__type ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2016-08-28 16:22:37 +00:00
fi
fi
2018-10-07 10:59:56 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 720 1800 true $SLEEP_TIME $KEEP_LOGGING
2015-11-12 00:37:43 +00:00
}
###### Sync core functions
## Rsync does not like spaces in directory names, considering it as two different directories. Handling this schema by escaping space.
2016-10-16 12:25:29 +00:00
## It seems this only happens when trying to execute an rsync command through weval $rsyncCmd on a remote host.
2015-11-12 00:37:43 +00:00
## So I am using unescaped $INITIATOR_SYNC_DIR for local rsync calls and escaped $ESC_INITIATOR_SYNC_DIR for remote rsync calls like user@host:$ESC_INITIATOR_SYNC_DIR
## The same applies for target sync dir..............................................T.H.I.S..I.S..A..P.R.O.G.R.A.M.M.I.N.G..N.I.G.H.T.M.A.R.E
2016-10-16 12:25:29 +00:00
function treeList {
local replicaPath = " ${ 1 } " # path to the replica for which a tree needs to be constructed
2016-09-16 07:48:58 +00:00
local replicaType = " ${ 2 } " # replica type: initiator, target
2016-10-16 12:25:29 +00:00
local treeFilename = " ${ 3 } " # filename to output tree (will be prefixed with $replicaType)
2016-02-18 15:21:17 +00:00
2016-12-07 20:30:10 +00:00
__CheckArguments 3 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-11-15 20:27:32 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-10-16 12:25:29 +00:00
local escapedReplicaPath
local rsyncCmd
2016-02-18 15:21:17 +00:00
2016-10-16 12:25:29 +00:00
escapedReplicaPath = $( EscapeSpaces " $replicaPath " )
2015-11-12 00:37:43 +00:00
2016-12-01 18:24:01 +00:00
# operation explanation
# (command || :) = Return code 0 regardless of command return code
# (grep -E \"^-|^d|^l\" || :) = Be sure line begins with '-' or 'd' or 'l' (rsync semantics for file, directory or symlink)
2017-06-08 14:30:20 +00:00
# (sed -r 's/^.{10} +[0-9,]+ [0-9/]{10} [0-9:]{8} //' || :) = Remove everything before timestamps
2017-06-04 11:01:34 +00:00
# (awk 'BEGIN { FS=\" -> \" } ; { print \$1 }' || :) = Only show output before ' -> ' in order to remove symlink destinations
2016-12-01 18:24:01 +00:00
# (grep -v \"^\.$\" || :) = Removes line containing current directory sign '.'
2016-10-16 12:25:29 +00:00
Logger " Creating $replicaType replica file list [ $replicaPath ]. " "NOTICE"
2016-09-16 07:48:58 +00:00
if [ " $REMOTE_OPERATION " = = "yes" ] && [ " $replicaType " = = " ${ TARGET [ $__type ] } " ] ; then
2015-11-12 00:37:43 +00:00
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
2018-09-30 11:57:57 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" $RSYNC_DEFAULT_ARGS $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE -e \" $RSYNC_SSH_CMD \" --list-only $REMOTE_USER @ $REMOTE_HOST :\" $escapedReplicaPath \" 2> \" $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType .error. $SCRIPT_PID . $TSTAMP \" | (grep -E \"^-|^d|^l\" || :) | (sed $SED_REGEX_ARG 's/^.{10} +[0-9,]+ [0-9/]{10} [0-9:]{8} //' || :) | (awk 'BEGIN { FS=\" -> \" } ; { print \$1 }' || :) | (grep -v \"^\. $\" || :) | sort > \" $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP \" "
2015-11-12 00:37:43 +00:00
else
2018-09-30 11:57:57 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" $RSYNC_DEFAULT_ARGS $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --list-only \" $replicaPath \" 2> \" $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType .error. $SCRIPT_PID . $TSTAMP \" | (grep -E \"^-|^d|^l\" || :) | (sed $SED_REGEX_ARG 's/^.{10} +[0-9,]+ [0-9/]{10} [0-9:]{8} //' || :) | (awk 'BEGIN { FS=\" -> \" } ; { print \$1 }' || :) | (grep -v \"^\. $\" || :) | sort > \" $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP \" "
2015-11-12 00:37:43 +00:00
fi
2016-10-16 12:25:29 +00:00
Logger " RSYNC_CMD: $rsyncCmd " "DEBUG"
eval " $rsyncCmd "
2015-11-12 00:37:43 +00:00
retval = $?
2016-10-17 07:56:40 +00:00
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
2017-05-31 16:02:18 +00:00
mv -f " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " " $treeFilename "
2016-10-17 07:56:40 +00:00
fi
## Retval 24 = some files vanished while creating list
2016-12-11 13:26:48 +00:00
if ( [ $retval -eq 0 ] || [ $retval -eq 24 ] ) then
2015-11-12 00:37:43 +00:00
return $?
2016-12-11 13:26:48 +00:00
elif [ $retval -eq 23 ] ; then
Logger " Some files could not be listed in $replicaType replica [ $replicaPath ]. Check for failing symlinks. " "ERROR" $retval
2016-12-14 07:12:35 +00:00
Logger " Command output\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .error.$SCRIPT_PID .$TSTAMP ) " "WARN"
2016-10-16 10:12:59 +00:00
return 0
2015-11-12 00:37:43 +00:00
else
2016-12-11 13:26:48 +00:00
Logger " Cannot create replica file list in [ $replicaPath ]. " "CRITICAL" $retval
2017-02-10 10:15:41 +00:00
_LOGGER_SILENT = true Logger " Command was [ $rsyncCmd ]. " "WARN"
2016-12-15 09:12:36 +00:00
Logger " Command output\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .error.$SCRIPT_PID .$TSTAMP ) " "WARN"
2016-08-09 20:14:17 +00:00
return $retval
2015-11-12 00:37:43 +00:00
fi
}
2016-10-16 12:25:29 +00:00
# deleteList(replicaType): Creates a list of files vanished from last run on replica $1 (initiator/target)
function deleteList {
2016-09-16 07:48:58 +00:00
local replicaType = " ${ 1 } " # replica type: initiator, target
2016-12-15 10:24:45 +00:00
2016-12-07 20:30:10 +00:00
__CheckArguments 1 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-11 13:26:48 +00:00
local retval
local subretval
2016-08-04 09:52:28 +00:00
local cmd
2016-02-18 15:21:17 +00:00
2016-11-15 20:27:32 +00:00
local failedDeletionListFromReplica
if [ " $replicaType " = = " ${ INITIATOR [ $__type ] } " ] ; then
failedDeletionListFromReplica = " ${ TARGET [ $__type ] } "
elif [ " $replicaType " = = " ${ TARGET [ $__type ] } " ] ; then
failedDeletionListFromReplica = " ${ INITIATOR [ $__type ] } "
else
Logger " Bogus replicaType in [ ${ FUNCNAME [0] } ]. " "CRITICAL"
exit 1
fi
2016-09-16 07:48:58 +00:00
Logger " Creating $replicaType replica deleted file list. " "NOTICE"
2016-10-16 10:33:53 +00:00
if [ -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__treeAfterFileNoSuffix ] } " ] ; then
2015-11-12 00:37:43 +00:00
## Same functionnality, comm is much faster than grep but is not available on every platform
if type comm > /dev/null 2>& 1 ; then
2016-10-16 10:33:53 +00:00
cmd = " comm -23 \" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__treeAfterFileNoSuffix ] } \" \" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__treeCurrentFile ] } \" > \" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__deletedListFile ] } \" "
2015-11-12 00:37:43 +00:00
else
## The || : forces the command to have a good result
2016-10-16 10:33:53 +00:00
cmd = " (grep -F -x -v -f \" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__treeCurrentFile ] } \" \" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__treeAfterFileNoSuffix ] } \" || :) > \" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__deletedListFile ] } \" "
2015-11-12 00:37:43 +00:00
fi
2017-02-06 16:11:39 +00:00
Logger " Launching command [ $cmd ]. " "DEBUG"
2015-11-12 00:37:43 +00:00
eval " $cmd " 2>> " $LOG_FILE "
retval = $?
2016-12-11 13:26:48 +00:00
if [ $retval -ne 0 ] ; then
2017-02-06 16:11:39 +00:00
Logger " Could not prepare $replicaType deletion list. " "CRITICAL" $retval
2017-02-10 10:15:41 +00:00
_LOGGER_SILENT = true Logger " Command was [ $cmd ]. " "WARN"
2016-12-11 13:26:48 +00:00
return $retval
fi
2015-11-12 00:37:43 +00:00
# Add delete failed file list to current delete list and then empty it
2016-11-15 20:27:32 +00:00
if [ -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $failedDeletionListFromReplica ${ INITIATOR [ $__failedDeletedListFile ] } " ] ; then
cat " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $failedDeletionListFromReplica ${ INITIATOR [ $__failedDeletedListFile ] } " >> " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__deletedListFile ] } "
2016-12-11 13:26:48 +00:00
subretval = $?
2016-12-11 13:52:09 +00:00
if [ $subretval -eq 0 ] ; then
2016-11-15 20:27:32 +00:00
rm -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $failedDeletionListFromReplica ${ INITIATOR [ $__failedDeletedListFile ] } "
2016-10-16 10:33:53 +00:00
else
2016-12-11 13:26:48 +00:00
Logger " Cannot add failed deleted list to current deleted list for replica [ $replicaType ]. " "ERROR" $subretval
2016-10-16 10:33:53 +00:00
fi
2015-11-12 00:37:43 +00:00
fi
return $retval
else
2016-10-16 10:33:53 +00:00
touch " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__deletedListFile ] } "
2015-11-12 00:37:43 +00:00
return $retval
fi
}
2016-10-16 12:25:29 +00:00
function _getFileCtimeMtimeLocal {
local replicaPath = " ${ 1 } " # Contains replica path
2016-09-16 07:48:58 +00:00
local replicaType = " ${ 2 } " # Initiator / Target
2016-10-16 12:25:29 +00:00
local fileList = " ${ 3 } " # Contains list of files to get time attrs
2017-05-31 09:16:36 +00:00
local timestampFile = " ${ 4 } " # Where to store the timestamp file
2016-12-15 10:24:45 +00:00
2017-05-30 13:45:43 +00:00
__CheckArguments 4 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-02-17 12:51:42 +00:00
2016-12-11 13:26:48 +00:00
local retval
2018-10-07 11:23:45 +00:00
echo -n "" > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP "
while IFS = '' read -r file; do
$STAT_CTIME_MTIME_CMD " $replicaPath $file " >> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP "
done < " $fileList "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger " Getting file attributes failed [ $retval ] on $replicaType . Stopping execution. " "CRITICAL" $retval
2018-10-07 11:23:45 +00:00
if [ -s " $RUN_DIR / $PROGRAM .ctime_mtime. $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2016-08-29 11:54:24 +00:00
fi
2017-06-05 13:32:09 +00:00
return $retval
2017-05-31 16:02:18 +00:00
else
2018-10-07 11:23:45 +00:00
cat " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " | sort > " $timestampFile "
2017-06-05 13:32:09 +00:00
retval = $?
return $retval
2016-08-29 11:54:24 +00:00
fi
2016-02-16 19:52:53 +00:00
}
2016-10-16 12:25:29 +00:00
function _getFileCtimeMtimeRemote {
2016-11-13 19:12:09 +00:00
local replicaPath = " ${ 1 } " # Contains replica path
2016-09-16 07:48:58 +00:00
local replicaType = " ${ 2 } "
2016-10-16 12:25:29 +00:00
local fileList = " ${ 3 } "
2017-05-30 13:45:43 +00:00
local timestampFile = " ${ 4 } "
__CheckArguments 4 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-02-17 12:51:42 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-08-04 09:52:28 +00:00
local cmd
2018-10-07 15:51:15 +00:00
cmd = 'cat "' $fileList '" | ' $SSH_CMD ' "env LC_ALL=C env _REMOTE_TOKEN=$_REMOTE_TOKEN cat > \".$PROGRAM._getFileCtimeMtimeRemote.Sent.$replicaType.$SCRIPT_PID.$TSTAMP\""'
2017-02-06 16:11:39 +00:00
Logger " Launching command [ $cmd ]. " "DEBUG"
2018-10-07 11:23:45 +00:00
eval " $cmd " &
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger " Sending ctime required file list failed with [ $retval ] on $replicaType . Stopping execution. " "CRITICAL" $retval
2017-02-10 10:15:41 +00:00
_LOGGER_SILENT = true Logger " Command was [ $cmd ]. " "WARN"
2018-10-07 11:23:45 +00:00
if [ -s " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2016-12-08 20:59:52 +00:00
fi
2017-06-05 13:32:09 +00:00
return $retval
2016-12-08 20:59:52 +00:00
fi
2017-06-02 23:28:34 +00:00
2017-02-08 12:52:04 +00:00
$SSH_CMD env _REMOTE_TOKEN = " $_REMOTE_TOKEN " \
env _DEBUG = " ' $_DEBUG ' " env _PARANOIA_DEBUG = " ' $_PARANOIA_DEBUG ' " env _LOGGER_SILENT = " ' $_LOGGER_SILENT ' " env _LOGGER_VERBOSE = " ' $_LOGGER_VERBOSE ' " env _LOGGER_PREFIX = " ' $_LOGGER_PREFIX ' " env _LOGGER_ERR_ONLY = " ' $_LOGGER_ERR_ONLY ' " \
2018-09-30 14:08:12 +00:00
env PROGRAM = " ' $PROGRAM ' " env SCRIPT_PID = " ' $SCRIPT_PID ' " env TSTAMP = " ' $TSTAMP ' " \
2017-06-02 23:20:38 +00:00
env replicaPath = " ' $replicaPath ' " env replicaType = " ' $replicaType ' " env REMOTE_STAT_CTIME_MTIME_CMD = " ' $REMOTE_STAT_CTIME_MTIME_CMD ' " \
2018-10-07 11:23:45 +00:00
env LC_ALL = C $COMMAND_SUDO ' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME [ 0] } .$replicaType .$SCRIPT_PID .$TSTAMP "
while IFS = '' read -r file; do
$REMOTE_STAT_CTIME_MTIME_CMD " $replicaPath $file "
done < " . $PROGRAM .._getFileCtimeMtimeRemote.Sent. $replicaType . $SCRIPT_PID . $TSTAMP "
if [ -f " . $PROGRAM .._getFileCtimeMtimeRemote.Sent. $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
rm -f " . $PROGRAM .._getFileCtimeMtimeRemote.Sent. $replicaType . $SCRIPT_PID . $TSTAMP "
fi
2016-12-08 20:59:52 +00:00
ENDSSH
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger " Getting file attributes failed [ $retval ] on $replicaType . Stopping execution. " "CRITICAL" $retval
2018-10-07 11:23:45 +00:00
if [ -s " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2016-02-18 15:21:17 +00:00
fi
2016-12-11 13:26:48 +00:00
return $retval
2016-12-09 18:01:58 +00:00
else
# Ugly fix for csh in FreeBSD 11 that adds leading and trailing '\"'
2018-10-07 11:23:45 +00:00
sed -i.tmp -e 's/^\\"//' -e 's/\\"$//' " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP "
2017-06-05 13:32:09 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
2017-06-09 06:33:57 +00:00
Logger "Cannot fix FreeBSD 11 remote csh syntax." "ERROR"
2017-06-05 13:32:09 +00:00
return $retval
fi
2018-10-07 11:23:45 +00:00
cat " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $replicaType . $SCRIPT_PID . $TSTAMP " | sort > " $timestampFile "
2017-06-05 13:32:09 +00:00
if [ $retval -ne 0 ] ; then
Logger " Cannot create timestamp file for $replicaType . " "ERROR"
return $retval
fi
2016-02-18 15:21:17 +00:00
fi
2016-02-16 19:52:53 +00:00
}
2017-05-30 09:14:11 +00:00
#WIP function that takes treeList files and gets ctime and mtime for each file, then compares those files to create the conflict file list
2017-05-30 10:16:59 +00:00
function timestampList {
2017-05-30 09:14:11 +00:00
local replicaPath = " ${ 1 } " # path to the replica for which a tree needs to be constructed
local replicaType = " ${ 2 } " # replica type: initiator, target
2017-05-30 12:35:44 +00:00
local fileList = " ${ 3 } " # List of files to get timestamps for
local timestampFilename = " ${ 4 } " # filename to output timestamp list (will be prefixed with $replicaType)
2017-05-30 09:14:11 +00:00
__CheckArguments 4 $# " $@ " #__WITH_PARANOIA_DEBUG
local retval
local escapedReplicaPath
local rsyncCmd
2017-05-30 10:16:59 +00:00
2017-05-31 10:31:18 +00:00
Logger " Getting file stats for $replicaType replica [ $replicaPath ]. " "NOTICE"
2017-05-30 10:16:59 +00:00
2017-05-30 12:35:44 +00:00
if [ " $REMOTE_OPERATION " = = "yes" ] && [ " $replicaType " = = " ${ TARGET [ $__type ] } " ] ; then
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
_getFileCtimeMtimeRemote " $replicaPath " " $replicaType " " $fileList " " $timestampFilename "
else
_getFileCtimeMtimeLocal " $replicaPath " " $replicaType " " $fileList " " $timestampFilename "
fi
2017-06-01 15:45:02 +00:00
retval = $?
return $retval
2017-05-30 10:16:59 +00:00
}
function conflictList {
2017-06-01 15:45:02 +00:00
local timestampCurrentFilename = " ${ 1 } " # filename of current timestamp list (will be prefixed with $replicaType)
2017-06-03 11:51:49 +00:00
local timestampAfterFilename = " ${ 2 } " # filename of previous timestamp list (will be prefixed with $replicaType)
2017-05-30 10:16:59 +00:00
2018-10-06 19:41:58 +00:00
__CheckArguments 2 $# " $@ " #__WITH_PARANOIA_DEBUG
2017-05-30 10:16:59 +00:00
local retval
local escapedReplicaPath
2017-06-01 15:45:02 +00:00
if [ -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } $timestampCurrentFilename " ] && [ -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } $timestampCurrentFilename " ] ; then
# Remove prepending replicaPaths
sed -i'.replicaPath' " s;^ ${ INITIATOR [ $__replicaDir ] } ;;g " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } $timestampCurrentFilename "
2017-06-05 13:32:09 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot remove prepending replicaPaths for current initiator timestamp file." "ERROR"
return $retval
fi
2017-06-01 15:45:02 +00:00
sed -i'.replicaPath' " s;^ ${ TARGET [ $__replicaDir ] } ;;g " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } $timestampCurrentFilename "
2017-06-05 13:32:09 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot remove prepending replicaPaths for current target timestamp file." "ERROR"
return $retval
fi
2017-06-01 15:45:02 +00:00
fi
2017-06-03 11:51:49 +00:00
if [ -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } $timestampAfterFilename " ] && [ -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } $timestampAfterFilename " ] ; then
# Remove prepending replicaPaths
sed -i'.replicaPath' " s;^ ${ INITIATOR [ $__replicaDir ] } ;;g " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } $timestampAfterFilename "
2017-06-05 13:32:09 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot remove prepending replicaPaths for after initiator timestamp file." "ERROR"
return $retval
fi
2017-06-03 11:51:49 +00:00
sed -i'.replicaPath' " s;^ ${ TARGET [ $__replicaDir ] } ;;g " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } $timestampAfterFilename "
2017-06-05 13:32:09 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot remove prepending replicaPaths for after target timestamp file." "ERROR"
return $retval
fi
2017-06-03 11:51:49 +00:00
fi
2017-06-01 15:45:02 +00:00
2017-06-03 11:51:49 +00:00
if [ -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } $timestampAfterFilename " ] && [ -f " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } $timestampAfterFilename " ] ; then
2017-05-30 10:16:59 +00:00
2017-06-03 11:51:49 +00:00
Logger "Creating conflictual file list." "NOTICE"
2017-06-01 15:45:02 +00:00
2017-06-06 15:39:53 +00:00
comm -23 " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } $timestampCurrentFilename " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } $timestampAfterFilename " | sort -t ';' -k 1,1 > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . ${ INITIATOR [ $__type ] } . $SCRIPT_PID . $TSTAMP "
2017-06-05 13:32:09 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot extract conflict data for initiator replica." "ERROR"
return $retval
fi
2017-06-06 15:39:53 +00:00
comm -23 " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } $timestampCurrentFilename " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } $timestampAfterFilename " | sort -t ';' -k 1,1 > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . ${ TARGET [ $__type ] } . $SCRIPT_PID . $TSTAMP "
2017-06-05 13:32:09 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot extract conflict data for target replica.." "ERROR"
return $retval
fi
2017-05-30 12:35:44 +00:00
2018-07-02 20:09:18 +00:00
join -j 1 -t ';' -o 1.1,1.2,1.3,2.2,2.3 " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . ${ INITIATOR [ $__type ] } . $SCRIPT_PID . $TSTAMP " " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . ${ TARGET [ $__type ] } . $SCRIPT_PID . $TSTAMP " > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .compare. $SCRIPT_PID . $TSTAMP "
2017-06-05 13:32:09 +00:00
retval = $?
2018-10-01 18:28:46 +00:00
#WIP
2018-10-02 21:37:33 +00:00
if [ " $TRAVIS_RUN " = = true ] ; then
2018-10-01 18:28:46 +00:00
echo " conflictList debug retval= $retval "
cat " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . ${ INITIATOR [ $__type ] } . $SCRIPT_PID . $TSTAMP "
cat " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . ${ TARGET [ $__type ] } . $SCRIPT_PID . $TSTAMP "
cat " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .compare. $SCRIPT_PID . $TSTAMP "
fi
2017-06-05 13:32:09 +00:00
if [ $retval -ne 0 ] ; then
Logger "Cannot create conflict list file." "ERROR"
return $retval
fi
2017-06-03 11:51:49 +00:00
fi
2017-05-30 09:14:11 +00:00
}
2016-02-18 15:21:17 +00:00
# rsync does sync with mtime, but file attribute modifications only change ctime.
# Hence, detect newer ctime on the replica that gets updated first with CONFLICT_PREVALANCE and update all newer file attributes on this replica before real update
2016-10-16 12:25:29 +00:00
function syncAttrs {
local initiatorReplica = " ${ 1 } "
local targetReplica = " ${ 2 } "
2018-10-07 10:59:56 +00:00
2016-12-07 20:30:10 +00:00
__CheckArguments 2 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-02-16 19:52:53 +00:00
2018-10-07 10:59:56 +00:00
local initiatorPid
local targetPid
2016-10-16 12:25:29 +00:00
local rsyncCmd
2016-08-04 09:52:28 +00:00
local retval
2016-02-17 22:00:45 +00:00
2016-10-16 12:25:29 +00:00
local sourceDir
local destDir
local escSourceDir
local escDestDir
local destReplica
2016-08-29 19:54:51 +00:00
2016-11-19 11:54:24 +00:00
if [ " $LOCAL_OS " = = "BusyBox" ] || [ " $LOCAL_OS " = = "Android" ] || [ " $REMOTE_OS " = = "BusyBox" ] || [ " $REMOTE_OS " = = "Android" ] ; then
2016-11-14 20:14:10 +00:00
Logger "Skipping acl synchronization. Busybox does not have join command." "NOTICE"
2016-10-22 18:56:14 +00:00
return 0
fi
2016-04-02 12:47:28 +00:00
Logger "Getting list of files that need updates." "NOTICE"
2016-02-17 12:51:42 +00:00
2016-02-16 19:52:53 +00:00
if [ " $REMOTE_OPERATION " = = "yes" ] ; then
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
2018-09-30 11:57:57 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" -i -n $RSYNC_DEFAULT_ARGS $RSYNC_ATTR_ARGS $RSYNC_PARTIAL_EXCLUDE -e \" $RSYNC_SSH_CMD \" --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE \" $initiatorReplica \" $REMOTE_USER @ $REMOTE_HOST :\" $targetReplica \" >> $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $SCRIPT_PID . $TSTAMP 2>&1 & "
2016-02-16 19:52:53 +00:00
else
2018-09-30 11:57:57 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" -i -n $RSYNC_DEFAULT_ARGS $RSYNC_ATTR_ARGS $RSYNC_PARTIAL_EXCLUDE --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE \" $initiatorReplica \" \" $targetReplica \" >> $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $SCRIPT_PID . $TSTAMP 2>&1 & "
2016-02-16 19:52:53 +00:00
fi
2016-10-16 12:25:29 +00:00
Logger " RSYNC_CMD: $rsyncCmd " "DEBUG"
eval " $rsyncCmd "
2018-02-20 21:15:04 +00:00
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-02-16 19:52:53 +00:00
retval = $?
2016-12-11 13:26:48 +00:00
if [ $retval -ne 0 ] && [ $retval -ne 24 ] ; then
Logger " Getting list of files that need updates failed [ $retval ]. Stopping execution. " "CRITICAL" $retval
2017-02-10 10:15:41 +00:00
_LOGGER_SILENT = true Logger " Command was [ $rsyncCmd ]. " "WARN"
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Rsync output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$SCRIPT_PID .$TSTAMP ) " "NOTICE"
2016-02-16 19:52:53 +00:00
fi
2016-12-11 13:26:48 +00:00
return $retval
2016-02-16 19:52:53 +00:00
else
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " List:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$SCRIPT_PID .$TSTAMP ) " "VERBOSE"
2016-08-29 16:08:30 +00:00
fi
2016-12-12 09:14:59 +00:00
( grep -Ev "^[^ ]*(c|s|t)[^ ]* " " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } . $SCRIPT_PID . $TSTAMP " || :) | ( grep -E "^[^ ]*(p|o|g|a)[^ ]* " || :) | sed -e 's/^[^ ]* //' >> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -cleaned. $SCRIPT_PID . $TSTAMP "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot prepare file list for attribute sync." "CRITICAL" $retval
2016-02-17 12:51:42 +00:00
exit 1
fi
2016-02-16 19:52:53 +00:00
fi
2016-04-02 12:47:28 +00:00
Logger "Getting ctimes for pending files on initiator." "NOTICE"
2017-05-31 16:02:18 +00:00
_getFileCtimeMtimeLocal " ${ INITIATOR [ $__replicaDir ] } " " ${ INITIATOR [ $__type ] } " " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -cleaned. $SCRIPT_PID . $TSTAMP " " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ INITIATOR [ $__type ] } . $SCRIPT_PID . $TSTAMP " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2016-04-02 12:47:28 +00:00
Logger "Getting ctimes for pending files on target." "NOTICE"
2016-02-16 19:52:53 +00:00
if [ " $REMOTE_OPERATION " != "yes" ] ; then
2017-05-31 16:02:18 +00:00
_getFileCtimeMtimeLocal " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -cleaned. $SCRIPT_PID . $TSTAMP " " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ TARGET [ $__type ] } . $SCRIPT_PID . $TSTAMP " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2016-02-16 19:52:53 +00:00
else
2017-05-31 16:02:18 +00:00
_getFileCtimeMtimeRemote " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -cleaned. $SCRIPT_PID . $TSTAMP " " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ TARGET [ $__type ] } . $SCRIPT_PID . $TSTAMP " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2016-02-16 19:52:53 +00:00
fi
2018-10-07 10:59:56 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Getting ctime attributes failed." "CRITICAL" $retval
2016-12-08 20:59:52 +00:00
return 1
fi
2016-02-18 23:13:22 +00:00
2016-10-16 10:12:59 +00:00
# If target gets updated first, then sync_attr must update initiators attrs first
2016-02-19 08:28:57 +00:00
# For join, remove leading replica paths
2016-04-02 22:32:15 +00:00
2017-05-31 16:02:18 +00:00
sed -i'.tmp' " s;^ ${ INITIATOR [ $__replicaDir ] } ;;g " " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ INITIATOR [ $__type ] } . $SCRIPT_PID . $TSTAMP "
sed -i'.tmp' " s;^ ${ TARGET [ $__replicaDir ] } ;;g " " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ TARGET [ $__type ] } . $SCRIPT_PID . $TSTAMP "
2016-04-02 22:32:15 +00:00
2016-08-30 10:19:12 +00:00
if [ " $CONFLICT_PREVALANCE " = = " ${ TARGET [ $__type ] } " ] ; then
2016-10-16 12:25:29 +00:00
sourceDir = " ${ INITIATOR [ $__replicaDir ] } "
escSourceDir = $( EscapeSpaces " ${ INITIATOR [ $__replicaDir ] } " )
destDir = " ${ TARGET [ $__replicaDir ] } "
escDestDir = $( EscapeSpaces " ${ TARGET [ $__replicaDir ] } " )
destReplica = " ${ TARGET [ $__type ] } "
2017-05-31 16:02:18 +00:00
join -j 1 -t ';' -o 1.1,1.2,2.2 " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ INITIATOR [ $__type ] } . $SCRIPT_PID . $TSTAMP " " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ TARGET [ $__type ] } . $SCRIPT_PID . $TSTAMP " | awk -F';' '{if ($2 > $3) print $1}' > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -ctime_files. $SCRIPT_PID . $TSTAMP "
2016-02-19 00:13:17 +00:00
else
2016-10-16 12:25:29 +00:00
sourceDir = " ${ TARGET [ $__replicaDir ] } "
escSourceDir = $( EscapeSpaces " ${ TARGET [ $__replicaDir ] } " )
destDir = " ${ INITIATOR [ $__replicaDir ] } "
escDestDir = $( EscapeSpaces " ${ INITIATOR [ $__replicaDir ] } " )
destReplica = " ${ INITIATOR [ $__type ] } "
2017-05-31 16:02:18 +00:00
join -j 1 -t ';' -o 1.1,1.2,2.2 " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ TARGET [ $__type ] } . $SCRIPT_PID . $TSTAMP " " $RUN_DIR / $PROGRAM .ctime_mtime___. ${ INITIATOR [ $__type ] } . $SCRIPT_PID . $TSTAMP " | awk -F';' '{if ($2 > $3) print $1}' > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -ctime_files. $SCRIPT_PID . $TSTAMP "
2016-02-18 15:21:17 +00:00
fi
2016-12-12 09:14:59 +00:00
if [ $( wc -l < " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -ctime_files. $SCRIPT_PID . $TSTAMP " ) -eq 0 ] ; then
2016-10-16 12:25:29 +00:00
Logger " Updating file attributes on $destReplica not required " "NOTICE"
2016-04-02 22:32:15 +00:00
return 0
fi
2016-10-16 12:25:29 +00:00
Logger " Updating file attributes on $destReplica . " "NOTICE"
2016-02-18 23:13:22 +00:00
if [ " $REMOTE_OPERATION " = = "yes" ] ; then
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
2016-02-19 20:44:52 +00:00
# No rsync args (hence no -r) because files are selected with --from-file
2016-10-16 12:25:29 +00:00
if [ " $destReplica " = = " ${ INITIATOR [ $__type ] } " ] ; then
2017-06-07 10:48:52 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $SYNC_OPTS -e \" $RSYNC_SSH_CMD \" --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__deletedListFile ] } \" --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ INITIATOR [ $__deletedListFile ] } \" --files-from=\" $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -ctime_files. $SCRIPT_PID . $TSTAMP \" $REMOTE_USER @ $REMOTE_HOST :\" $escSourceDir \" \" $destDir \" >> $RUN_DIR / $PROGRAM .attr-update. $destReplica . $SCRIPT_PID . $TSTAMP 2>&1 & "
2016-02-18 23:13:22 +00:00
else
2017-06-07 10:48:52 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $SYNC_OPTS -e \" $RSYNC_SSH_CMD \" --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__deletedListFile ] } \" --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ INITIATOR [ $__deletedListFile ] } \" --files-from=\" $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -ctime_files. $SCRIPT_PID . $TSTAMP \" \" $sourceDir \" $REMOTE_USER @ $REMOTE_HOST :\" $escDestDir \" >> $RUN_DIR / $PROGRAM .attr-update. $destReplica . $SCRIPT_PID . $TSTAMP 2>&1 & "
2016-02-18 23:13:22 +00:00
fi
2016-02-17 22:00:45 +00:00
else
2017-06-07 10:48:52 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $SYNC_OPTS --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__deletedListFile ] } \" --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ INITIATOR [ $__deletedListFile ] } \" --files-from=\" $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } -ctime_files. $SCRIPT_PID . $TSTAMP \" \" $sourceDir \" \" $destDir \" >> $RUN_DIR / $PROGRAM .attr-update. $destReplica . $SCRIPT_PID . $TSTAMP 2>&1 & "
2016-02-18 23:13:22 +00:00
2016-02-17 22:00:45 +00:00
fi
2016-02-18 23:13:22 +00:00
2016-10-16 12:25:29 +00:00
Logger " RSYNC_CMD: $rsyncCmd " "DEBUG"
eval " $rsyncCmd "
2018-02-20 21:15:04 +00:00
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-02-17 22:00:45 +00:00
retval = $?
2016-02-16 19:52:53 +00:00
2016-12-11 19:54:40 +00:00
if [ $retval -ne 0 ] && [ $retval -ne 24 ] ; then
2016-12-11 13:26:48 +00:00
Logger " Updating file attributes on $destReplica [ $retval ]. Stopping execution. " "CRITICAL" $retval
2017-02-10 10:15:41 +00:00
_LOGGER_SILENT = true Logger " Command was [ $rsyncCmd ]. " "WARN"
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM .attr-update. $destReplica . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Rsync output:\n $( cat $RUN_DIR /$PROGRAM .attr-update.$destReplica .$SCRIPT_PID .$TSTAMP ) " "NOTICE"
2016-02-17 22:00:45 +00:00
fi
2016-12-08 20:59:52 +00:00
return 1
2016-02-17 22:00:45 +00:00
else
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM .attr-update. $destReplica . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " List:\n $( cat $RUN_DIR /$PROGRAM .attr-update.$destReplica .$SCRIPT_PID .$TSTAMP ) " "VERBOSE"
2016-08-29 16:08:30 +00:00
fi
2016-10-16 12:25:29 +00:00
Logger " Successfully updated file attributes on $destReplica replica. " "NOTICE"
2016-02-17 22:00:45 +00:00
fi
2016-02-16 19:52:53 +00:00
}
2016-10-16 12:25:29 +00:00
# syncUpdate(source replica, destination replica, delete_list_filename)
function syncUpdate {
local sourceReplica = " ${ 1 } " # Contains replica type of source: initiator, target
local destinationReplica = " ${ 2 } " # Contains replica type of destination: initiator, target
2016-12-07 20:30:10 +00:00
__CheckArguments 2 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-10-16 12:25:29 +00:00
local rsyncCmd
2016-08-04 09:52:28 +00:00
local retval
2016-02-18 15:21:17 +00:00
2016-10-16 12:25:29 +00:00
local sourceDir
local escSourceDir
local destDir
local escDestDir
2016-08-29 19:54:51 +00:00
2016-10-16 12:25:29 +00:00
local backupArgs
2016-08-29 19:54:51 +00:00
2016-10-16 12:25:29 +00:00
Logger " Updating $destinationReplica replica. " "NOTICE"
if [ " $sourceReplica " = = " ${ INITIATOR [ $__type ] } " ] ; then
sourceDir = " ${ INITIATOR [ $__replicaDir ] } "
destDir = " ${ TARGET [ $__replicaDir ] } "
backupArgs = " $TARGET_BACKUP "
escSourceDir = $( EscapeSpaces " ${ INITIATOR [ $__replicaDir ] } " )
escDestDir = $( EscapeSpaces " ${ TARGET [ $__replicaDir ] } " )
2015-11-12 00:37:43 +00:00
else
2016-10-16 12:25:29 +00:00
sourceDir = " ${ TARGET [ $__replicaDir ] } "
destDir = " ${ INITIATOR [ $__replicaDir ] } "
backupArgs = " $INITIATOR_BACKUP "
2016-08-29 19:54:51 +00:00
2016-10-16 12:25:29 +00:00
escSourceDir = $( EscapeSpaces " ${ TARGET [ $__replicaDir ] } " )
escDestDir = $( EscapeSpaces " ${ INITIATOR [ $__replicaDir ] } " )
2015-11-12 00:37:43 +00:00
fi
if [ " $REMOTE_OPERATION " = = "yes" ] ; then
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
2016-10-16 12:25:29 +00:00
if [ " $sourceReplica " = = " ${ INITIATOR [ $__type ] } " ] ; then
2018-09-30 11:57:57 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" $RSYNC_DEFAULT_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $SYNC_OPTS -e \" $RSYNC_SSH_CMD \" $backupArgs --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $sourceReplica ${ INITIATOR [ $__deletedListFile ] } \" --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $destinationReplica ${ INITIATOR [ $__deletedListFile ] } \" \" $sourceDir \" $REMOTE_USER @ $REMOTE_HOST :\" $escDestDir \" >> $RUN_DIR / $PROGRAM .update. $destinationReplica . $SCRIPT_PID . $TSTAMP 2>&1 "
2015-11-12 00:37:43 +00:00
else
2018-09-30 11:57:57 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" $RSYNC_DEFAULT_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $SYNC_OPTS -e \" $RSYNC_SSH_CMD \" $backupArgs --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $destinationReplica ${ INITIATOR [ $__deletedListFile ] } \" --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $sourceReplica ${ INITIATOR [ $__deletedListFile ] } \" $REMOTE_USER @ $REMOTE_HOST :\" $escSourceDir \" \" $destDir \" >> $RUN_DIR / $PROGRAM .update. $destinationReplica . $SCRIPT_PID . $TSTAMP 2>&1 "
2015-11-12 00:37:43 +00:00
fi
else
2018-09-30 11:57:57 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" $RSYNC_DEFAULT_ARGS $RSYNC_DRY_ARG $RSYNC_ATTR_ARGS $RSYNC_TYPE_ARGS $SYNC_OPTS $backupArgs --exclude \" $OSYNC_DIR \" $RSYNC_PATTERNS $RSYNC_PARTIAL_EXCLUDE --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $sourceReplica ${ INITIATOR [ $__deletedListFile ] } \" --exclude-from=\" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $destinationReplica ${ INITIATOR [ $__deletedListFile ] } \" \" $sourceDir \" \" $destDir \" >> $RUN_DIR / $PROGRAM .update. $destinationReplica . $SCRIPT_PID . $TSTAMP 2>&1 "
2015-11-12 00:37:43 +00:00
fi
2016-10-16 12:25:29 +00:00
Logger " RSYNC_CMD: $rsyncCmd " "DEBUG"
eval " $rsyncCmd "
2015-11-12 00:37:43 +00:00
retval = $?
2016-12-11 13:26:48 +00:00
if [ $retval -ne 0 ] && [ $retval -ne 24 ] ; then
Logger " Updating $destinationReplica replica failed. Stopping execution. " "CRITICAL" $retval
2017-02-10 10:15:41 +00:00
_LOGGER_SILENT = true Logger " Command was [ $rsyncCmd ]. " "WARN"
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM .update. $destinationReplica . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Rsync output:\n $( cat $RUN_DIR /$PROGRAM .update.$destinationReplica .$SCRIPT_PID .$TSTAMP ) " "NOTICE"
2015-11-12 00:37:43 +00:00
fi
2016-08-30 09:54:00 +00:00
exit 1
2015-11-12 00:37:43 +00:00
else
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM .update. $destinationReplica . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " List:\n $( cat $RUN_DIR /$PROGRAM .update.$destinationReplica .$SCRIPT_PID .$TSTAMP ) " "VERBOSE"
2016-08-29 16:08:30 +00:00
fi
2016-10-16 12:25:29 +00:00
Logger " Updating $destinationReplica replica succeded. " "NOTICE"
2015-11-12 00:37:43 +00:00
return 0
fi
}
2016-10-16 12:25:29 +00:00
function _deleteLocal {
local replicaType = " ${ 1 } " # Replica type
local replicaDir = " ${ 2 } " # Full path to replica
local deletionDir = " ${ 3 } " # deletion dir in format .[workdir]/deleted
2016-12-07 20:30:10 +00:00
__CheckArguments 3 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-08-04 09:52:28 +00:00
local parentdir
2016-10-16 12:25:29 +00:00
local previousFile = ""
2016-08-02 08:01:48 +00:00
2016-11-15 12:10:47 +00:00
local deletionListFromReplica
if [ " $replicaType " = = " ${ INITIATOR [ $__type ] } " ] ; then
deletionListFromReplica = " ${ TARGET [ $__type ] } "
elif [ " $replicaType " = = " ${ TARGET [ $__type ] } " ] ; then
deletionListFromReplica = " ${ INITIATOR [ $__type ] } "
else
Logger " Bogus replicaType in [ ${ FUNCNAME [0] } ]. " "CRITICAL"
exit 1
fi
2016-10-16 12:25:29 +00:00
if [ ! -d " $replicaDir $deletionDir " ] && [ $_DRYRUN = = false ] ; then
2016-12-19 12:19:21 +00:00
mkdir -p " $replicaDir $deletionDir "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger " Cannot create local replica deletion directory in [ $replicaDir $deletionDir ]. " "ERROR" $retval
2016-08-29 11:16:07 +00:00
exit 1
fi
2016-08-06 11:26:16 +00:00
fi
2016-08-02 08:01:48 +00:00
2016-08-08 17:05:57 +00:00
while read -r files; do
2016-08-13 09:55:08 +00:00
## On every run, check wheter the next item is already deleted because it is included in a directory already deleted
2016-10-16 12:25:29 +00:00
if [ [ " $files " != " $previousFile / " * ] ] && [ " $files " != "" ] ; then
2016-08-02 08:01:48 +00:00
if [ " $SOFT_DELETE " != "no" ] ; then
2016-08-29 11:54:24 +00:00
if [ $_DRYRUN = = false ] ; then
2016-12-01 19:51:45 +00:00
if [ -e " $replicaDir $deletionDir / $files " ] || [ -L " $replicaDir $deletionDir / $files " ] ; then
2016-10-16 12:25:29 +00:00
rm -rf " ${ replicaDir : ? } $deletionDir / $files "
2015-11-12 00:37:43 +00:00
fi
2016-02-19 20:44:52 +00:00
2016-12-01 19:51:45 +00:00
if [ -e " $replicaDir $files " ] || [ -L " $replicaDir $files " ] ; then
2016-02-19 20:44:52 +00:00
# In order to keep full path on soft deletion, create parent directories before move
parentdir = " $( dirname " $files " ) "
if [ " $parentdir " != "." ] ; then
2016-10-16 12:25:29 +00:00
mkdir -p " $replicaDir $deletionDir / $parentdir "
Logger " Moving deleted file [ $replicaDir $files ] to [ $replicaDir $deletionDir / $parentdir ]. " "VERBOSE"
mv -f " $replicaDir $files " " $replicaDir $deletionDir / $parentdir "
2016-02-19 20:44:52 +00:00
else
2016-10-16 12:25:29 +00:00
Logger " Moving deleted file [ $replicaDir $files ] to [ $replicaDir $deletionDir ]. " "VERBOSE"
mv -f " $replicaDir $files " " $replicaDir $deletionDir "
2016-02-19 20:44:52 +00:00
fi
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger " Cannot move [ $replicaDir $files ] to deletion directory. " "ERROR" $retval
2016-10-16 12:25:29 +00:00
echo " $files " >> " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__failedDeletedListFile ] } "
2016-11-14 20:14:10 +00:00
else
2016-12-12 09:14:59 +00:00
echo " $files " >> " $RUN_DIR / $PROGRAM .delete. $replicaType . $SCRIPT_PID . $TSTAMP "
2016-02-19 20:44:52 +00:00
fi
2015-11-12 00:37:43 +00:00
fi
fi
else
2016-08-29 11:54:24 +00:00
if [ $_DRYRUN = = false ] ; then
2016-12-01 19:51:45 +00:00
if [ -e " $replicaDir $files " ] || [ -L " $replicaDir $files " ] ; then
2016-10-16 12:25:29 +00:00
rm -rf " $replicaDir $files "
2016-12-11 13:26:48 +00:00
retval = $?
2016-10-16 12:25:29 +00:00
Logger " Deleting [ $replicaDir $files ]. " "VERBOSE"
2016-12-11 13:26:48 +00:00
if [ $retval -ne 0 ] ; then
Logger " Cannot delete [ $replicaDir $files ]. " "ERROR" $retval
2016-10-16 12:25:29 +00:00
echo " $files " >> " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $replicaType ${ INITIATOR [ $__failedDeletedListFile ] } "
2016-11-14 20:14:10 +00:00
else
2016-12-12 09:14:59 +00:00
echo " $files " >> " $RUN_DIR / $PROGRAM .delete. $replicaType . $SCRIPT_PID . $TSTAMP "
2016-02-19 20:44:52 +00:00
fi
2015-11-12 00:37:43 +00:00
fi
fi
fi
2016-10-16 12:25:29 +00:00
previousFile = " $files "
2015-11-12 00:37:43 +00:00
fi
2016-11-15 12:10:47 +00:00
done < " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $deletionListFromReplica ${ INITIATOR [ $__deletedListFile ] } "
2015-11-12 00:37:43 +00:00
}
2016-10-16 12:25:29 +00:00
function _deleteRemote {
local replicaType = " ${ 1 } " # Replica type
local replicaDir = " ${ 2 } " # Full path to replica
local deletionDir = " ${ 3 } " # deletion dir in format .[workdir]/deleted
2016-12-07 20:30:10 +00:00
__CheckArguments 3 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-10-16 12:25:29 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-10-16 12:25:29 +00:00
local escDestDir
local rsyncCmd
2016-02-18 19:54:07 +00:00
2016-11-14 20:14:10 +00:00
local failedDeleteList
local successDeleteList
2016-11-15 12:10:47 +00:00
local deletionListFromReplica
if [ " $replicaType " = = " ${ INITIATOR [ $__type ] } " ] ; then
deletionListFromReplica = " ${ TARGET [ $__type ] } "
elif [ " $replicaType " = = " ${ TARGET [ $__type ] } " ] ; then
deletionListFromReplica = " ${ INITIATOR [ $__type ] } "
else
Logger " Bogus replicaType in [ ${ FUNCNAME [0] } ]. " "CRITICAL"
exit 1
fi
2016-11-14 20:14:10 +00:00
failedDeleteList = " $( EscapeSpaces ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__stateDir ] } /$replicaType ${ TARGET [ $__failedDeletedListFile ] } ) "
2016-11-15 12:10:47 +00:00
successDeleteList = " $( EscapeSpaces ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__stateDir ] } /$replicaType ${ TARGET [ $__successDeletedListFile ] } ) "
2016-11-14 20:14:10 +00:00
2015-11-12 00:37:43 +00:00
## This is a special coded function. Need to redelcare local functions on remote host, passing all needed variables as escaped arguments to ssh command.
## Anything beetween << ENDSSH and ENDSSH will be executed remotely
# Additionnaly, we need to copy the deletetion list to the remote state folder
2016-10-16 12:25:29 +00:00
escDestDir = " $( EscapeSpaces " ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__stateDir ] } " ) "
2017-06-08 07:25:33 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" -e \" $RSYNC_SSH_CMD \" \" ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / $deletionListFromReplica ${ INITIATOR [ $__deletedListFile ] } \" $REMOTE_USER @ $REMOTE_HOST :\" $escDestDir /\" >> $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .precopy. $SCRIPT_PID . $TSTAMP 2>&1 "
2016-10-16 12:25:29 +00:00
Logger " RSYNC_CMD: $rsyncCmd " "DEBUG"
eval " $rsyncCmd " 2>> " $LOG_FILE "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot copy the deletion list to remote replica." "ERROR" $retval
2017-02-10 10:15:41 +00:00
_LOGGER_SILENT = true Logger " Command was [ $rsyncCmd ]. " "WARN"
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .precopy. $SCRIPT_PID . $TSTAMP " ] ; then
Logger " $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .precopy.$SCRIPT_PID .$TSTAMP ) " "ERROR"
2015-11-12 00:37:43 +00:00
fi
exit 1
fi
2017-02-08 12:52:04 +00:00
$SSH_CMD env _REMOTE_TOKEN = " $_REMOTE_TOKEN " \
env _DEBUG = " ' $_DEBUG ' " env _PARANOIA_DEBUG = " ' $_PARANOIA_DEBUG ' " env _LOGGER_SILENT = " ' $_LOGGER_SILENT ' " env _LOGGER_VERBOSE = " ' $_LOGGER_VERBOSE ' " env _LOGGER_PREFIX = " ' $_LOGGER_PREFIX ' " env _LOGGER_ERR_ONLY = " ' $_LOGGER_ERR_ONLY ' " \
2018-09-30 14:08:12 +00:00
env PROGRAM = " ' $PROGRAM ' " env SCRIPT_PID = " ' $SCRIPT_PID ' " env TSTAMP = " ' $TSTAMP ' " \
2018-09-30 19:21:30 +00:00
env _DRYRUN = " ' $_DRYRUN ' " \
2016-12-08 10:36:55 +00:00
env FILE_LIST = " ' $( EscapeSpaces " ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__stateDir ] } / $deletionListFromReplica ${ INITIATOR [ $__deletedListFile ] } " ) ' " env REPLICA_DIR = " ' $( EscapeSpaces " $replicaDir " ) ' " env SOFT_DELETE = " ' $SOFT_DELETE ' " \
2017-06-07 10:48:52 +00:00
env DELETION_DIR = " ' $( EscapeSpaces " $deletionDir " ) ' " env FAILED_DELETE_LIST = " ' $failedDeleteList ' " env SUCCESS_DELETE_LIST = " ' $successDeleteList ' " \
env LC_ALL = C $COMMAND_SUDO ' bash -s' << 'ENDSSH' >> " $RUN_DIR / $PROGRAM .remote_deletion. $SCRIPT_PID . $TSTAMP " 2>& 1
2016-12-07 20:30:10 +00:00
include #### DEBUG SUBSET ####
include #### TrapError SUBSET ####
include #### RemoteLogger SUBSET ####
2015-11-12 00:37:43 +00:00
## Empty earlier failed delete list
> " $FAILED_DELETE_LIST "
2016-11-15 12:10:47 +00:00
> " $SUCCESS_DELETE_LIST "
2015-11-12 00:37:43 +00:00
2016-03-31 21:18:06 +00:00
parentdir =
2016-10-16 12:25:29 +00:00
previousFile = ""
2016-08-13 09:55:08 +00:00
2016-10-16 12:25:29 +00:00
if [ ! -d " $REPLICA_DIR $DELETION_DIR " ] && [ $_DRYRUN = = false ] ; then
2016-12-19 12:19:21 +00:00
mkdir -p " $REPLICA_DIR $DELETION_DIR "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
RemoteLogger " Cannot create remote replica deletion directory in [ $REPLICA_DIR $DELETION_DIR ]. " "ERROR" $retval
2016-08-29 11:16:07 +00:00
exit 1
fi
2016-08-13 09:55:08 +00:00
fi
2016-08-08 17:05:57 +00:00
while read -r files; do
2016-08-13 09:55:08 +00:00
## On every run, check wheter the next item is already deleted because it is included in a directory already deleted
2016-10-16 12:25:29 +00:00
if [ [ " $files " != " $previousFile / " * ] ] && [ " $files " != "" ] ; then
2015-11-12 00:37:43 +00:00
if [ " $SOFT_DELETE " != "no" ] ; then
2016-08-29 11:54:24 +00:00
if [ $_DRYRUN = = false ] ; then
2016-12-01 19:51:45 +00:00
if [ -e " $REPLICA_DIR $DELETION_DIR / $files " ] || [ -L " $REPLICA_DIR $DELETION_DIR / $files " ] ; then
2016-12-19 12:19:21 +00:00
rm -rf " $REPLICA_DIR $DELETION_DIR / $files "
2015-11-12 00:37:43 +00:00
fi
2016-02-19 20:44:52 +00:00
2016-12-01 19:51:45 +00:00
if [ -e " $REPLICA_DIR $files " ] || [ -L " $REPLICA_DIR $files " ] ; then
2016-02-19 20:44:52 +00:00
# In order to keep full path on soft deletion, create parent directories before move
parentdir = " $( dirname " $files " ) "
if [ " $parentdir " != "." ] ; then
2016-12-07 20:30:10 +00:00
RemoteLogger " Moving deleted file [ $REPLICA_DIR $files ] to [ $REPLICA_DIR $DELETION_DIR / $parentdir ]. " "VERBOSE"
2016-12-19 12:19:21 +00:00
mkdir -p " $REPLICA_DIR $DELETION_DIR / $parentdir "
mv -f " $REPLICA_DIR $files " " $REPLICA_DIR $DELETION_DIR / $parentdir "
2016-02-19 20:44:52 +00:00
else
2016-12-07 20:30:10 +00:00
RemoteLogger " Moving deleted file [ $REPLICA_DIR $files ] to [ $REPLICA_DIR $DELETION_DIR ]. " "VERBOSE"
2016-12-19 12:19:21 +00:00
mv -f " $REPLICA_DIR $files " " $REPLICA_DIR $DELETION_DIR "
2016-02-19 20:44:52 +00:00
fi
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
RemoteLogger " Cannot move [ $REPLICA_DIR $files ] to deletion directory. " "ERROR" $retval
2016-11-14 20:14:10 +00:00
# Using $files instead of $REPLICA_DIR$files here so the list is ready for next run
2016-02-19 20:44:52 +00:00
echo " $files " >> " $FAILED_DELETE_LIST "
2016-11-14 20:14:10 +00:00
else
echo " $files " >> " $SUCCESS_DELETE_LIST "
2016-02-19 20:44:52 +00:00
fi
2015-11-12 00:37:43 +00:00
fi
fi
else
2016-08-29 11:54:24 +00:00
if [ $_DRYRUN = = false ] ; then
2016-12-01 19:51:45 +00:00
if [ -e " $REPLICA_DIR $files " ] || [ -e " $REPLICA_DIR $files " ] ; then
2016-12-07 20:30:10 +00:00
RemoteLogger " Deleting [ $REPLICA_DIR $files ]. " "VERBOSE"
2016-12-19 12:19:21 +00:00
rm -rf " $REPLICA_DIR $files "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
RemoteLogger " Cannot delete [ $REPLICA_DIR $files ]. " "ERROR" $retval
2016-08-02 08:01:48 +00:00
echo " $files " >> " $FAILED_DELETE_LIST "
2016-11-14 20:14:10 +00:00
else
echo " $files " >> " $SUCCESS_DELETE_LIST "
2016-02-19 20:44:52 +00:00
fi
2015-11-12 00:37:43 +00:00
fi
fi
fi
2016-10-16 12:25:29 +00:00
previousFile = " $files "
2015-11-12 00:37:43 +00:00
fi
2016-08-08 16:06:03 +00:00
done < " $FILE_LIST "
2015-11-12 00:37:43 +00:00
ENDSSH
2016-12-12 09:14:59 +00:00
if [ -s " $RUN_DIR / $PROGRAM .remote_deletion. $SCRIPT_PID . $TSTAMP " ] ; then
2016-12-06 21:41:44 +00:00
(
2016-12-13 10:45:51 +00:00
_LOGGER_PREFIX = "RR"
2016-12-12 09:14:59 +00:00
Logger " $( cat $RUN_DIR /$PROGRAM .remote_deletion.$SCRIPT_PID .$TSTAMP ) " "ERROR"
2016-12-06 21:41:44 +00:00
)
2016-08-29 18:40:29 +00:00
fi
2015-11-12 00:37:43 +00:00
## Copy back the deleted failed file list
2017-06-07 10:48:52 +00:00
rsyncCmd = " $( type -p $RSYNC_EXECUTABLE ) -r --rsync-path=\"env LC_ALL=C env _REMOTE_TOKEN= $_REMOTE_TOKEN $RSYNC_PATH \" -e \" $RSYNC_SSH_CMD \" --include \" $( dirname ${ TARGET [ $__stateDir ] } ) \" --include \" ${ TARGET [ $__stateDir ] } \" --include \" ${ TARGET [ $__stateDir ] } / $replicaType ${ TARGET [ $__failedDeletedListFile ] } \" --include \" ${ TARGET [ $__stateDir ] } / $replicaType ${ TARGET [ $__successDeletedListFile ] } \" --exclude='*' $REMOTE_USER @ $REMOTE_HOST :\" $( EscapeSpaces ${ TARGET [ $__replicaDir ] } ) \" \" ${ INITIATOR [ $__replicaDir ] } \" > \" $RUN_DIR / $PROGRAM .remote_failed_deletion_list_copy. $SCRIPT_PID . $TSTAMP \" "
2016-10-16 12:25:29 +00:00
Logger " RSYNC_CMD: $rsyncCmd " "DEBUG"
eval " $rsyncCmd " 2>> " $LOG_FILE "
2016-12-11 13:26:48 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
Logger "Cannot copy back the failed deletion list to initiator replica." "CRITICAL" $retval
2017-02-10 10:15:41 +00:00
_LOGGER_SILENT = true Logger " Command was [ $rsyncCmd ]. " "WARN"
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM .remote_failed_deletion_list_copy. $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Comand output: $( cat $RUN_DIR /$PROGRAM .remote_failed_deletion_list_copy.$SCRIPT_PID .$TSTAMP ) " "NOTICE"
2015-11-12 00:37:43 +00:00
fi
2016-08-30 09:54:00 +00:00
exit 1
2015-11-12 00:37:43 +00:00
fi
2016-08-02 08:01:48 +00:00
return 0
2015-11-12 00:37:43 +00:00
}
2016-10-16 12:25:29 +00:00
# delete_Propagation(replica type)
function deletionPropagation {
2016-11-15 12:10:47 +00:00
local replicaType = " ${ 1 } " # Contains replica type: initiator, target where to delete
2016-12-07 20:30:10 +00:00
__CheckArguments 1 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-11 13:26:48 +00:00
local retval
2016-10-16 12:25:29 +00:00
local replicaDir
local deleteDir
2016-02-18 15:21:17 +00:00
2016-09-16 07:48:58 +00:00
Logger " Propagating deletions to $replicaType replica. " "NOTICE"
2015-11-12 00:37:43 +00:00
2016-09-16 07:48:58 +00:00
if [ " $replicaType " = = " ${ INITIATOR [ $__type ] } " ] ; then
2016-12-06 20:32:27 +00:00
if [ $( ArrayContains " ${ INITIATOR [ $__type ] } " " ${ SKIP_DELETION [@] } " ) -eq 0 ] ; then
2016-10-21 10:38:03 +00:00
replicaDir = " ${ INITIATOR [ $__replicaDir ] } "
deleteDir = " ${ INITIATOR [ $__deleteDir ] } "
2016-11-15 12:10:47 +00:00
_deleteLocal " ${ INITIATOR [ $__type ] } " " $replicaDir " " $deleteDir "
2016-10-21 10:38:03 +00:00
retval = $?
2016-12-11 13:26:48 +00:00
if [ $retval -ne 0 ] ; then
Logger " Deletion on $replicaType replica failed. " "CRITICAL" $retval
2016-10-21 10:38:03 +00:00
exit 1
fi
2015-11-12 00:37:43 +00:00
else
2016-10-21 10:38:03 +00:00
Logger " Skipping deletion on replica $replicaType . " "NOTICE"
2015-11-12 00:37:43 +00:00
fi
2016-10-21 10:38:03 +00:00
elif [ " $replicaType " = = " ${ TARGET [ $__type ] } " ] ; then
2016-12-06 20:32:27 +00:00
if [ $( ArrayContains " ${ TARGET [ $__type ] } " " ${ SKIP_DELETION [@] } " ) -eq 0 ] ; then
2016-10-21 10:38:03 +00:00
replicaDir = " ${ TARGET [ $__replicaDir ] } "
deleteDir = " ${ TARGET [ $__deleteDir ] } "
if [ " $REMOTE_OPERATION " = = "yes" ] ; then
2016-11-15 12:10:47 +00:00
_deleteRemote " ${ TARGET [ $__type ] } " " $replicaDir " " $deleteDir "
2016-10-21 10:38:03 +00:00
else
2016-11-15 12:10:47 +00:00
_deleteLocal " ${ TARGET [ $__type ] } " " $replicaDir " " $deleteDir "
2015-11-12 00:37:43 +00:00
fi
2016-10-21 10:38:03 +00:00
retval = $?
2016-12-11 13:26:48 +00:00
if [ $retval -eq 0 ] ; then
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM ._delete_remote. $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Remote:\n $( cat $RUN_DIR /$PROGRAM ._delete_remote.$SCRIPT_PID .$TSTAMP ) " "VERBOSE"
2016-10-21 10:38:03 +00:00
fi
return $retval
else
Logger " Deletion on $replicaType failed. " "CRITICAL"
2016-12-12 09:14:59 +00:00
if [ -f " $RUN_DIR / $PROGRAM .remote_deletion. $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Remote:\n $( cat $RUN_DIR /$PROGRAM .remote_deletion.$SCRIPT_PID .$TSTAMP ) " "CRITICAL" $retval
2016-10-21 10:38:03 +00:00
fi
exit 1
2015-11-12 00:37:43 +00:00
fi
2016-10-21 10:38:03 +00:00
else
Logger " Skipping deletion on replica $replicaType . " "NOTICE"
2015-11-12 00:37:43 +00:00
fi
fi
}
2018-06-25 21:55:13 +00:00
function Initialize {
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
Logger "Initializing initiator and target file lists." "NOTICE"
treeList " ${ INITIATOR [ $__replicaDir ] } " " ${ INITIATOR [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__treeAfterFile ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2018-06-25 21:55:13 +00:00
treeList " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ INITIATOR [ $__treeAfterFile ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2018-06-25 21:55:13 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
if [ $? -ne 0 ] ; then
IFS = ';' read -r -a pidArray <<< " $( eval echo \" \$ WAIT_FOR_TASK_COMPLETION_${ FUNCNAME [0] } \" ) "
initiatorFail = false
targetFail = false
for pid in " ${ pidArray [@] } " ; do
pid = ${ pid % : * }
if [ " $pid " = = " $initiatorPid " ] ; then
2018-07-01 08:54:17 +00:00
Logger "Failed to create initialization treeList files for initiator." "ERROR"
2018-06-25 21:55:13 +00:00
elif [ " $pid " = = " $targetPid " ] ; then
2018-07-01 08:54:17 +00:00
Logger "Failed to create initialization treeList files for target." "ERROR"
2018-06-25 21:55:13 +00:00
fi
done
exit 1
resumeTarget = " ${ SYNC_ACTION [8] } "
fi
2018-07-01 08:54:17 +00:00
2018-07-02 16:19:47 +00:00
timestampList " ${ INITIATOR [ $__replicaDir ] } " " ${ INITIATOR [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__treeAfterFile ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__timestampAfterFile ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2018-07-01 08:54:17 +00:00
2018-07-02 16:19:47 +00:00
timestampList " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ TARGET [ $__treeAfterFile ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ INITIATOR [ $__timestampAfterFile ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2018-07-01 08:54:17 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
if [ $? -ne 0 ] ; then
IFS = ';' read -r -a pidArray <<< " $( eval echo \" \$ WAIT_FOR_TASK_COMPLETION_${ FUNCNAME [0] } \" ) "
initiatorFail = false
targetFail = false
for pid in " ${ pidArray [@] } " ; do
pid = ${ pid % : * }
if [ " $pid " = = " $initiatorPid " ] ; then
Logger "Failed to create initialization timestamp files for initiator." "ERROR"
elif [ " $pid " = = " $targetPid " ] ; then
Logger "Failed to create initialization timestamp files for target." "ERROR"
fi
done
exit 1
resumeTarget = " ${ SYNC_ACTION [8] } "
fi
2018-06-25 21:55:13 +00:00
}
2017-05-30 12:35:44 +00:00
###### Sync function in 9 steps
2015-11-12 00:37:43 +00:00
######
2016-08-09 20:24:50 +00:00
###### Step 0a & 0b: Create current file list of replicas
###### Step 1a & 1b: Create deleted file list of replicas
2018-07-02 20:21:36 +00:00
###### Step 2a & 2b: Create current ctime & mtime file list of replicas
2017-05-30 10:16:59 +00:00
###### Step 3a & 3b: Merge conflict file list
###### Step 4: Update file attributes
###### Step 5a & 5b: Update replicas
###### Step 6a & 6b: Propagate deletions on replicas
2017-06-03 11:57:10 +00:00
###### Step 7a & 7b: Create after run file list of replicas
2018-10-07 11:23:45 +00:00
###### Step 8a & 8b: Create after run ctime & mtime file list of replicas
2015-11-12 00:37:43 +00:00
function Sync {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-08-09 20:14:17 +00:00
local resumeCount
local resumeInitiator
local resumeTarget
local initiatorPid
local targetPid
2016-08-19 08:53:13 +00:00
local initiatorFail
local targetFail
2016-08-09 20:14:17 +00:00
2015-11-12 00:37:43 +00:00
Logger "Starting synchronization task." "NOTICE"
2016-08-09 20:14:17 +00:00
if [ " $RESUME_SYNC " != "no" ] ; then
2016-08-30 10:19:12 +00:00
if [ -f " ${ INITIATOR [ $__resumeCount ] } " ] ; then
resumeCount = $( cat " ${ INITIATOR [ $__resumeCount ] } " )
2015-11-12 00:37:43 +00:00
else
2016-08-09 20:14:17 +00:00
resumeCount = 0
2015-11-12 00:37:43 +00:00
fi
2016-08-09 20:14:17 +00:00
if [ $resumeCount -lt $RESUME_TRY ] ; then
2016-08-30 10:19:12 +00:00
if [ -f " ${ INITIATOR [ $__initiatorLastActionFile ] } " ] ; then
resumeInitiator = $( cat " ${ INITIATOR [ $__initiatorLastActionFile ] } " )
2015-11-12 00:37:43 +00:00
else
2016-08-09 20:14:17 +00:00
resumeInitiator = "synced"
fi
2016-08-30 10:19:12 +00:00
if [ -f " ${ INITIATOR [ $__targetLastActionFile ] } " ] ; then
resumeTarget = $( cat " ${ INITIATOR [ $__targetLastActionFile ] } " )
2016-08-09 20:14:17 +00:00
else
resumeTarget = "synced"
fi
if [ " $resumeInitiator " != "synced" ] ; then
2016-12-13 10:45:51 +00:00
Logger " Trying to resume aborted execution on $( $STAT_CMD " ${ INITIATOR [ $__initiatorLastActionFile ] } " ) at task [ $resumeInitiator ] for initiator. [ $resumeCount ] previous tries. " "NOTICE"
2016-08-30 10:19:12 +00:00
echo $(( $resumeCount + 1 )) > " ${ INITIATOR [ $__resumeCount ] } "
2016-08-09 20:14:17 +00:00
else
resumeInitiator = "none"
fi
if [ " $resumeTarget " != "synced" ] ; then
2016-12-13 10:45:51 +00:00
Logger " Trying to resume aborted execution on $( $STAT_CMD " ${ INITIATOR [ $__targetLastActionFile ] } " ) as task [ $resumeTarget ] for target. [ $resumeCount ] previous tries. " "NOTICE"
2016-08-30 10:19:12 +00:00
echo $(( $resumeCount + 1 )) > " ${ INITIATOR [ $__resumeCount ] } "
2016-08-09 20:14:17 +00:00
else
resumeTarget = "none"
2015-11-12 00:37:43 +00:00
fi
else
2017-05-30 13:45:43 +00:00
if [ $RESUME_TRY -ne 0 ] ; then
Logger " Will not resume aborted execution. Too many resume tries [ $resumeCount ]. " "WARN"
fi
2016-08-30 10:19:12 +00:00
echo "0" > " ${ INITIATOR [ $__resumeCount ] } "
2016-08-09 20:14:17 +00:00
resumeInitiator = "none"
resumeTarget = "none"
2015-11-12 00:37:43 +00:00
fi
else
2016-08-09 20:14:17 +00:00
resumeInitiator = "none"
resumeTarget = "none"
2015-11-12 00:37:43 +00:00
fi
################################################################################################################################################# Actual sync begins here
2016-08-09 20:14:17 +00:00
## Step 0a & 0b
if [ " $resumeInitiator " = = "none" ] || [ " $resumeTarget " = = "none" ] || [ " $resumeInitiator " = = " ${ SYNC_ACTION [0] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [0] } " ] ; then
if [ " $resumeInitiator " = = "none" ] || [ " $resumeInitiator " = = " ${ SYNC_ACTION [0] } " ] ; then
2017-05-31 16:02:18 +00:00
treeList " ${ INITIATOR [ $__replicaDir ] } " " ${ INITIATOR [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__treeCurrentFile ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2015-11-12 00:37:43 +00:00
fi
2016-08-09 20:14:17 +00:00
if [ " $resumeTarget " = = "none" ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [0] } " ] ; then
2017-05-31 16:02:18 +00:00
treeList " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ INITIATOR [ $__treeCurrentFile ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2015-11-12 00:37:43 +00:00
fi
2016-08-09 20:14:17 +00:00
2018-02-20 21:15:04 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] ; then
2016-12-03 09:40:30 +00:00
IFS = ';' read -r -a pidArray <<< " $( eval echo \" \$ WAIT_FOR_TASK_COMPLETION_${ FUNCNAME [0] } \" ) "
2016-08-19 08:53:13 +00:00
initiatorFail = false
targetFail = false
2016-08-09 20:14:17 +00:00
for pid in " ${ pidArray [@] } " ; do
pid = ${ pid % : * }
2016-10-21 16:23:45 +00:00
if [ " $pid " = = " $initiatorPid " ] ; then
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [0] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2016-08-19 08:53:13 +00:00
initiatorFail = true
2016-10-21 16:23:45 +00:00
elif [ " $pid " = = " $targetPid " ] ; then
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [0] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-19 08:53:13 +00:00
targetFail = true
2016-08-09 20:14:17 +00:00
fi
done
2016-08-19 08:53:13 +00:00
if [ $initiatorFail = = false ] ; then
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [1] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2016-08-19 08:53:13 +00:00
fi
if [ $targetFail = = false ] ; then
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [1] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-19 08:53:13 +00:00
fi
2016-12-11 19:54:40 +00:00
exit 1
2015-11-12 00:37:43 +00:00
else
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [1] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [1] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-09 20:14:17 +00:00
resumeInitiator = " ${ SYNC_ACTION [1] } "
resumeTarget = " ${ SYNC_ACTION [1] } "
2015-11-12 00:37:43 +00:00
fi
fi
2016-08-09 20:14:17 +00:00
## Step 1a & 1b
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [1] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [1] } " ] ; then
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [1] } " ] ; then
2016-10-16 12:25:29 +00:00
deleteList " ${ INITIATOR [ $__type ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2016-08-09 20:14:17 +00:00
fi
if [ " $resumeTarget " = = " ${ SYNC_ACTION [1] } " ] ; then
2016-10-16 12:25:29 +00:00
deleteList " ${ TARGET [ $__type ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2016-08-09 20:14:17 +00:00
fi
2018-02-20 21:15:04 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] ; then
2016-12-03 09:40:30 +00:00
IFS = ';' read -r -a pidArray <<< " $( eval echo \" \$ WAIT_FOR_TASK_COMPLETION_${ FUNCNAME [0] } \" ) "
2016-08-19 08:53:13 +00:00
initiatorFail = false
targetFail = false
2016-08-09 20:14:17 +00:00
for pid in " ${ pidArray [@] } " ; do
pid = ${ pid % : * }
2016-10-21 16:23:45 +00:00
if [ " $pid " = = " $initiatorPid " ] ; then
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [1] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2016-08-19 08:53:13 +00:00
initiatorFail = true
2016-10-21 16:23:45 +00:00
elif [ " $pid " = = " $targetPid " ] ; then
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [1] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-19 08:53:13 +00:00
targetFail = true
2016-08-09 20:14:17 +00:00
fi
done
2016-08-19 08:53:13 +00:00
if [ $initiatorFail = = false ] ; then
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [2] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2016-08-19 08:53:13 +00:00
fi
if [ $targetFail = = false ] ; then
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [2] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-19 08:53:13 +00:00
fi
2016-12-11 19:54:40 +00:00
exit 1
2015-11-12 00:37:43 +00:00
else
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [2] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [2] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-09 20:14:17 +00:00
resumeInitiator = " ${ SYNC_ACTION [2] } "
resumeTarget = " ${ SYNC_ACTION [2] } "
2015-11-12 00:37:43 +00:00
fi
fi
2016-08-09 20:14:17 +00:00
2017-05-30 10:16:59 +00:00
## Step 2a & 2b
2016-08-09 20:14:17 +00:00
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [2] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [2] } " ] ; then
2017-06-07 10:17:39 +00:00
#if [[ "$RSYNC_ATTR_ARGS" == *"-X"* ]] || [[ "$RSYNC_ATTR_ARGS" == *"-A"* ]] || [ "$LOG_CONFLICTS" == "yes" ]; then
#TODO: refactor in v1.3 with syncattrs
if [ " $LOG_CONFLICTS " = = "yes" ] ; then
2017-05-30 10:16:59 +00:00
2017-05-30 13:45:43 +00:00
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [2] } " ] ; then
2017-05-31 16:02:18 +00:00
timestampList " ${ INITIATOR [ $__replicaDir ] } " " ${ INITIATOR [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__treeCurrentFile ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__timestampCurrentFile ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2017-05-30 13:45:43 +00:00
fi
2017-05-30 10:16:59 +00:00
2017-05-30 13:45:43 +00:00
if [ " $resumeTarget " = = " ${ SYNC_ACTION [2] } " ] ; then
2017-05-31 16:02:18 +00:00
timestampList " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ TARGET [ $__treeCurrentFile ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ TARGET [ $__timestampCurrentFile ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2017-05-30 13:45:43 +00:00
fi
2018-02-20 21:15:04 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2017-05-30 13:45:43 +00:00
if [ $? -ne 0 ] ; then
IFS = ';' read -r -a pidArray <<< " $( eval echo \" \$ WAIT_FOR_TASK_COMPLETION_${ FUNCNAME [0] } \" ) "
initiatorFail = false
targetFail = false
for pid in " ${ pidArray [@] } " ; do
pid = ${ pid % : * }
if [ " $pid " = = " $initiatorPid " ] ; then
echo " ${ SYNC_ACTION [2] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
initiatorFail = true
elif [ " $pid " = = " $targetPid " ] ; then
echo " ${ SYNC_ACTION [2] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
targetFail = true
fi
done
if [ $initiatorFail = = false ] ; then
echo " ${ SYNC_ACTION [3] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2017-05-30 10:16:59 +00:00
fi
2017-05-30 13:45:43 +00:00
if [ $targetFail = = false ] ; then
echo " ${ SYNC_ACTION [3] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
fi
2016-08-09 20:14:17 +00:00
2017-05-30 13:45:43 +00:00
exit 1
else
echo " ${ SYNC_ACTION [3] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [3] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2017-05-30 13:45:43 +00:00
resumeInitiator = " ${ SYNC_ACTION [3] } "
resumeTarget = " ${ SYNC_ACTION [3] } "
2016-08-09 11:51:14 +00:00
fi
2016-08-09 20:14:17 +00:00
else
2016-08-30 10:19:12 +00:00
echo " ${ SYNC_ACTION [3] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [3] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-09 20:14:17 +00:00
resumeInitiator = " ${ SYNC_ACTION [3] } "
resumeTarget = " ${ SYNC_ACTION [3] } "
2016-02-16 21:15:44 +00:00
fi
fi
2016-08-09 11:51:14 +00:00
2016-08-09 20:14:17 +00:00
## Step 3a & 3b
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [3] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [3] } " ] ; then
2017-06-05 16:53:15 +00:00
if [ " $LOG_CONFLICTS " = = "yes" ] ; then
2018-10-07 10:23:59 +00:00
conflictList " ${ INITIATOR [ $__timestampCurrentFile ] } " " ${ INITIATOR [ $__timestampAfterFileNoSuffix ] } " &
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2017-05-30 13:45:43 +00:00
if [ $? -ne 0 ] ; then
2017-06-01 15:45:02 +00:00
echo " ${ SYNC_ACTION [3] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [3] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2017-05-30 13:45:43 +00:00
exit 1
else
echo " ${ SYNC_ACTION [4] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [4] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2017-05-30 13:45:43 +00:00
resumeInitiator = " ${ SYNC_ACTION [4] } "
resumeTarget = " ${ SYNC_ACTION [4] } "
2017-06-01 15:45:02 +00:00
2017-05-30 10:16:59 +00:00
fi
else
echo " ${ SYNC_ACTION [4] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [4] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [4] } "
resumeTarget = " ${ SYNC_ACTION [4] } "
fi
fi
## Step 4
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [4] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [4] } " ] ; then
2017-05-31 16:02:18 +00:00
if [ [ " $RSYNC_ATTR_ARGS " = = *"-X" * ] ] || [ [ " $RSYNC_ATTR_ARGS " = = *"-A" * ] ] ; then
syncAttrs " ${ INITIATOR [ $__replicaDir ] } " " $TARGET_SYNC_DIR " &
2018-02-20 21:15:04 +00:00
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2017-05-31 16:02:18 +00:00
if [ $? -ne 0 ] ; then
echo " ${ SYNC_ACTION [4] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [4] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
exit 1
else
echo " ${ SYNC_ACTION [5] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [5] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [5] } "
resumeTarget = " ${ SYNC_ACTION [5] } "
fi
else
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [5] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [5] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [5] } "
resumeTarget = " ${ SYNC_ACTION [5] } "
2017-05-31 16:02:18 +00:00
fi
2017-05-30 10:16:59 +00:00
fi
## Step 5a & 5b
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [5] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [5] } " ] ; then
2016-08-30 10:19:12 +00:00
if [ " $CONFLICT_PREVALANCE " = = " ${ TARGET [ $__type ] } " ] ; then
2017-05-30 10:16:59 +00:00
if [ " $resumeTarget " = = " ${ SYNC_ACTION [5] } " ] ; then
2016-11-29 19:28:00 +00:00
syncUpdate " ${ TARGET [ $__type ] } " " ${ INITIATOR [ $__type ] } " &
2018-02-20 21:15:04 +00:00
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [5] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeTarget = " ${ SYNC_ACTION [5] } "
2016-11-29 19:28:00 +00:00
exit 1
else
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [6] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeTarget = " ${ SYNC_ACTION [6] } "
2015-11-12 00:37:43 +00:00
fi
2016-08-19 08:53:13 +00:00
fi
2017-05-30 10:16:59 +00:00
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [5] } " ] ; then
2016-12-13 11:28:06 +00:00
syncUpdate " ${ INITIATOR [ $__type ] } " " ${ TARGET [ $__type ] } " &
2018-02-20 21:15:04 +00:00
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [5] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [5] } "
2016-11-29 19:28:00 +00:00
exit 1
else
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [6] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [6] } "
2016-08-29 19:54:51 +00:00
fi
2016-08-19 08:53:13 +00:00
fi
2015-11-12 00:37:43 +00:00
else
2017-05-30 10:16:59 +00:00
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [5] } " ] ; then
2016-12-13 11:28:06 +00:00
syncUpdate " ${ INITIATOR [ $__type ] } " " ${ TARGET [ $__type ] } " &
2018-02-20 21:15:04 +00:00
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [5] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [5] } "
2016-11-29 19:28:00 +00:00
exit 1
else
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [6] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [6] } "
2016-08-29 19:54:51 +00:00
fi
fi
2017-05-30 10:16:59 +00:00
if [ " $resumeTarget " = = " ${ SYNC_ACTION [5] } " ] ; then
2016-12-13 11:28:06 +00:00
syncUpdate " ${ TARGET [ $__type ] } " " ${ INITIATOR [ $__type ] } " &
2018-02-20 21:15:04 +00:00
ExecTasks $! " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [5] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeTarget = " ${ SYNC_ACTION [5] } "
2016-11-29 19:28:00 +00:00
exit 1
else
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [6] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeTarget = " ${ SYNC_ACTION [6] } "
2016-08-29 19:54:51 +00:00
fi
fi
2015-11-12 00:37:43 +00:00
fi
fi
2016-08-09 20:14:17 +00:00
2017-05-30 10:16:59 +00:00
## Step 6a & 6b
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [6] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [6] } " ] ; then
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [6] } " ] ; then
2016-11-15 12:10:47 +00:00
deletionPropagation " ${ INITIATOR [ $__type ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2015-11-12 00:37:43 +00:00
fi
2016-08-09 20:14:17 +00:00
2017-05-30 10:16:59 +00:00
if [ " $resumeTarget " = = " ${ SYNC_ACTION [6] } " ] ; then
2016-11-15 12:10:47 +00:00
deletionPropagation " ${ TARGET [ $__type ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2015-11-12 00:37:43 +00:00
fi
2016-08-09 20:14:17 +00:00
2018-02-20 21:15:04 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] ; then
2016-12-03 09:40:30 +00:00
IFS = ';' read -r -a pidArray <<< " $( eval echo \" \$ WAIT_FOR_TASK_COMPLETION_${ FUNCNAME [0] } \" ) "
2016-08-19 08:53:13 +00:00
initiatorFail = false
targetFail = false
2016-08-09 20:14:17 +00:00
for pid in " ${ pidArray [@] } " ; do
pid = ${ pid % : * }
2016-10-21 16:23:45 +00:00
if [ " $pid " = = " $initiatorPid " ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [6] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2016-08-19 08:53:13 +00:00
initiatorFail = true
2016-10-21 16:23:45 +00:00
elif [ " $pid " = = " $targetPid " ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [6] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-19 08:53:13 +00:00
targetFail = true
2016-08-09 20:14:17 +00:00
fi
done
2016-08-19 08:53:13 +00:00
if [ $initiatorFail = = false ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [7] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2016-08-19 08:53:13 +00:00
fi
if [ $targetFail = = false ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [7] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-19 08:53:13 +00:00
fi
2016-12-11 19:54:40 +00:00
exit 1
2015-11-12 00:37:43 +00:00
else
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [7] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [7] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [7] } "
resumeTarget = " ${ SYNC_ACTION [7] } "
2016-08-09 20:14:17 +00:00
2015-11-12 00:37:43 +00:00
fi
fi
2016-08-09 20:14:17 +00:00
2017-05-30 10:16:59 +00:00
## Step 7a & 7b
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [7] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [7] } " ] ; then
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [7] } " ] ; then
2017-05-31 16:02:18 +00:00
treeList " ${ INITIATOR [ $__replicaDir ] } " " ${ INITIATOR [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__treeAfterFile ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2016-08-09 20:14:17 +00:00
fi
2017-05-30 10:16:59 +00:00
if [ " $resumeTarget " = = " ${ SYNC_ACTION [7] } " ] ; then
2017-05-31 16:02:18 +00:00
treeList " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ INITIATOR [ $__treeAfterFile ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2016-08-09 20:14:17 +00:00
fi
2018-02-20 21:15:04 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] ; then
2016-12-03 09:40:30 +00:00
IFS = ';' read -r -a pidArray <<< " $( eval echo \" \$ WAIT_FOR_TASK_COMPLETION_${ FUNCNAME [0] } \" ) "
2016-08-19 08:53:13 +00:00
initiatorFail = false
targetFail = false
2016-08-09 20:14:17 +00:00
for pid in " ${ pidArray [@] } " ; do
pid = ${ pid % : * }
2016-10-21 16:23:45 +00:00
if [ " $pid " = = " $initiatorPid " ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [7] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2016-08-19 08:53:13 +00:00
initiatorFail = true
2016-10-21 16:23:45 +00:00
elif [ " $pid " = = " $targetPid " ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [7] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-19 08:53:13 +00:00
targetFail = true
2016-08-09 20:14:17 +00:00
fi
done
2016-08-19 08:53:13 +00:00
if [ $initiatorFail = = false ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [8] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
2016-08-19 08:53:13 +00:00
fi
if [ $targetFail = = false ] ; then
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [8] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2016-08-19 08:53:13 +00:00
fi
2016-12-11 19:54:40 +00:00
exit 1
2015-11-12 00:37:43 +00:00
else
2017-05-30 10:16:59 +00:00
echo " ${ SYNC_ACTION [8] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [8] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [8] } "
resumeTarget = " ${ SYNC_ACTION [8] } "
2015-11-12 00:37:43 +00:00
fi
fi
2017-06-03 11:57:10 +00:00
# Step 8a & 8b
2017-05-30 12:35:44 +00:00
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [8] } " ] || [ " $resumeTarget " = = " ${ SYNC_ACTION [8] } " ] ; then
2017-06-07 10:17:39 +00:00
#if [[ "$RSYNC_ATTR_ARGS" == *"-X"* ]] || [[ "$RSYNC_ATTR_ARGS" == *"-A"* ]] || [ "$LOG_CONFLICTS" == "yes" ]; then
#TODO: refactor in v1.3 with syncattrs
if [ " $LOG_CONFLICTS " = = "yes" ] ; then
2017-06-03 11:51:49 +00:00
if [ " $resumeInitiator " = = " ${ SYNC_ACTION [8] } " ] ; then
timestampList " ${ INITIATOR [ $__replicaDir ] } " " ${ INITIATOR [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__treeAfterFile ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__type ] } ${ INITIATOR [ $__timestampAfterFile ] } " &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2017-06-03 11:51:49 +00:00
fi
if [ " $resumeTarget " = = " ${ SYNC_ACTION [8] } " ] ; then
timestampList " ${ TARGET [ $__replicaDir ] } " " ${ TARGET [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ TARGET [ $__treeAfterFile ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ TARGET [ $__type ] } ${ TARGET [ $__timestampAfterFile ] } " &
2018-10-07 10:59:56 +00:00
targetPid = $!
2017-06-03 11:51:49 +00:00
fi
2018-02-20 21:15:04 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2017-05-30 12:35:44 +00:00
if [ $? -ne 0 ] ; then
2017-06-03 11:51:49 +00:00
IFS = ';' read -r -a pidArray <<< " $( eval echo \" \$ WAIT_FOR_TASK_COMPLETION_${ FUNCNAME [0] } \" ) "
initiatorFail = false
targetFail = false
for pid in " ${ pidArray [@] } " ; do
pid = ${ pid % : * }
if [ " $pid " = = " $initiatorPid " ] ; then
echo " ${ SYNC_ACTION [8] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
initiatorFail = true
elif [ " $pid " = = " $targetPid " ] ; then
echo " ${ SYNC_ACTION [8] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
targetFail = true
fi
done
if [ $initiatorFail = = false ] ; then
echo " ${ SYNC_ACTION [9] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
fi
if [ $targetFail = = false ] ; then
echo " ${ SYNC_ACTION [9] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
fi
2017-05-30 12:35:44 +00:00
exit 1
else
echo " ${ SYNC_ACTION [9] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [9] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
2017-06-03 11:51:49 +00:00
resumeInitiator = " ${ SYNC_ACTION [9] } "
resumeTarget = " ${ SYNC_ACTION [9] } "
2017-05-30 12:35:44 +00:00
fi
else
echo " ${ SYNC_ACTION [9] } " > " ${ INITIATOR [ $__initiatorLastActionFile ] } "
echo " ${ SYNC_ACTION [9] } " > " ${ INITIATOR [ $__targetLastActionFile ] } "
resumeInitiator = " ${ SYNC_ACTION [9] } "
2017-06-03 11:51:49 +00:00
resumeTarget = " ${ SYNC_ACTION [3] } "
2015-11-12 00:37:43 +00:00
fi
fi
Logger "Finished synchronization task." "NOTICE"
2016-08-30 10:19:12 +00:00
echo "0" > " ${ INITIATOR [ $__resumeCount ] } "
2015-11-12 00:37:43 +00:00
}
function _SoftDeleteLocal {
2016-09-16 07:48:58 +00:00
local replicaType = " ${ 1 } " # replica type (initiator, target)
2016-10-16 12:25:29 +00:00
local replicaDeletionPath = " ${ 2 } " # Contains the full path to softdelete / backup directory without ending slash
2016-10-22 18:47:10 +00:00
local changeTime = " ${ 3 } " # Delete files older than changeTime days
local deletionType = " ${ 4 } " # Trivial deletion type string
2016-09-16 07:48:58 +00:00
2016-12-07 20:30:10 +00:00
__CheckArguments 4 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-08-04 09:52:28 +00:00
local retval
2016-02-18 15:21:17 +00:00
2016-11-19 11:54:24 +00:00
if [ " $LOCAL_OS " = = "Busybox" ] || [ " $LOCAL_OS " = = "Android" ] ; then
2016-10-22 18:47:10 +00:00
Logger " Skipping $deletionType deletion on $replicaType . Busybox find -ctime not supported. " "NOTICE"
return 0
fi
2016-10-16 12:25:29 +00:00
if [ -d " $replicaDeletionPath " ] ; then
2016-08-29 11:54:24 +00:00
if [ $_DRYRUN = = true ] ; then
2016-10-22 18:47:10 +00:00
Logger " Listing files older than $changeTime days on $replicaType replica for $deletionType deletion. Does not remove anything. " "NOTICE"
2015-11-12 00:37:43 +00:00
else
2016-10-22 18:47:10 +00:00
Logger " Removing files older than $changeTime days on $replicaType replica for $deletionType deletion. " "NOTICE"
2015-11-12 00:37:43 +00:00
fi
2016-08-08 16:06:03 +00:00
2018-03-22 16:23:14 +00:00
$FIND_CMD " $replicaDeletionPath " -type f -ctime +" $changeTime " > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteList. $replicaType . $SCRIPT_PID . $TSTAMP " 2>> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP "
while IFS = '' read -r file; do
Logger " On $replicaType will delete file [ $file ] " "VERBOSE"
if [ $_DRYRUN = = false ] ; then
rm -f " $file " >> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP " 2>& 1
fi
done < " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteList. $replicaType . $SCRIPT_PID . $TSTAMP "
$FIND_CMD " $replicaDeletionPath " -type d -empty -ctime +" $changeTime " > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteList. $replicaType . $SCRIPT_PID . $TSTAMP " 2>> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP "
2018-10-02 17:01:44 +00:00
while IFS = '' read -r directory; do
2018-03-22 16:23:14 +00:00
Logger " On $replicaType will delete empty directory [ $file ] " "VERBOSE"
if [ $_DRYRUN = = false ] ; then
2018-10-02 17:01:44 +00:00
rm -df " $directory " >> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP " 2>& 1
2018-03-22 16:23:14 +00:00
fi
done < " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteList. $replicaType . $SCRIPT_PID . $TSTAMP "
if [ -s " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
Logger " Error while executing cleanup on $replicaType replica. " "ERROR" $retval
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .deleteErrors.$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2015-11-12 00:37:43 +00:00
else
2018-03-22 16:23:14 +00:00
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .deleteErrors.$replicaType .$SCRIPT_PID .$TSTAMP ) " "VERBOSE"
2016-12-11 13:36:26 +00:00
Logger " File cleanup complete on $replicaType replica. " "NOTICE"
2015-11-12 00:37:43 +00:00
fi
2016-12-12 22:33:57 +00:00
2016-10-16 12:25:29 +00:00
elif [ -d " $replicaDeletionPath " ] && ! [ -w " $replicaDeletionPath " ] ; then
Logger " The $replicaType replica dir [ $replicaDeletionPath ] is not writable. Cannot clean old files. " "ERROR"
2016-08-29 19:05:46 +00:00
else
2016-10-16 12:25:29 +00:00
Logger " The $replicaType replica dir [ $replicaDeletionPath ] does not exist. Skipping cleaning of old files. " "VERBOSE"
2015-11-12 00:37:43 +00:00
fi
}
function _SoftDeleteRemote {
2016-09-16 07:48:58 +00:00
local replicaType = " ${ 1 } "
2016-10-16 12:25:29 +00:00
local replicaDeletionPath = " ${ 2 } " # Contains the full path to softdelete / backup directory without ending slash
2016-10-22 18:47:10 +00:00
local changeTime = " ${ 3 } " # Delete files older than changeTime days
local deletionType = " ${ 4 } " # Trivial deletion type string
2016-12-07 20:30:10 +00:00
__CheckArguments 4 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-08-04 09:52:28 +00:00
local retval
2016-02-18 15:21:17 +00:00
2016-11-19 11:54:24 +00:00
if [ " $REMOTE_OS " = = "BusyBox" ] || [ " $REMOTE_OS " = = "Android" ] ; then
2016-10-22 18:47:10 +00:00
Logger " Skipping $deletionType deletion on $replicaType . Busybox find -ctime not supported. " "NOTICE"
return 0
fi
2015-11-12 00:37:43 +00:00
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
2016-08-29 11:54:24 +00:00
if [ $_DRYRUN = = true ] ; then
2016-10-22 18:47:10 +00:00
Logger " Listing files older than $changeTime days on $replicaType replica for $deletionType deletion. Does not remove anything. " "NOTICE"
2015-11-12 00:37:43 +00:00
else
2016-10-22 18:47:10 +00:00
Logger " Removing files older than $changeTime days on $replicaType replica for $deletionType deletion. " "NOTICE"
2015-11-12 00:37:43 +00:00
fi
2017-02-08 12:52:04 +00:00
$SSH_CMD env _REMOTE_TOKEN = " $_REMOTE_TOKEN " \
env _DEBUG = " ' $_DEBUG ' " env _PARANOIA_DEBUG = " ' $_PARANOIA_DEBUG ' " env _LOGGER_SILENT = " ' $_LOGGER_SILENT ' " env _LOGGER_VERBOSE = " ' $_LOGGER_VERBOSE ' " env _LOGGER_PREFIX = " ' $_LOGGER_PREFIX ' " env _LOGGER_ERR_ONLY = " ' $_LOGGER_ERR_ONLY ' " \
2018-09-30 14:08:12 +00:00
env PROGRAM = " ' $PROGRAM ' " env SCRIPT_PID = " ' $SCRIPT_PID ' " env TSTAMP = " ' $TSTAMP ' " \
2017-06-07 10:48:52 +00:00
env _DRYRUN = " ' $_DRYRUN ' " env replicaType = " ' $replicaType ' " env replicaDeletionPath = " ' $replicaDeletionPath ' " env changeTime = " ' $changeTime ' " env REMOTE_FIND_CMD = " ' $REMOTE_FIND_CMD ' " \
env LC_ALL = C $COMMAND_SUDO ' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME [ 0] } .$replicaType .$SCRIPT_PID .$TSTAMP " 2>&1
2018-03-22 16:23:14 +00:00
include #### DEBUG SUBSET ####
include #### TrapError SUBSET ####
include #### IsInteger SUBSET ####
include #### HumanToNumeric SUBSET ####
include #### RemoteLogger SUBSET ####
2016-02-08 12:00:57 +00:00
2016-12-06 12:30:05 +00:00
if [ -d " $replicaDeletionPath " ] ; then
2018-03-22 16:23:14 +00:00
$REMOTE_FIND_CMD " $replicaDeletionPath " -type f -ctime +" $changeTime " > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteList. $replicaType . $SCRIPT_PID . $TSTAMP " 2>> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP "
while IFS = '' read -r file; do
RemoteLogger " On $replicaType will delete file [ $file ] " "VERBOSE"
if [ $_DRYRUN = = false ] ; then
rm -f " $file " >> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP " 2>& 1
fi
done < " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteList. $replicaType . $SCRIPT_PID . $TSTAMP "
$REMOTE_FIND_CMD " $replicaDeletionPath " -type d -empty -ctime +" $changeTime " > " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteList. $replicaType . $SCRIPT_PID . $TSTAMP " 2>> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP "
2018-10-02 17:01:44 +00:00
while IFS = '' read -r directory; do
2018-03-22 16:23:14 +00:00
RemoteLogger " On $replicaType will delete empty directory [ $file ] " "VERBOSE"
if [ $_DRYRUN = = false ] ; then
2018-10-02 17:01:44 +00:00
rm -df " $directory " >> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP " 2>& 1
2018-03-22 16:23:14 +00:00
fi
done < " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteList. $replicaType . $SCRIPT_PID . $TSTAMP "
if [ -s " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .deleteErrors. $replicaType . $SCRIPT_PID . $TSTAMP " ] ; then
RemoteLogger " Error while executing cleanup on $replicaType replica. " "ERROR" $retval
RemoteLogger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .deleteErrors.$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
exit 1
else
RemoteLogger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .deleteErrors.$replicaType .$SCRIPT_PID .$TSTAMP ) " "VERBOSE"
RemoteLogger " File cleanup complete on $replicaType replica. " "NOTICE"
exit 0
fi
elif [ -d " $replicaDeletionPath " ] && ! [ -w " $replicaDeletionPath " ] ; then
RemoteLogger " The $replicaType replica dir [ $replicaDeletionPath ] is not writable. Cannot clean old files. " "ERROR"
exit 1
2016-12-06 12:30:05 +00:00
else
2018-03-22 16:23:14 +00:00
RemoteLogger " The $replicaType replica dir [ $replicaDeletionPath ] does not exist. Skipping cleaning of old files. " "VERBOSE"
exit 0
2016-12-06 12:30:05 +00:00
fi
ENDSSH
2015-11-12 00:37:43 +00:00
retval = $?
if [ $retval -ne 0 ] ; then
2016-12-11 13:26:48 +00:00
Logger " Error while executing cleanup on remote $replicaType replica. " "ERROR" $retval
2018-03-22 16:23:14 +00:00
(
_LOGGER_PREFIX = ""
2016-12-14 07:12:35 +00:00
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "WARN"
2018-03-22 16:23:14 +00:00
)
2015-11-12 00:37:43 +00:00
else
2016-09-16 07:48:58 +00:00
Logger " Cleanup complete on $replicaType replica. " "NOTICE"
2018-03-22 16:23:14 +00:00
(
_LOGGER_PREFIX = ""
2016-12-12 22:33:57 +00:00
Logger " Command output:\n $( cat $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .$replicaType .$SCRIPT_PID .$TSTAMP ) " "VERBOSE"
2018-03-22 16:23:14 +00:00
)
2015-11-12 00:37:43 +00:00
fi
}
function SoftDelete {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2018-10-07 10:59:56 +00:00
local initiatorPid
local targetPid
2016-08-03 22:52:05 +00:00
2015-11-12 00:37:43 +00:00
if [ " $CONFLICT_BACKUP " != "no" ] && [ $CONFLICT_BACKUP_DAYS -ne 0 ] ; then
Logger "Running conflict backup cleanup." "NOTICE"
2016-10-22 18:47:10 +00:00
_SoftDeleteLocal " ${ INITIATOR [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__backupDir ] } " $CONFLICT_BACKUP_DAYS "conflict backup" &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2015-11-12 00:37:43 +00:00
if [ " $REMOTE_OPERATION " != "yes" ] ; then
2016-10-22 18:47:10 +00:00
_SoftDeleteLocal " ${ TARGET [ $__type ] } " " ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__backupDir ] } " $CONFLICT_BACKUP_DAYS "conflict backup" &
2018-10-07 10:59:56 +00:00
targetPid = $!
2015-11-12 00:37:43 +00:00
else
2016-10-22 18:47:10 +00:00
_SoftDeleteRemote " ${ TARGET [ $__type ] } " " ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__backupDir ] } " $CONFLICT_BACKUP_DAYS "conflict backup" &
2018-10-07 10:59:56 +00:00
targetPid = $!
2015-11-12 00:37:43 +00:00
fi
2018-10-07 10:59:56 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] && [ " $( eval echo \" \$ HARD_MAX_EXEC_TIME_REACHED_${ FUNCNAME [0] } \" ) " = = true ] ; then
2016-11-29 19:28:00 +00:00
exit 1
fi
2015-11-12 00:37:43 +00:00
fi
if [ " $SOFT_DELETE " != "no" ] && [ $SOFT_DELETE_DAYS -ne 0 ] ; then
Logger "Running soft deletion cleanup." "NOTICE"
2016-10-22 18:47:10 +00:00
_SoftDeleteLocal " ${ INITIATOR [ $__type ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__deleteDir ] } " $SOFT_DELETE_DAYS "softdelete" &
2018-10-07 10:59:56 +00:00
initiatorPid = $!
2015-11-12 00:37:43 +00:00
if [ " $REMOTE_OPERATION " != "yes" ] ; then
2016-10-22 18:47:10 +00:00
_SoftDeleteLocal " ${ TARGET [ $__type ] } " " ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__deleteDir ] } " $SOFT_DELETE_DAYS "softdelete" &
2018-10-07 10:59:56 +00:00
targetPid = $!
2015-11-12 00:37:43 +00:00
else
2016-10-22 18:47:10 +00:00
_SoftDeleteRemote " ${ TARGET [ $__type ] } " " ${ TARGET [ $__replicaDir ] } ${ TARGET [ $__deleteDir ] } " $SOFT_DELETE_DAYS "softdelete" &
2018-10-07 10:59:56 +00:00
targetPid = $!
2015-11-12 00:37:43 +00:00
fi
2018-10-07 10:59:56 +00:00
ExecTasks " $initiatorPid ; $targetPid " " ${ FUNCNAME [0] } " false 0 0 $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME false $SLEEP_TIME $KEEP_LOGGING
2016-12-11 13:26:48 +00:00
if [ $? -ne 0 ] && [ " $( eval echo \" \$ HARD_MAX_EXEC_TIME_REACHED_${ FUNCNAME [0] } \" ) " = = true ] ; then
2016-11-29 19:28:00 +00:00
exit 1
fi
2015-11-12 00:37:43 +00:00
fi
}
2018-09-30 19:21:30 +00:00
function _TriggerInitiatorRunLocal {
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
local PUSH_FILE
2018-10-01 08:27:01 +00:00
PUSH_FILE = " ${ INITIATOR [ $__updateTriggerFile ] } "
2018-09-30 19:21:30 +00:00
2018-10-01 08:27:01 +00:00
echo " $INSTANCE_ID # $( date '+%Y%m%dT%H%M%S.%N' ) " >> " $PUSH_FILE " 2> " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .error. $SCRIPT_PID . $TSTAMP "
if [ $? -ne 0 ] ; then
Logger "Could not notify local initiator of file changes." "ERROR"
2018-09-30 19:21:30 +00:00
Logger " $( cat " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .error. $SCRIPT_PID . $TSTAMP " ) " "ERROR"
return 1
2018-10-01 08:27:01 +00:00
else
Logger " Initiator of instance [ $INSTANCE_ID ] should be notified of file changes now. " "NOTICE"
2018-09-30 19:21:30 +00:00
fi
return 0
}
function _TriggerInitiatorRunRemote {
2018-09-30 14:08:12 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2018-10-01 08:49:35 +00:00
$SSH_CMD env _REMOTE_TOKEN = " $_REMOTE_TOKEN " \
2018-09-30 14:08:12 +00:00
env _DEBUG = " ' $_DEBUG ' " env _PARANOIA_DEBUG = " ' $_PARANOIA_DEBUG ' " env _LOGGER_SILENT = " ' $_LOGGER_SILENT ' " env _LOGGER_VERBOSE = " ' $_LOGGER_VERBOSE ' " env _LOGGER_PREFIX = " ' $_LOGGER_PREFIX ' " env _LOGGER_ERR_ONLY = " ' $_LOGGER_ERR_ONLY ' " \
env PROGRAM = " ' $PROGRAM ' " env SCRIPT_PID = " ' $SCRIPT_PID ' " env TSTAMP = " ' $TSTAMP ' " \
2018-10-01 08:49:35 +00:00
env INSTANCE_ID = " ' $INSTANCE_ID ' " env PUSH_FILE = " ' $( EscapeSpaces " ${ INITIATOR [ $__updateTriggerFile ] } " ) ' " \
2018-09-30 14:08:12 +00:00
env LC_ALL = C $COMMAND_SUDO ' bash -s' << 'ENDSSH' > "$RUN_DIR/$PROGRAM.${FUNCNAME [ 0] } .$SCRIPT_PID .$TSTAMP " 2> " $RUN_DIR /$PROGRAM .${ FUNCNAME [0] } .error.$SCRIPT_PID .$TSTAMP "
2018-10-01 08:27:01 +00:00
echo " $INSTANCE_ID # $( date '+%Y%m%dT%H%M%S.%N' ) " >> " $PUSH_FILE "
2018-09-30 14:08:12 +00:00
ENDSSH
2018-10-01 08:27:01 +00:00
if [ $? -ne 0 ] ; then
Logger "Could not notifiy remote initiator of file changes." "ERROR"
2018-10-01 18:28:46 +00:00
Logger " SSH_CMD [ $SSH_CMD ] " "DEBUG"
2018-09-30 14:08:12 +00:00
(
_LOGGER_PREFIX = "RR"
Logger " $( cat " $RUN_DIR / $PROGRAM . ${ FUNCNAME [0] } .error. $SCRIPT_PID . $TSTAMP " ) " "ERROR"
)
return 1
2018-10-01 08:27:01 +00:00
else
Logger " Initiator of instance [ $INSTANCE_ID ] should be notified of file changes now. " "NOTICE"
2018-09-30 14:08:12 +00:00
fi
return 0
}
2018-09-30 19:21:30 +00:00
function TriggerInitiatorRun {
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
if [ " $REMOTE_OPERATION " != "no" ] ; then
_TriggerInitiatorRunRemote
else
_TriggerInitiatorRunLocal
fi
}
2018-06-25 21:59:06 +00:00
function _SummaryFromRsyncFile {
2016-11-15 12:10:47 +00:00
local replicaPath = " ${ 1 } "
local summaryFile = " ${ 2 } "
local direction = " ${ 3 } "
2016-11-14 18:17:30 +00:00
2016-12-07 20:30:10 +00:00
__CheckArguments 3 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-11-14 18:17:30 +00:00
if [ -f " $summaryFile " ] ; then
while read -r file; do
2016-12-12 20:46:44 +00:00
# grep -E "^<|^>|^\." = Remove all lines that do not begin with <, > or . to deal with a bizarre bug involving rsync 3.0.6 / CentOS 6 and --skip-compress showing 'adding zip' line for every skipped compressed extension
if echo " $file " | grep -E "^<|^>|^\." > /dev/null 2>& 1; then
# awk removes first part of line until space, then show all others
2016-12-12 21:41:01 +00:00
Logger " $direction $replicaPath $( echo $file | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}' ) " "ALWAYS"
2016-12-12 20:46:44 +00:00
fi
2016-11-14 18:17:30 +00:00
done < " $summaryFile "
fi
}
2018-06-25 21:59:06 +00:00
function _SummaryFromDeleteFile {
local replicaPath = " ${ 1 } "
local summaryFile = " ${ 2 } "
local direction = " ${ 3 } "
__CheckArguments 3 $# " $@ " #__WITH_PARANOIA_DEBUG
if [ -f " $summaryFile " ] ; then
while read -r file; do
Logger " $direction $replicaPath $file " "ALWAYS"
done < " $summaryFile "
fi
}
2016-11-14 18:17:30 +00:00
function Summary {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2016-11-14 18:17:30 +00:00
2016-12-06 21:41:44 +00:00
(
2016-11-14 18:17:30 +00:00
_LOGGER_PREFIX = ""
2016-11-15 12:10:47 +00:00
Logger "Attrib updates: INITIATOR << >> TARGET" "ALWAYS"
2016-11-14 18:17:30 +00:00
2018-06-25 21:59:06 +00:00
_SummaryFromRsyncFile " ${ TARGET [ $__replicaDir ] } " " $RUN_DIR / $PROGRAM .attr-update.target. $SCRIPT_PID . $TSTAMP " "~ >>"
_SummaryFromRsyncFile " ${ INITIATOR [ $__replicaDir ] } " " $RUN_DIR / $PROGRAM .attr-update.initiator. $SCRIPT_PID . $TSTAMP " "~ <<"
2016-11-14 18:17:30 +00:00
2018-06-24 17:10:23 +00:00
Logger "File transfers: INITIATOR << >> TARGET (may include file ownership and timestamp attributes)" "ALWAYS"
2018-06-25 21:59:06 +00:00
_SummaryFromRsyncFile " ${ TARGET [ $__replicaDir ] } " " $RUN_DIR / $PROGRAM .update.target. $SCRIPT_PID . $TSTAMP " "+ >>"
_SummaryFromRsyncFile " ${ INITIATOR [ $__replicaDir ] } " " $RUN_DIR / $PROGRAM .update.initiator. $SCRIPT_PID . $TSTAMP " "+ <<"
2016-11-14 18:17:30 +00:00
Logger "File deletions: INITIATOR << >> TARGET" "ALWAYS"
2016-11-14 20:14:10 +00:00
if [ " $REMOTE_OPERATION " = = "yes" ] ; then
2018-06-25 21:59:06 +00:00
_SummaryFromDeleteFile " ${ TARGET [ $__replicaDir ] } " " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } /target ${ TARGET [ $__successDeletedListFile ] } " "- >>"
2016-11-14 20:14:10 +00:00
else
2018-06-25 21:59:06 +00:00
_SummaryFromDeleteFile " ${ TARGET [ $__replicaDir ] } " " $RUN_DIR / $PROGRAM .delete.target. $SCRIPT_PID . $TSTAMP " "- >>"
2016-11-14 20:14:10 +00:00
fi
2018-06-25 21:59:06 +00:00
_SummaryFromDeleteFile " ${ INITIATOR [ $__replicaDir ] } " " $RUN_DIR / $PROGRAM .delete.initiator. $SCRIPT_PID . $TSTAMP " "- <<"
2016-12-06 21:41:44 +00:00
)
2016-11-14 18:17:30 +00:00
}
2017-06-03 11:51:49 +00:00
function LogConflicts {
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2017-06-05 16:53:15 +00:00
local subject
local body
2018-10-01 18:28:46 +00:00
#WIP
2018-10-02 21:37:33 +00:00
if [ " $TRAVIS_RUN " = = true ] ; then
2018-10-01 18:28:46 +00:00
cat " $RUN_DIR / $PROGRAM .conflictList.compare. $SCRIPT_PID . $TSTAMP "
fi
2018-06-25 09:16:57 +00:00
# We keep this in a separate if check because of the subshell used for Logger with _LOGGER_PREFIX
2018-07-02 20:09:18 +00:00
if [ -f " $RUN_DIR / $PROGRAM .conflictList.compare. $SCRIPT_PID . $TSTAMP " ] ; then
2018-06-25 09:16:57 +00:00
Logger "File conflicts: INITIATOR << >> TARGET" "ALWAYS"
fi
2017-06-03 11:51:49 +00:00
(
_LOGGER_PREFIX = ""
2018-10-01 18:28:46 +00:00
2018-07-02 20:09:18 +00:00
if [ -f " $RUN_DIR / $PROGRAM .conflictList.compare. $SCRIPT_PID . $TSTAMP " ] ; then
2017-06-05 16:53:15 +00:00
echo "" > " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__conflictListFile ] } "
2017-06-03 11:51:49 +00:00
while read -r line; do
2018-10-06 19:41:58 +00:00
2018-07-02 20:40:55 +00:00
echo " ${ INITIATOR [ $__replicaDir ] } $( echo $line | awk -F';' '{print $1}' ) << >> ${ TARGET [ $__replicaDir ] } $( echo $line | awk -F';' '{print $1}' ) " >> " ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } / ${ INITIATOR [ $__conflictListFile ] } "
2018-07-02 20:09:18 +00:00
done < " $RUN_DIR / $PROGRAM .conflictList.compare. $SCRIPT_PID . $TSTAMP "
2017-06-05 16:53:15 +00:00
Logger " $( cat ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } /${ INITIATOR [ $__conflictListFile ] } ) " "ALWAYS"
2017-06-03 11:51:49 +00:00
fi
)
2018-07-02 20:09:18 +00:00
if [ " $ALERT_CONFLICTS " = = "yes" ] && [ -s " $RUN_DIR / $PROGRAM .conflictList.compare. $SCRIPT_PID . $TSTAMP " ] ; then
subject = " Conflictual files found in [ $INSTANCE_ID ] "
body = "List of conflictual files:" $'\n' " $( cat ${ INITIATOR [ $__replicaDir ] } ${ INITIATOR [ $__stateDir ] } /${ INITIATOR [ $__conflictListFile ] } ) "
SendEmail " $subject " " $body " " $DESTINATION_MAILS " "" " $SENDER_MAIL " " $SMTP_SERVER " " $SMTP_PORT " " $SMTP_ENCRYPTION " " $SMTP_USER " " $SMTP_PASSWORD "
fi
2017-06-03 11:51:49 +00:00
}
2015-11-12 00:37:43 +00:00
function Init {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
# Set error exit code if a piped command fails
set -o pipefail
set -o errtrace
# Do not use exit and quit traps if osync runs in monitor mode
2018-10-01 08:01:00 +00:00
if [ $_SYNC_ON_CHANGES = = "no" ] ; then
2016-08-22 06:32:24 +00:00
trap TrapStop INT HUP TERM QUIT
2016-02-18 22:28:57 +00:00
trap TrapQuit EXIT
2015-11-12 00:37:43 +00:00
else
2016-08-22 06:32:24 +00:00
trap TrapQuit TERM EXIT HUP QUIT
2015-11-12 00:37:43 +00:00
fi
2016-02-18 15:21:17 +00:00
local uri
local hosturiandpath
local hosturi
2015-11-12 00:37:43 +00:00
## Test if target dir is a ssh uri, and if yes, break it down it its values
if [ " ${ TARGET_SYNC_DIR : 0 : 6 } " = = "ssh://" ] ; then
REMOTE_OPERATION = "yes"
# remove leadng 'ssh://'
uri = ${ TARGET_SYNC_DIR #ssh : //* }
if [ [ " $uri " = = *"@" * ] ] ; then
# remove everything after '@'
REMOTE_USER = ${ uri %@* }
else
REMOTE_USER = $LOCAL_USER
fi
if [ " $SSH_RSA_PRIVATE_KEY " = = "" ] ; then
2016-10-19 10:28:11 +00:00
if [ ! -f " $SSH_PASSWORD_FILE " ] ; then
# Assume that there might exist a standard rsa key
SSH_RSA_PRIVATE_KEY = ~/.ssh/id_rsa
fi
2015-11-12 00:37:43 +00:00
fi
# remove everything before '@'
2016-02-18 15:21:17 +00:00
hosturiandpath = ${ uri #*@ }
2015-11-12 00:37:43 +00:00
# remove everything after first '/'
2016-02-18 15:21:17 +00:00
hosturi = ${ hosturiandpath %%/* }
if [ [ " $hosturi " = = *":" * ] ] ; then
REMOTE_PORT = ${ hosturi ##* : }
2015-11-12 00:37:43 +00:00
else
REMOTE_PORT = 22
fi
2016-02-18 15:21:17 +00:00
REMOTE_HOST = ${ hosturi %% : * }
2015-11-12 00:37:43 +00:00
# remove everything before first '/'
2016-02-18 15:21:17 +00:00
TARGET_SYNC_DIR = ${ hosturiandpath #*/ }
2018-10-01 07:54:24 +00:00
elif [ " ${ INITIATOR_SYNC_DIR : 0 : 6 } " = = "ssh://" ] ; then
REMOTE_OPERATION = "yes"
# remove leadng 'ssh://'
uri = ${ INITIATOR_SYNC_DIR #ssh : //* }
if [ [ " $uri " = = *"@" * ] ] ; then
# remove everything after '@'
REMOTE_USER = ${ uri %@* }
else
REMOTE_USER = $LOCAL_USER
fi
if [ " $SSH_RSA_PRIVATE_KEY " = = "" ] ; then
if [ ! -f " $SSH_PASSWORD_FILE " ] ; then
# Assume that there might exist a standard rsa key
SSH_RSA_PRIVATE_KEY = ~/.ssh/id_rsa
fi
fi
# remove everything before '@'
hosturiandpath = ${ uri #*@ }
# remove everything after first '/'
hosturi = ${ hosturiandpath %%/* }
if [ [ " $hosturi " = = *":" * ] ] ; then
REMOTE_PORT = ${ hosturi ##* : }
else
REMOTE_PORT = 22
fi
REMOTE_HOST = ${ hosturi %% : * }
# remove everything before first '/'
INITIATOR_SYNC_DIR = ${ hosturiandpath #*/ }
2016-11-13 14:59:12 +00:00
else
REMOTE_OPERATION = "no"
2015-11-12 00:37:43 +00:00
fi
2016-08-30 09:29:01 +00:00
if [ " $INITIATOR_SYNC_DIR " = = "" ] || [ " $TARGET_SYNC_DIR " = = "" ] ; then
Logger "Initiator or target path empty." "CRITICAL"
exit 1
fi
2015-11-12 00:37:43 +00:00
## Make sure there is only one trailing slash on path
INITIATOR_SYNC_DIR = " ${ INITIATOR_SYNC_DIR %/ } / "
TARGET_SYNC_DIR = " ${ TARGET_SYNC_DIR %/ } / "
2016-12-11 19:54:40 +00:00
# Expand ~ if exists
INITIATOR_SYNC_DIR = " ${ INITIATOR_SYNC_DIR /# \~ / $HOME } "
TARGET_SYNC_DIR = " ${ TARGET_SYNC_DIR /# \~ / $HOME } "
SSH_RSA_PRIVATE_KEY = " ${ SSH_RSA_PRIVATE_KEY /# \~ / $HOME } "
2016-10-19 10:28:11 +00:00
SSH_PASSWORD_FILE = " ${ SSH_PASSWORD_FILE /# \~ / $HOME } "
2016-09-02 19:43:14 +00:00
2016-02-17 12:51:42 +00:00
## Replica format
## Why the f*** does bash not have simple objects ?
# Local variables used for state filenames
2016-10-16 12:25:29 +00:00
local lockFilename = "lock"
local stateDir = "state"
local backupDir = "backup"
local deleteDir = "deleted"
local partialDir = "_partial"
local lastAction = "last-action"
2016-12-11 19:54:40 +00:00
local resumeCount = "resume-count"
2018-10-01 08:27:01 +00:00
local pushFile = ".osync-update.push"
2016-08-29 11:54:24 +00:00
if [ " $_DRYRUN " = = true ] ; then
2016-12-11 19:54:40 +00:00
local drySuffix = "-dry"
2016-02-19 20:44:52 +00:00
else
2016-10-16 12:25:29 +00:00
local drySuffix =
2016-02-19 20:44:52 +00:00
fi
2016-08-30 10:19:12 +00:00
# The following associative like array definitions are used for bash ver < 4 compat
readonly __type = 0
readonly __replicaDir = 1
readonly __lockFile = 2
readonly __stateDir = 3
readonly __backupDir = 4
readonly __deleteDir = 5
readonly __partialDir = 6
readonly __initiatorLastActionFile = 7
readonly __targetLastActionFile = 8
readonly __resumeCount = 9
readonly __treeCurrentFile = 10
readonly __treeAfterFile = 11
readonly __treeAfterFileNoSuffix = 12
2016-09-16 07:48:58 +00:00
readonly __deletedListFile = 13
2016-08-30 10:19:12 +00:00
readonly __failedDeletedListFile = 14
2016-11-14 20:14:10 +00:00
readonly __successDeletedListFile = 15
2017-05-30 13:00:05 +00:00
readonly __timestampCurrentFile = 16
2017-06-03 11:51:49 +00:00
readonly __timestampAfterFile = 17
2017-06-05 16:53:15 +00:00
readonly __timestampAfterFileNoSuffix = 18
readonly __conflictListFile = 19
2017-07-27 20:50:48 +00:00
readonly __updateTriggerFile = 20
2016-08-30 10:19:12 +00:00
INITIATOR = ( )
INITIATOR[ $__type ] = 'initiator'
INITIATOR[ $__replicaDir ] = " $INITIATOR_SYNC_DIR "
2016-10-16 12:25:29 +00:00
INITIATOR[ $__lockFile ] = " $INITIATOR_SYNC_DIR $OSYNC_DIR / $lockFilename "
INITIATOR[ $__stateDir ] = " $OSYNC_DIR / $stateDir "
INITIATOR[ $__backupDir ] = " $OSYNC_DIR / $backupDir "
INITIATOR[ $__deleteDir ] = " $OSYNC_DIR / $deleteDir "
INITIATOR[ $__partialDir ] = " $OSYNC_DIR / $partialDir "
INITIATOR[ $__initiatorLastActionFile ] = " $INITIATOR_SYNC_DIR $OSYNC_DIR / $stateDir /initiator- $lastAction - $INSTANCE_ID $drySuffix "
INITIATOR[ $__targetLastActionFile ] = " $INITIATOR_SYNC_DIR $OSYNC_DIR / $stateDir /target- $lastAction - $INSTANCE_ID $drySuffix "
INITIATOR[ $__resumeCount ] = " $INITIATOR_SYNC_DIR $OSYNC_DIR / $stateDir / $resumeCount - $INSTANCE_ID $drySuffix "
INITIATOR[ $__treeCurrentFile ] = " -tree-current- $INSTANCE_ID $drySuffix "
INITIATOR[ $__treeAfterFile ] = " -tree-after- $INSTANCE_ID $drySuffix "
2016-08-30 10:19:12 +00:00
INITIATOR[ $__treeAfterFileNoSuffix ] = " -tree-after- $INSTANCE_ID "
2016-10-16 12:25:29 +00:00
INITIATOR[ $__deletedListFile ] = " -deleted-list- $INSTANCE_ID $drySuffix "
INITIATOR[ $__failedDeletedListFile ] = " -failed-delete- $INSTANCE_ID $drySuffix "
2016-11-14 20:14:10 +00:00
INITIATOR[ $__successDeletedListFile ] = " -success-delete- $INSTANCE_ID $drySuffix "
2017-05-30 12:35:44 +00:00
INITIATOR[ $__timestampCurrentFile ] = " -timestamps-current- $INSTANCE_ID $drySuffix "
2017-06-03 11:51:49 +00:00
INITIATOR[ $__timestampAfterFile ] = " -timestamps-after- $INSTANCE_ID $drySuffix "
2017-06-05 16:53:15 +00:00
INITIATOR[ $__timestampAfterFileNoSuffix ] = " -timestamps-after- $INSTANCE_ID "
2017-05-30 13:45:43 +00:00
INITIATOR[ $__conflictListFile ] = " conflicts- $INSTANCE_ID $drySuffix "
2018-10-01 08:27:01 +00:00
INITIATOR[ $__updateTriggerFile ] = " $INITIATOR_SYNC_DIR $pushFile "
2016-08-30 10:19:12 +00:00
TARGET = ( )
TARGET[ $__type ] = 'target'
TARGET[ $__replicaDir ] = " $TARGET_SYNC_DIR "
2016-10-16 12:25:29 +00:00
TARGET[ $__lockFile ] = " $TARGET_SYNC_DIR $OSYNC_DIR / $lockFilename "
TARGET[ $__stateDir ] = " $OSYNC_DIR / $stateDir "
TARGET[ $__backupDir ] = " $OSYNC_DIR / $backupDir "
TARGET[ $__deleteDir ] = " $OSYNC_DIR / $deleteDir "
2016-11-14 20:14:10 +00:00
TARGET[ $__partialDir ] = " $OSYNC_DIR / $partialDir " # unused
TARGET[ $__initiatorLastActionFile ] = " $TARGET_SYNC_DIR $OSYNC_DIR / $stateDir /initiator- $lastAction - $INSTANCE_ID $drySuffix " # unused
TARGET[ $__targetLastActionFile ] = " $TARGET_SYNC_DIR $OSYNC_DIR / $stateDir /target- $lastAction - $INSTANCE_ID $drySuffix " # unused
TARGET[ $__resumeCount ] = " $TARGET_SYNC_DIR $OSYNC_DIR / $stateDir / $resumeCount - $INSTANCE_ID $drySuffix " # unused
TARGET[ $__treeCurrentFile ] = " -tree-current- $INSTANCE_ID $drySuffix " # unused
TARGET[ $__treeAfterFile ] = " -tree-after- $INSTANCE_ID $drySuffix " # unused
TARGET[ $__treeAfterFileNoSuffix ] = " -tree-after- $INSTANCE_ID " # unused
TARGET[ $__deletedListFile ] = " -deleted-list- $INSTANCE_ID $drySuffix " # unused
TARGET[ $__failedDeletedListFile ] = " -failed-delete- $INSTANCE_ID $drySuffix "
TARGET[ $__successDeletedListFile ] = " -success-delete- $INSTANCE_ID $drySuffix "
2017-05-30 12:35:44 +00:00
TARGET[ $__timestampCurrentFile ] = " -timestamps-current- $INSTANCE_ID $drySuffix "
2017-06-03 11:51:49 +00:00
TARGET[ $__timestampAfterFile ] = " -timestamps-after- $INSTANCE_ID $drySuffix "
2017-06-05 16:53:15 +00:00
TARGET[ $__timestampAfterFileNoSuffix ] = " -timestamps-after- $INSTANCE_ID "
2017-05-30 13:45:43 +00:00
TARGET[ $__conflictListFile ] = " conflicts- $INSTANCE_ID $drySuffix "
2018-10-01 08:27:01 +00:00
TARGET[ $__updateTriggerFile ] = " $TARGET_SYNC_DIR $pushFile "
2016-11-14 20:14:10 +00:00
2016-08-30 10:19:12 +00:00
PARTIAL_DIR = " ${ INITIATOR [ $__partialDir ] } "
2015-11-12 00:37:43 +00:00
## Set sync only function arguments for rsync
SYNC_OPTS = "-u"
2016-11-17 19:00:50 +00:00
if [ $_LOGGER_VERBOSE = = true ] || [ $_SUMMARY = = true ] ; then
2016-03-01 19:13:48 +00:00
SYNC_OPTS = $SYNC_OPTS " -i"
2015-11-12 00:37:43 +00:00
fi
2016-08-29 11:54:24 +00:00
if [ $STATS = = true ] ; then
2015-11-12 00:37:43 +00:00
SYNC_OPTS = $SYNC_OPTS " --stats"
fi
2015-11-27 13:12:44 +00:00
## Add Rsync include / exclude patterns
2018-10-01 18:28:46 +00:00
if [ " $_SYNC_ON_CHANGES " != "target" ] ; then
RsyncPatterns
fi
2015-11-12 00:37:43 +00:00
2016-02-17 12:51:42 +00:00
## Conflict options
if [ " $CONFLICT_BACKUP " != "no" ] ; then
2016-11-15 12:49:00 +00:00
INITIATOR_BACKUP = " --backup --backup-dir=\" ${ INITIATOR [ $__backupDir ] } \" "
TARGET_BACKUP = " --backup --backup-dir=\" ${ TARGET [ $__backupDir ] } \" "
2016-02-17 12:51:42 +00:00
if [ " $CONFLICT_BACKUP_MULTIPLE " = = "yes" ] ; then
INITIATOR_BACKUP = " $INITIATOR_BACKUP --suffix . $( date +%Y.%m.%d-%H.%M.%S) "
TARGET_BACKUP = " $TARGET_BACKUP --suffix . $( date +%Y.%m.%d-%H.%M.%S) "
fi
else
2016-06-03 18:41:34 +00:00
INITIATOR_BACKUP = ""
TARGET_BACKUP = ""
2016-02-17 12:51:42 +00:00
fi
2015-11-12 00:37:43 +00:00
SYNC_ACTION = (
2016-08-09 20:14:17 +00:00
'replica-tree'
'deleted-list'
2017-06-03 11:57:10 +00:00
'timestampList-list'
2017-05-30 09:14:11 +00:00
'conflict-list'
2016-08-09 20:14:17 +00:00
'sync_attrs'
'update-replica'
'delete-propagation'
'replica-tree-after'
2017-06-03 11:57:10 +00:00
'timestampList-after'
2016-08-09 20:14:17 +00:00
'synced'
2015-11-12 00:37:43 +00:00
)
}
function Main {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2016-12-06 21:51:19 +00:00
HandleLocks
2015-11-12 00:37:43 +00:00
Sync
}
function Usage {
2016-12-07 20:30:10 +00:00
__CheckArguments 0 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
if [ " $IS_STABLE " != "yes" ] ; then
2016-12-11 19:54:40 +00:00
echo -e "\e[93mThis is an unstable dev build. Please use with caution.\e[0m"
fi
2015-11-12 00:37:43 +00:00
echo " $PROGRAM $PROGRAM_VERSION $PROGRAM_BUILD "
2016-10-17 07:56:40 +00:00
echo " $AUTHOR "
echo " $CONTACT "
2015-11-12 00:37:43 +00:00
echo ""
2017-06-18 20:11:09 +00:00
echo " You may use $PROGRAM with a full blown configuration file, or use its default options for quick command line sync. "
echo " Usage: $0 /path/to/config/file [OPTIONS] "
echo " or $0 --initiator=/path/to/initiator/replica --target=/path/to/target/replica [OPTIONS] [QUICKSYNC OPTIONS] "
echo " or $0 --initiator=/path/to/initiator/replica --target=ssh://[backupuser]@remotehost.com[:portnumber]//path/to/target/replica [OPTIONS] [QUICKSYNC OPTIONS] "
2015-11-12 00:37:43 +00:00
echo ""
echo "[OPTIONS]"
2017-05-30 07:29:16 +00:00
echo "--dry Will run osync without actually doing anything; just testing"
echo "--no-prefix Will suppress time / date suffix from output"
echo "--silent Will run osync without any output to stdout, used for cron jobs"
echo "--errors-only Output only errors (can be combined with silent or verbose)"
echo "--summary Outputs a list of transferred / deleted files at the end of the run"
echo "--log-conflicts Outputs a list of conflicted files"
2017-06-05 16:53:15 +00:00
echo "--alert-conflicts Send an email if conflictual files found (implies --log-conflicts)"
2017-05-30 07:29:16 +00:00
echo "--verbose Increases output"
echo "--stats Adds rsync transfer statistics to verbose output"
echo "--partial Allows rsync to keep partial downloads that can be resumed later (experimental)"
echo "--no-maxtime Disables any soft and hard execution time checks"
echo "--force-unlock Will override any existing active or dead locks on initiator and target replica"
echo "--on-changes Will launch a sync task after a short wait period if there is some file activity on initiator replica. You should try daemon mode instead"
2018-09-30 19:21:30 +00:00
echo "--on-changes-target Will trigger ansync task on initiator if initiator runs daemon mode. You should call this with the osync-target-helper service"
2017-05-30 12:50:21 +00:00
echo "--no-resume Do not try to resume a failed run. By default, execution is resumed once"
2018-06-25 21:55:13 +00:00
echo "--initialize Create file lists without actually synchronizing anything, this will help setup deletion detections before the first run"
2017-05-30 12:50:21 +00:00
2015-11-12 00:37:43 +00:00
echo ""
echo "[QUICKSYNC OPTIONS]"
echo "--initiator=\"\" Master replica path. Will contain state and backup directory (is mandatory)"
echo "--target=\"\" Local or remote target replica path. Can be a ssh uri like ssh://user@host.com:22//path/to/target/replica (is mandatory)"
echo "--rsakey=\"\" Alternative path to rsa private key for ssh connection to target replica"
2016-10-19 10:28:11 +00:00
echo "--password-file=\"\" If no rsa private key is used for ssh authentication, a password file can be used"
2017-02-08 12:52:04 +00:00
echo "--remote-token=\"\" When using ssh filter protection, you must specify the remote token set in ssh_filter.sh"
2015-11-12 00:37:43 +00:00
echo "--instance-id=\"\" Optional sync task name to identify this synchronization task when using multiple targets"
2016-10-21 10:38:03 +00:00
echo "--skip-deletion=\"\" You may skip deletion propagation on initiator or target. Valid values: initiator target initiator,target"
2016-12-12 10:16:53 +00:00
echo "--destination-mails=\"\" Double quoted list of space separated email addresses to send alerts to"
2015-11-12 00:37:43 +00:00
echo ""
echo "Additionaly, you may set most osync options at runtime. eg:"
2017-06-18 20:11:09 +00:00
echo " SOFT_DELETE_DAYS=365 $0 --initiator=/path --target=/other/path "
2015-11-12 00:37:43 +00:00
echo ""
exit 128
}
function SyncOnChanges {
2018-09-30 14:08:12 +00:00
local isTargetHelper = " ${ 1 :- false } " # Is this service supposed to be run as target helper ?
__CheckArguments 1 $# " $@ " #__WITH_PARANOIA_DEBUG
2015-11-12 00:37:43 +00:00
2018-09-30 14:08:12 +00:00
local watchDirectory
2016-08-04 09:52:28 +00:00
local cmd
local retval
2016-02-18 15:21:17 +00:00
2016-11-21 16:02:05 +00:00
if [ " $LOCAL_OS " = = "MacOSX" ] ; then
if ! type fswatch > /dev/null 2>& 1 ; then
2018-10-01 05:26:56 +00:00
Logger "No fswatch command found. Cannot monitor changes." "CRITICAL"
2016-11-21 16:02:05 +00:00
exit 1
fi
else
if ! type inotifywait > /dev/null 2>& 1 ; then
Logger "No inotifywait command found. Cannot monitor changes." "CRITICAL"
exit 1
fi
2015-11-12 00:37:43 +00:00
fi
2018-09-30 14:08:12 +00:00
if [ $isTargetHelper = = false ] ; then
if [ ! -d " $INITIATOR_SYNC_DIR " ] ; then
Logger " Initiator directory [ $INITIATOR_SYNC_DIR ] does not exist. Cannot monitor. " "CRITICAL"
exit 1
fi
Logger " #### Running $PROGRAM in initiator file monitor mode. " "NOTICE"
else
if [ ! -d " $TARGET_SYNC_DIR " ] ; then
Logger " Target directory [ $TARGET_SYNC_DIR ] does not exist. Cannot monitor. " "CRITICAL"
exit 1
fi
Logger " #### Running $PROGRAM in target helper file monitor mode. " "NOTICE"
fi
2015-11-12 00:37:43 +00:00
2016-08-08 16:06:03 +00:00
while true; do
2018-09-30 14:08:12 +00:00
if [ $isTargetHelper = = false ] ; then
if [ " $ConfigFile " != "" ] ; then
cmd = 'bash ' $osync_cmd ' "' $ConfigFile '" ' $opts
else
cmd = 'bash ' $osync_cmd ' ' $opts
fi
Logger " Daemon cmd: $cmd " "DEBUG"
eval " $cmd "
retval = $?
if [ $retval -ne 0 ] && [ $retval != 2 ] ; then
Logger " $PROGRAM child exited with error. " "ERROR" $retval
fi
watchDirectory = " $INITIATOR_SYNC_DIR "
2015-11-12 00:37:43 +00:00
else
2018-09-30 14:08:12 +00:00
# Notify initiator about target changes
TriggerInitiatorRun
watchDirectory = " $TARGET_SYNC_DIR "
2015-11-12 00:37:43 +00:00
fi
2018-09-30 14:08:12 +00:00
2015-11-12 00:37:43 +00:00
Logger "#### Monitoring now." "NOTICE"
2016-11-21 16:02:05 +00:00
if [ " $LOCAL_OS " = = "MacOSX" ] ; then
2018-09-30 14:08:12 +00:00
fswatch $RSYNC_PATTERNS --exclude " $OSYNC_DIR " -1 " $watchDirectory " > /dev/null &
2018-10-01 05:26:56 +00:00
# Mac fswatch doesn't have timeout switch, replacing wait $! with WaitForTaskCompletion without warning nor spinner and increased SLEEP_TIME to avoid cpu hogging. This simulates wait $! with timeout
2018-02-20 21:15:04 +00:00
ExecTasks $! "MonitorMacOSXWait" false 0 0 0 $MAX_WAIT true 1 0
2018-09-30 14:08:12 +00:00
elif [ " $LOCAL_OS " = = "BSD" ] ; then
2018-07-08 11:18:26 +00:00
# BSD version of inotifywait does not support multiple --exclude statements
2018-09-30 14:08:12 +00:00
inotifywait --exclude " $OSYNC_DIR " -qq -r -e create -e modify -e delete -e move -e attrib --timeout " $MAX_WAIT " " $watchDirectory " &
2016-11-21 16:02:05 +00:00
else
2018-10-01 08:49:35 +00:00
inotifywait --exclude " $OSYNC_DIR " $RSYNC_PATTERNS -qq -r -e create -e modify -e delete -e move -e attrib --timeout " $MAX_WAIT " " $watchDirectory " &
2016-11-22 16:18:35 +00:00
wait $!
2016-11-21 16:02:05 +00:00
fi
2015-11-12 00:37:43 +00:00
retval = $?
2016-12-11 13:26:48 +00:00
if [ $retval -eq 0 ] ; then
2015-11-12 00:37:43 +00:00
Logger " #### Changes detected, waiting $MIN_WAIT seconds before running next sync. " "NOTICE"
sleep $MIN_WAIT
2016-12-11 13:45:01 +00:00
# inotifywait --timeout result is 2, WaitForTaskCompletion HardTimeout is 1
elif [ " $LOCAL_OS " = = "MacOSX" ] ; then
Logger " #### Changes or error detected, waiting $MIN_WAIT seconds before running next sync. " "NOTICE"
2016-12-11 13:26:48 +00:00
elif [ $retval -eq 2 ] ; then
2015-11-12 00:37:43 +00:00
Logger " #### $MAX_WAIT timeout reached, running sync. " "NOTICE"
2016-12-11 13:45:01 +00:00
elif [ $retval -eq 1 ] ; then
2017-06-18 20:11:09 +00:00
Logger " #### inotify error detected, waiting $MIN_WAIT seconds before running next sync. " "ERROR" $retval
2015-11-12 00:37:43 +00:00
sleep $MIN_WAIT
2018-02-20 21:53:30 +00:00
elif [ $retval -eq 127 ] ; then
Logger "inotifywait could not load succesfully. Please check if all necessary libraries for inotifywait are present." "CRITICAL"
exit 1
2015-11-12 00:37:43 +00:00
fi
done
}
2016-12-03 08:53:44 +00:00
#### SCRIPT ENTRY POINT
2016-02-19 00:13:17 +00:00
# quicksync mode settings, overriden by config file
2016-08-29 11:54:24 +00:00
STATS = false
PARTIAL = no
2016-02-21 10:11:28 +00:00
if [ " $CONFLICT_PREVALANCE " = = "" ] ; then
CONFLICT_PREVALANCE = initiator
fi
2016-07-27 10:04:27 +00:00
2016-12-12 10:16:53 +00:00
DESTINATION_MAILS = ""
2016-08-28 19:07:40 +00:00
INITIATOR_LOCK_FILE_EXISTS = false
TARGET_LOCK_FILE_EXISTS = false
2016-08-29 11:54:24 +00:00
FORCE_UNLOCK = false
2017-05-30 13:45:43 +00:00
LOG_CONFLICTS = "no"
2017-06-05 16:53:15 +00:00
ALERT_CONFLICTS = "no"
2016-08-29 11:54:24 +00:00
no_maxtime = false
2015-11-12 00:37:43 +00:00
opts = ""
2016-08-29 11:54:24 +00:00
ERROR_ALERT = false
WARN_ALERT = false
2016-12-03 08:53:44 +00:00
# Number of CTRL+C needed to stop script
SOFT_STOP = 2
2016-08-29 11:54:24 +00:00
# Number of given replicas in command line
2015-11-12 00:37:43 +00:00
_QUICK_SYNC = 0
2018-10-01 08:01:00 +00:00
_SYNC_ON_CHANGES = "no"
2016-08-29 11:54:24 +00:00
_NOLOCKS = false
2015-11-12 00:37:43 +00:00
osync_cmd = $0
2016-11-14 18:17:30 +00:00
_SUMMARY = false
2018-06-25 21:55:13 +00:00
INITIALIZE = "no"
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
function GetCommandlineArguments {
local isFirstArgument = true
if [ $# -eq 0 ]
then
2015-11-12 00:37:43 +00:00
Usage
2017-07-27 20:50:48 +00:00
fi
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
for i in " $@ " ; do
case $i in
--dry)
_DRYRUN = true
opts = $opts " --dry"
; ;
--silent)
_LOGGER_SILENT = true
opts = $opts " --silent"
; ;
--verbose)
_LOGGER_VERBOSE = true
opts = $opts " --verbose"
; ;
--stats)
STATS = true
opts = $opts " --stats"
; ;
--partial)
PARTIAL = "yes"
opts = $opts " --partial"
; ;
--force-unlock)
FORCE_UNLOCK = true
opts = $opts " --force-unlock"
; ;
--no-maxtime)
no_maxtime = true
opts = $opts " --no-maxtime"
; ;
--help| -h| --version| -v)
Usage
; ;
--initiator= *)
_QUICK_SYNC = $(( $_QUICK_SYNC + 1 ))
INITIATOR_SYNC_DIR = ${ i ##*= }
opts = $opts " --initiator=\" $INITIATOR_SYNC_DIR \" "
; ;
--target= *)
_QUICK_SYNC = $(( $_QUICK_SYNC + 1 ))
TARGET_SYNC_DIR = ${ i ##*= }
opts = $opts " --target=\" $TARGET_SYNC_DIR \" "
; ;
--rsakey= *)
SSH_RSA_PRIVATE_KEY = ${ i ##*= }
opts = $opts " --rsakey=\" $SSH_RSA_PRIVATE_KEY \" "
; ;
--password-file= *)
SSH_PASSWORD_FILE = ${ i ##*= }
opts = $opts " --password-file\" $SSH_PASSWORD_FILE \" "
; ;
--instance-id= *)
INSTANCE_ID = ${ i ##*= }
opts = $opts " --instance-id=\" $INSTANCE_ID \" "
; ;
--skip-deletion= *)
opts = $opts " --skip-deletion=\" ${ i ##*= } \" "
2017-11-22 14:05:09 +00:00
SKIP_DELETION = ${ i ##*= }
2017-07-27 20:50:48 +00:00
; ;
--on-changes)
2018-10-01 08:01:00 +00:00
_SYNC_ON_CHANGES = "initiator"
2018-09-30 19:21:30 +00:00
_NOLOCKS = true
_LOGGER_PREFIX = "date"
; ;
--on-changes-target)
2018-10-01 08:01:00 +00:00
_SYNC_ON_CHANGES = "target"
2017-07-27 20:50:48 +00:00
_NOLOCKS = true
_LOGGER_PREFIX = "date"
; ;
--no-resume)
opts = $opts " --no-resume"
RESUME_TRY = 0
; ;
--no-locks)
_NOLOCKS = true
; ;
--errors-only)
opts = $opts " --errors-only"
_LOGGER_ERR_ONLY = true
; ;
--summary)
opts = $opts " --summary"
_SUMMARY = true
; ;
--log-conflicts)
LOG_CONFLICTS = "yes"
opts = $opts " --log-conflicts"
; ;
--alert-conflicts)
ALERT_CONFLICTS = "yes"
LOG_CONFLICTS = "yes"
opts = $opts " --alert-conflicts"
; ;
2018-06-25 21:55:13 +00:00
--initialize)
INITIALIZE = "yes"
2018-07-02 13:46:45 +00:00
opts = $opts " --initialize"
2018-06-25 21:55:13 +00:00
; ;
2017-07-27 20:50:48 +00:00
--no-prefix)
opts = $opts " --no-prefix"
_LOGGER_PREFIX = ""
; ;
--destination-mails= *)
DESTINATION_MAILS = ${ i ##*= }
; ;
--remote-token= *)
_REMOTE_TOKEN = ${ i ##*= }
; ;
*)
if [ $isFirstArgument = = false ] ; then
Logger " Unknown option ' $i ' " "CRITICAL"
Usage
fi
; ;
esac
isFirstArgument = false
done
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
# Remove leading space if there is one
opts = " ${ opts # * } "
}
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
GetCommandlineArguments " $@ "
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
## Here we set default options for quicksync tasks when no configuration file is provided.
if [ $_QUICK_SYNC -eq 2 ] ; then
if [ " $INSTANCE_ID " = = "" ] ; then
INSTANCE_ID = "quicksync_task"
fi
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
# Let the possibility to initialize those values directly via command line like SOFT_DELETE_DAYS=60 ./osync.sh
if [ $( IsInteger $MINIMUM_SPACE ) -ne 1 ] ; then
MINIMUM_SPACE = 1024
fi
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
if [ $( IsInteger $CONFLICT_BACKUP_DAYS ) -ne 1 ] ; then
CONFLICT_BACKUP_DAYS = 30
fi
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
if [ $( IsInteger $SOFT_DELETE_DAYS ) -ne 1 ] ; then
SOFT_DELETE_DAYS = 30
fi
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
if [ $( IsInteger $RESUME_TRY ) -ne 1 ] ; then
RESUME_TRY = 1
fi
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
if [ $( IsInteger $SOFT_MAX_EXEC_TIME ) -ne 1 ] ; then
SOFT_MAX_EXEC_TIME = 0
fi
2015-11-12 00:37:43 +00:00
2017-07-27 20:50:48 +00:00
if [ $( IsInteger $HARD_MAX_EXEC_TIME ) -ne 1 ] ; then
HARD_MAX_EXEC_TIME = 0
fi
2016-11-15 21:32:33 +00:00
2018-03-20 09:49:20 +00:00
if [ $( IsInteger $MAX_EXEC_TIME_PER_CMD_BEFORE ) -ne 1 ] ; then
MAX_EXEC_TIME_PER_CMD_BEFORE = 0
fi
if [ $( IsInteger $MAX_EXEC_TIME_PER_CMD_AFTER ) -ne 1 ] ; then
MAX_EXEC_TIME_PER_CMD_AFTER = 0
fi
2017-07-27 20:50:48 +00:00
if [ " $PATH_SEPARATOR_CHAR " = = "" ] ; then
PATH_SEPARATOR_CHAR = ";"
2015-11-12 00:37:43 +00:00
fi
2018-03-20 09:46:13 +00:00
if [ $( IsInteger $MIN_WAIT ) -ne 1 ] ; then
2017-07-27 20:50:48 +00:00
MIN_WAIT = 30
2018-03-20 09:46:13 +00:00
fi
2018-07-01 08:46:16 +00:00
# First character shouldn't be '-' when config file given
elif [ " ${ 1 : 0 : 1 } " != "-" ] ; then
2017-07-27 20:50:48 +00:00
ConfigFile = " ${ 1 } "
LoadConfigFile " $ConfigFile "
2018-07-01 08:46:16 +00:00
else
Logger "Wrong arguments given. Expecting a config file or initiator and target arguments." "CRITICAL"
exit 1
2017-07-27 20:50:48 +00:00
fi
2015-11-12 00:37:43 +00:00
2016-11-14 18:17:30 +00:00
if [ " $LOGFILE " = = "" ] ; then
if [ -w /var/log ] ; then
LOG_FILE = " /var/log/ $PROGRAM . $INSTANCE_ID .log "
elif ( [ " $HOME " != "" ] && [ -w " $HOME " ] ) ; then
LOG_FILE = " $HOME / $PROGRAM . $INSTANCE_ID .log "
2016-10-21 16:23:45 +00:00
else
2016-11-14 18:17:30 +00:00
LOG_FILE = " ./ $PROGRAM . $INSTANCE_ID .log "
2016-10-21 16:23:45 +00:00
fi
2016-11-14 18:17:30 +00:00
else
LOG_FILE = " $LOGFILE "
fi
if [ ! -w " $( dirname $LOG_FILE ) " ] ; then
echo " Cannot write to log [ $( dirname $LOG_FILE ) ]. "
else
Logger " Script begin, logging to [ $LOG_FILE ]. " "DEBUG"
fi
2015-11-12 00:37:43 +00:00
2016-11-14 18:17:30 +00:00
if [ " $IS_STABLE " != "yes" ] ; then
Logger " This is an unstable dev build [ $PROGRAM_BUILD ]. Please use with caution. " "WARN"
fi
2016-04-07 16:17:10 +00:00
2016-11-14 18:17:30 +00:00
GetLocalOS
2016-12-04 10:10:02 +00:00
InitLocalOSDependingSettings
2016-11-14 18:17:30 +00:00
PreInit
Init
CheckEnvironment
PostInit
if [ $_QUICK_SYNC -lt 2 ] ; then
2018-10-01 08:08:22 +00:00
if [ " $_SYNC_ON_CHANGES " = = "no" ] ; then
CheckCurrentConfig true
else
CheckCurrentConfig false
fi
2016-11-14 18:17:30 +00:00
fi
CheckCurrentConfigAll
DATE = $( date)
Logger "-------------------------------------------------------------" "NOTICE"
2016-11-15 12:11:59 +00:00
Logger " $DRY_WARNING $DATE - $PROGRAM $PROGRAM_VERSION script begin. " "ALWAYS"
2016-11-14 18:17:30 +00:00
Logger "-------------------------------------------------------------" "NOTICE"
Logger " Sync task [ $INSTANCE_ID ] launched as $LOCAL_USER @ $LOCAL_HOST (PID $SCRIPT_PID ) " "NOTICE"
2018-10-01 08:08:22 +00:00
if [ " $_SYNC_ON_CHANGES " = = "initiator" ] ; then
2018-09-30 14:08:12 +00:00
SyncOnChanges false
2018-10-01 08:08:22 +00:00
elif [ " $_SYNC_ON_CHANGES " = = "target" ] ; then
2018-09-30 19:21:30 +00:00
SyncOnChanges true
2016-11-14 18:17:30 +00:00
else
GetRemoteOS
2016-12-04 10:10:02 +00:00
InitRemoteOSDependingSettings
2016-11-14 18:17:30 +00:00
if [ $no_maxtime = = true ] ; then
SOFT_MAX_EXEC_TIME = 0
HARD_MAX_EXEC_TIME = 0
fi
2016-12-06 21:41:44 +00:00
CheckReplicas
2016-11-14 18:17:30 +00:00
RunBeforeHook
2018-06-25 21:55:13 +00:00
if [ " $INITIALIZE " = = "yes" ] ; then
HandleLocks
Initialize
else
Main
if [ $? -eq 0 ] ; then
SoftDelete
fi
if [ $_SUMMARY = = true ] ; then
Summary
fi
if [ $LOG_CONFLICTS = = "yes" ] ; then
LogConflicts
fi
2017-06-03 11:51:49 +00:00
fi
2016-11-14 18:17:30 +00:00
fi