Rebuilt targets

pull/84/head
deajan 8 years ago
parent 7283729eae
commit cafbf43222

@ -3,8 +3,8 @@
PROGRAM="osync" # Rsync based two way sync engine with fault tolerance
AUTHOR="(C) 2013-2016 by Orsiris de Jong"
CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr"
PROGRAM_VERSION=1.2-beta2
PROGRAM_BUILD=2016111502
PROGRAM_VERSION=1.2-beta3
PROGRAM_BUILD=2016111704
IS_STABLE=no
# Execution order #__WITH_PARANOIA_DEBUG
@ -45,17 +45,22 @@ IS_STABLE=no
#### MINIMAL-FUNCTION-SET BEGIN ####
## FUNC_BUILD=2016111503
## FUNC_BUILD=2016111705
## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
## To use in a program, define the following variables:
## PROGRAM=program-name
## INSTANCE_ID=program-instance-name
## _DEBUG=yes/no
## _LOGGER_STDERR=true/false
## _LOGGER_LOGGER_SILENT=true/false
## _LOGGER_LOGGER_VERBOSE=true/false
## _LOGGER_ERR_ONLY=true/false
## _LOGGER_PREFIX="date"/"time"/""
## Logger sets {ERROR|WARN}_ALERT variable when called with critical / error / warn loglevel
## When called from subprocesses, variable of main process can't be set. Status needs to be get via $RUN_DIR/$PROGRAM.Logger.{error|warn}.$SCRIPT_PID
#TODO: Rewrite Logger so we can decide what to send to stdout, stderr and logfile
#TODO: Windows checks, check sendmail & mailsend
if ! type "$BASH" > /dev/null; then
@ -71,10 +76,10 @@ MAIL_ALERT_MSG="Execution of $PROGRAM instance $INSTANCE_ID on $(date) has warni
# Environment variables that can be overriden by programs
_DRYRUN=false
_SILENT=false
_VERBOSE=false
_LOGGER_SILENT=false
_LOGGER_VERBOSE=false
_LOGGER_ERR_ONLY=false
_LOGGER_PREFIX="date"
_LOGGER_STDERR=false
if [ "$KEEP_LOGGING" == "" ]; then
KEEP_LOGGING=1801
fi
@ -83,9 +88,6 @@ fi
ERROR_ALERT=false
WARN_ALERT=false
# Log from current run
CURRENT_LOG=""
## allow function call checks #__WITH_PARANOIA_DEBUG
if [ "$_PARANOIA_DEBUG" == "yes" ];then #__WITH_PARANOIA_DEBUG
_DEBUG=yes #__WITH_PARANOIA_DEBUG
@ -95,13 +97,13 @@ fi #__WITH_PARANOIA_DEBUG
if [ ! "$_DEBUG" == "yes" ]; then
_DEBUG=no
SLEEP_TIME=.05 # Tested under linux and FreeBSD bash, #TODO tests on cygwin / msys
_VERBOSE=false
_LOGGER_VERBOSE=false
else
if [ "$SLEEP_TIME" == "" ]; then
SLEEP_TIME=1
if [ "$SLEEP_TIME" == "" ]; then # Set SLEEP_TIME as environment variable when runinng with bash -x in order to avoid spamming console
SLEEP_TIME=.05
fi
trap 'TrapError ${LINENO} $?' ERR
_VERBOSE=true
_LOGGER_VERBOSE=true
fi
SCRIPT_PID=$$
@ -148,28 +150,43 @@ function Dummy {
# Sub function of Logger
function _Logger {
local svalue="${1}" # What to log to stdout
local lvalue="${2:-$svalue}" # What to log to logfile, defaults to screen value
local evalue="${3}" # What to log to stderr
local logValue="${1}" # Log to file
local stdValue="${2}" # Log to screeen
local toStderr="${3:-false}" # Log to stderr instead of stdout
echo -e "$logValue" >> "$LOG_FILE"
# Current log file
echo -e "$logValue" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID"
echo -e "$lvalue" >> "$LOG_FILE"
CURRENT_LOG="$CURRENT_LOG"$'\n'"$lvalue"
if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then
if [ $toStderr == true ]; then
# Force stderr color in subshell
(>&2 echo -e "$stdValue")
if [ $_LOGGER_STDERR == true ] && [ "$evalue" != "" ]; then
cat <<< "$evalue" 1>&2
elif [ "$_SILENT" == false ]; then
echo -e "$svalue"
else
echo -e "$stdValue"
fi
fi
}
# General log function with log levels:
# CRITICAL, ERROR, WARN are colored in stdout, prefixed in stderr
# NOTICE is standard level
# VERBOSE is only sent to stdout / stderr if _VERBOSE=true
# DEBUG & PARANOIA_DEBUG are only sent if _DEBUG=yes
# Environment variables
# _LOGGER_SILENT: Disables any output to stdout & stderr
# _LOGGER_STD_ERR: Disables any output to stdout except for ALWAYS loglevel
# _LOGGER_VERBOSE: Allows VERBOSE loglevel messages to be sent to stdout
# Loglevels
# Except for VERBOSE, all loglevels are ALWAYS sent to log file
# CRITICAL, ERROR, WARN sent to stderr, color depending on level, level also logged
# NOTICE sent to stdout
# VERBOSE sent to stdout if _LOGGER_VERBOSE = true
# ALWAYS is sent to stdout unless _LOGGER_SILENT = true
# DEBUG & PARANOIA_DEBUG are only sent to stdout if _DEBUG=yes
function Logger {
local value="${1}" # Sentence to log (in double quotes)
local level="${2}" # Log level: PARANOIA_DEBUG, DEBUG, VERBOSE, NOTICE, WARN, ERROR, CRITIAL
local level="${2}" # Log level
if [ "$_LOGGER_PREFIX" == "time" ]; then
prefix="TIME: $SECONDS - "
@ -180,42 +197,44 @@ function Logger {
fi
if [ "$level" == "CRITICAL" ]; then
_Logger "$prefix\e[41m$value\e[0m" "$prefix$level:$value" "$level:$value"
_Logger "$prefix($level):$value" "$prefix\e[41m$value\e[0m" true
ERROR_ALERT=true
# ERROR_ALERT / WARN_ALERT isn't set in main when Logger is called from a subprocess. Need to keep this flag.
echo "1" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID"
return
elif [ "$level" == "ERROR" ]; then
_Logger "$prefix\e[91m$value\e[0m" "$prefix$level:$value" "$level:$value"
_Logger "$prefix($level):$value" "$prefix\e[91m$value\e[0m" true
ERROR_ALERT=true
echo "1" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID"
return
elif [ "$level" == "WARN" ]; then
_Logger "$prefix\e[33m$value\e[0m" "$prefix$level:$value" "$level:$value"
_Logger "$prefix($level):$value" "$prefix\e[33m$value\e[0m" true
WARN_ALERT=true
echo "1" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.warn.$SCRIPT_PID"
return
elif [ "$level" == "NOTICE" ]; then
if [ "$_LOGGER_ERR_ONLY" != true ]; then
_Logger "$prefix$value"
_Logger "$prefix$value" "$prefix$value"
fi
return
elif [ "$level" == "VERBOSE" ]; then
if [ $_VERBOSE == true ]; then
_Logger "$prefix$value"
if [ $_LOGGER_VERBOSE == true ]; then
_Logger "$prefix:$value" "$prefix$value"
fi
return
elif [ "$level" == "ALWAYS" ]; then
if [ $_SILENT != true ]; then
_Logger "$prefix$value" "$prefix$level:$value" "$level:$value"
fi
_Logger "$prefix$value" "$prefix$value"
return
elif [ "$level" == "DEBUG" ]; then
if [ "$_DEBUG" == "yes" ]; then
_Logger "$prefix$value"
_Logger "$prefix$value" "$prefix$value"
return
fi
elif [ "$level" == "PARANOIA_DEBUG" ]; then #__WITH_PARANOIA_DEBUG
if [ "$_PARANOIA_DEBUG" == "yes" ]; then #__WITH_PARANOIA_DEBUG
_Logger "$prefix$value" #__WITH_PARANOIA_DEBUG
return #__WITH_PARANOIA_DEBUG
fi #__WITH_PARANOIA_DEBUG
elif [ "$level" == "PARANOIA_DEBUG" ]; then #__WITH_PARANOIA_DEBUG
if [ "$_PARANOIA_DEBUG" == "yes" ]; then #__WITH_PARANOIA_DEBUG
_Logger "$prefix$value" "$prefix$value" #__WITH_PARANOIA_DEBUG
return #__WITH_PARANOIA_DEBUG
fi #__WITH_PARANOIA_DEBUG
else
_Logger "\e[41mLogger function called without proper loglevel [$level].\e[0m"
_Logger "Value was: $prefix$value"
@ -242,7 +261,7 @@ function QuickLogger {
__CheckArguments 1 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG
if [ $_SILENT == true ]; then
if [ $_LOGGER_SILENT == true ]; then
_QuickLogger "$value" "log"
else
_QuickLogger "$value" "stdout"
@ -305,10 +324,10 @@ function SendAlert {
__CheckArguments 0-1 $# ${FUNCNAME[0]} "$@" #__WITH_PARANOIA_DEBUG
local attachment=
local attachmentFile=
local subject=
local body=
local attachment
local attachmentFile
local subject
local body
if [ "$DESTINATION_MAILS" == "" ]; then
return 0
@ -333,7 +352,9 @@ function SendAlert {
else
attachment=true
fi
body="$MAIL_ALERT_MSG"$'\n\n'"$CURRENT_LOG"
if [ -e "$RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID" ]; then
body="$MAIL_ALERT_MSG"$'\n\n'"$(cat $RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID)"
fi
if [ $ERROR_ALERT == true ]; then
subject="Error alert for $INSTANCE_ID"
@ -521,7 +542,7 @@ function TrapError {
local line="$1"
local code="${2:-1}"
if [ $_SILENT == false ]; then
if [ $_LOGGER_SILENT == false ]; then
echo -e "\e[45m/!\ ERROR in ${job}: Near line ${line}, exit code ${code}\e[0m"
fi
}
@ -548,7 +569,7 @@ function LoadConfigFile {
}
function Spinner {
if [ $_SILENT == true ] || [ "$_LOGGER_ERR_ONLY" == true ]; then
if [ $_LOGGER_SILENT == true ] || [ "$_LOGGER_ERR_ONLY" == true ]; then
return 0
fi
@ -1091,7 +1112,7 @@ function RunLocalCommand {
Logger "Command failed." "ERROR"
fi
if [ $_VERBOSE == true ] || [ $retval -ne 0 ]; then
if [ $_LOGGER_VERBOSE == true ] || [ $retval -ne 0 ]; then
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE"
fi
@ -1126,7 +1147,7 @@ function RunRemoteCommand {
Logger "Command failed." "ERROR"
fi
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ] && ([ $_VERBOSE == true ] || [ $retval -ne 0 ])
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ] && ([ $_LOGGER_VERBOSE == true ] || [ $retval -ne 0 ])
then
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE"
fi
@ -1622,12 +1643,19 @@ function TrapStop {
function TrapQuit {
local exitcode
# Get ERROR / WARN alert flags from subprocesses that call Logger
if [ -f "$RUN_DIR/$PROGRAM.Logger.warn.$SCRIPT_PID" ]; then
WARN_ALERT=true
fi
if [ -f "$RUN_DIR/$PROGRAM.Logger.error.$SCRIPT_PID" ]; then
ERROR_ALERT=true
fi
if [ $ERROR_ALERT == true ]; then
UnlockReplicas
if [ "$RUN_AFTER_CMD_ON_ERROR" == "yes" ]; then
RunAfterHook
fi
CleanUp
Logger "$PROGRAM finished with errors." "ERROR"
if [ "$_DEBUG" != "yes" ]
then
@ -1641,7 +1669,6 @@ function TrapQuit {
if [ "$RUN_AFTER_CMD_ON_ERROR" == "yes" ]; then
RunAfterHook
fi
CleanUp
Logger "$PROGRAM finished with warnings." "WARN"
if [ "$_DEBUG" != "yes" ]
then
@ -1653,11 +1680,11 @@ function TrapQuit {
else
UnlockReplicas
RunAfterHook
CleanUp
Logger "$PROGRAM finished." "NOTICE"
exitcode=0
fi
CleanUp
KillChilds $$ > /dev/null 2>&1
exit $exitcode
@ -1705,6 +1732,8 @@ function CheckCurrentConfig {
function CheckCurrentConfigAll {
__CheckArguments 0 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
local tmp
if [ "$INSTANCE_ID" == "" ]; then
Logger "No INSTANCE_ID defined in config file." "CRITICAL"
exit 1
@ -1726,9 +1755,13 @@ function CheckCurrentConfigAll {
exit 1
fi
if [ "$SKIP_DELETION" != "" ] && [ $(arrayContains "${INITIATOR[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ] && [ $(arrayContains "${TARGET[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then
Logger "Bogus skip deletion parameter." "CRITICAL"
exit 1
if [ "$SKIP_DELETION" != "" ]; then
tmp="$SKIP_DELETION"
IFS=',' read -r -a SKIP_DELETION <<< "$tmp"
if [ $(arrayContains "${INITIATOR[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ] && [ $(arrayContains "${TARGET[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then
Logger "Bogus skip deletion parameter [$SKIP_DELETION]." "CRITICAL"
exit 1
fi
fi
}
@ -1950,27 +1983,41 @@ function CreateStateDirs {
function _CheckLocksLocal {
local lockfile="${1}"
__CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
local replicaType="${2}"
local lockfile_content
local lock_pid
local lock_instance_id
__CheckArguments 2 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
if [ -f "$lockfile" ]; then
lockfile_content=$(cat $lockfile)
Logger "Master lock pid present: $lockfile_content" "DEBUG"
lock_pid=${lockfile_content%@*}
lock_instance_id=${lockfile_content#*@}
kill -9 $lock_pid > /dev/null 2>&1
local lockfileContent
local lockPid
local lockInstanceID
if [ -s "$lockfile" ]; then
lockfileContent=$(cat $lockfile)
Logger "Master lock pid present: $lockfileContent" "DEBUG"
lockPid=${lockfileContent%@*}
if [ $(IsInteger $lockPid) -ne 1 ]; then
Logger "Invalid pid [$lockPid] in local replica." "CRITICAL"
exit 1
fi
lockInstanceID=${lockfileContent#*@}
if [ "$lockInstanceID" == "" ]; then
Logger "Invalid instance id [$lockInstanceID] in local replica." "CRITICAL"
exit 1
Logger "Local $replicaType lock is: [$lockPid@$lockInstanceID]." "DEBUG"
fi
kill -0 $lockPid > /dev/null 2>&1
if [ $? != 0 ]; then
Logger "There is a dead osync lock in [$lockfile]. Instance [$lock_pid] no longer running. Resuming." "NOTICE"
#rm "$lockfile"
#if [ $? != 0 ]; then
# Logger "Cannot remove lock in [$lockfile]." "CRITICAL"
# exit 1
#fi
Logger "There is a local dead osync lock [$lockPid@$lockInstanceID] that is no longer running. Resuming." "NOTICE"
if [ "$replicaType" == "${INITIATOR[$__type]}" ]; then
# REPLICA_OVERWRITE_LOCK disables noclobber option in WriteLock functions
INITIATOR_OVERWRITE_LOCK=true
elif [ "$replicaType" == "${TARGET[$__type]}" ]; then
TARGET_OVERWRITE_LOCK=true
fi
else
Logger "There is already a local instance of osync running [$lock_pid] for this replica. Cannot start." "CRITICAL"
Logger "There is already a local instance [$lockPid@$lockInstanceID] of osync running for this replica. Cannot start." "CRITICAL"
exit 1
fi
fi
@ -1981,9 +2028,9 @@ function _CheckLocksRemote {
__CheckArguments 1 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
local cmd
local lock_pid
local lock_instance_id
local lockfile_content
local lockPid
local lockInstanceID
local lockfileContent
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
@ -1992,34 +2039,42 @@ function _CheckLocksRemote {
Logger "cmd: $cmd" "DEBUG"
eval "$cmd"
if [ $? != 0 ]; then
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then
lockfile_content=$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)
else
Logger "Cannot get remote lockfile." "CRITICAL"
exit 1
fi
Logger "Cannot check remote replica lock." "CRITICAL"
exit 1
fi
lock_pid=${lockfile_content%@*}
lock_instance_id=${lockfile_content#*@}
if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then
lockfileContent="$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)"
lockPid=${lockfileContent%@*}
if [ $(IsInteger $lockPid) -ne 1 ]; then
Logger "Invalid pid [$lockPid] in remote replica lock." "CRITICAL"
exit 1
fi
lockInstanceID=${lockfileContent#*@}
if [ "$lockInstanceID" == "" ]; then
Logger "Invalid instance id [$lockInstanceID] in remote replica." "CRITICAL"
exit 1
fi
if [ "$lock_pid" != "" ] && [ "$lock_instance_id" != "" ]; then
Logger "Remote lock is: $lock_pid@$lock_instance_id" "DEBUG"
Logger "Remote lock is: [$lockPid@$lockInstanceID]" "DEBUG"
kill -0 $lock_pid > /dev/null 2>&1
kill -0 $lockPid > /dev/null 2>&1
if [ $? != 0 ]; then
if [ "$lock_instance_id" == "$INSTANCE_ID" ]; then
Logger "There is a dead osync lock on target replica that corresponds to this initiator sync id [$lock_instance_id]. Instance [$lock_pid] no longer running. Resuming." "NOTICE"
if [ "$lockInstanceID" == "$INSTANCE_ID" ]; then
Logger "There is a remote dead osync lock [$lockPid@lockInstanceID] on target replica that corresponds to this initiator INSTANCE_ID. Pid [$lockPid] no longer running. Resuming." "NOTICE"
TARGET_OVERWRITE_LOCK=true
else
if [ "$FORCE_STRANGER_LOCK_RESUME" == "yes" ]; then
Logger "WARNING: There is a dead osync lock on target replica that does not correspond to this initiator sync-id [$lock_instance_id]. Forcing resume." "WARN"
Logger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Forcing resume." "WARN"
TARGET_OVERWRITE_LOCK=true
else
Logger "There is a dead osync lock on target replica that does not correspond to this initiator sync-id [$lock_instance_id]. Will not resume." "CRITICAL"
Logger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Will not resume." "CRITICAL"
exit 1
fi
fi
else
Logger "There is already a local instance of osync that locks target replica [$lock_pid@$lock_instance_id]. Cannot start." "CRITICAL"
Logger "There is already a local instance of osync that locks target replica [$lockPid@$lockInstanceID]. Cannot start." "CRITICAL"
exit 1
fi
fi
@ -2041,10 +2096,10 @@ function CheckLocks {
exit 1
fi
else
_CheckLocksLocal "${INITIATOR[$__lockFile]}" &
_CheckLocksLocal "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}" &
pids="$!"
if [ "$REMOTE_OPERATION" != "yes" ]; then
_CheckLocksLocal "${TARGET[$__lockFile]}" &
_CheckLocksLocal "${TARGET[$__lockFile]}" "${INITIATOR[$__type]}" &
pids="$pids;$!"
else
_CheckLocksRemote "${TARGET[$__lockFile]}" &
@ -2062,10 +2117,14 @@ function CheckLocks {
function _WriteLockFilesLocal {
local lockfile="${1}"
local replicaType="${2}"
__CheckArguments 2 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
local overwrite="${3:-false}"
__CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
(
set -o noclobber
if [ $overwrite == true ]; then
set -o noclobber
fi
$COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID"
)
if [ $? != 0 ]; then
@ -2080,19 +2139,23 @@ function _WriteLockFilesLocal {
function _WriteLockFilesRemote {
local lockfile="${1}"
local replicaType="${2}"
__CheckArguments 2 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
local overwrite="${3-false}"
__CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
local cmd
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
cmd=$SSH_CMD' "( set -o noclobber; echo '$SCRIPT_PID@$INSTANCE_ID' | '$COMMAND_SUDO' tee \"'$lockfile'\")" > /dev/null 2> $RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID'
cmd=$SSH_CMD' "( if [ $overwrite == true ]; then set -o noclobber; fi; echo '$SCRIPT_PID@$INSTANCE_ID' | '$COMMAND_SUDO' tee \"'$lockfile'\")" > /dev/null 2> $RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID'
#WIP
#cmd=$SSH_CMD' "( set -o noclobber; echo '$SCRIPT_PID@$INSTANCE_ID' | '$COMMAND_SUDO' tee \"'$lockfile'\")" > /dev/null 2> $RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID'
Logger "cmd: $cmd" "DEBUG"
eval "$cmd"
if [ $? != 0 ]; then
Logger "Could not create lock file on remote $replicaType in [$lockfile]." "CRITICAL"
Loggxer "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$replicaType.$SCRIPT_PID)" "NOTICE"
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$replicaType.$SCRIPT_PID)" "NOTICE"
return 1
else
Logger "Locked remote $replicaType replica in [$lockfile]." "DEBUG"
@ -2107,14 +2170,14 @@ function WriteLockFiles {
local pidArray
local pid
_WriteLockFilesLocal "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}"&
_WriteLockFilesLocal "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}" $INITIATOR_LOCK_OVERWRITE &
initiatorPid="$!"
if [ "$REMOTE_OPERATION" != "yes" ]; then
_WriteLockFilesLocal "${TARGET[$__lockFile]}" "${TARGET[$__type]}" &
_WriteLockFilesLocal "${TARGET[$__lockFile]}" "${TARGET[$__type]}" $TARGET_LOCK_OVERWRITE &
targetPid="$!"
else
_WriteLockFilesRemote "${TARGET[$__lockFile]}" "${TARGET[$__type]}" &
_WriteLockFilesRemote "${TARGET[$__lockFile]}" "${TARGET[$__type]}" $TARGET_LOCK_OVERWRITE &
targetPid="$!"
fi
@ -2212,11 +2275,11 @@ function treeList {
local replicaType="${2}" # replica type: initiator, target
local treeFilename="${3}" # filename to output tree (will be prefixed with $replicaType)
__CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
local escapedReplicaPath
local rsyncCmd
__CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
escapedReplicaPath=$(EscapeSpaces "$replicaPath")
Logger "Creating $replicaType replica file list [$replicaPath]." "NOTICE"
@ -2255,6 +2318,17 @@ function deleteList {
local cmd
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
Logger "Creating $replicaType replica deleted file list." "NOTICE"
if [ -f "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__treeAfterFileNoSuffix]}" ]; then
## Same functionnality, comm is much faster than grep but is not available on every platform
@ -2270,10 +2344,10 @@ function deleteList {
retval=$?
# Add delete failed file list to current delete list and then empty it
if [ -f "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__failedDeletedListFile]}" ]; then
cat "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__failedDeletedListFile]}" >> "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__deletedListFile]}"
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]}"
if [ $? == 0 ]; then
rm -f "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__failedDeletedListFile]}"
rm -f "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$failedDeletionListFromReplica${INITIATOR[$__failedDeletedListFile]}"
else
Logger "Cannot add failed deleted list to current deleted list for replica [$replicaType]." "ERROR"
fi
@ -2635,7 +2709,7 @@ function _deleteRemote {
exit 1
fi
$SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$_DRYRUN _VERBOSE=$_VERBOSE COMMAND_SUDO=$COMMAND_SUDO FILE_LIST="$(EscapeSpaces "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}/$deletionListFromReplica${INITIATOR[$__deletedListFile]}")" REPLICA_DIR="$(EscapeSpaces "$replicaDir")" SOFT_DELETE=$SOFT_DELETE DELETION_DIR="$(EscapeSpaces "$deletionDir")" FAILED_DELETE_LIST="$failedDeleteList" SUCCESS_DELETE_LIST="$successDeleteList" 'bash -s' << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" 2>&1
$SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$_DRYRUN _LOGGER_VERBOSE=$_LOGGER_VERBOSE COMMAND_SUDO=$COMMAND_SUDO FILE_LIST="$(EscapeSpaces "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}/$deletionListFromReplica${INITIATOR[$__deletedListFile]}")" REPLICA_DIR="$(EscapeSpaces "$replicaDir")" SOFT_DELETE=$SOFT_DELETE DELETION_DIR="$(EscapeSpaces "$deletionDir")" FAILED_DELETE_LIST="$failedDeleteList" SUCCESS_DELETE_LIST="$successDeleteList" 'bash -s' << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" 2>&1
## The following lines are executed remotely
function _logger {
@ -2662,7 +2736,7 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$
_logger "$prefix$value"
return
elif [ "$level" == "VERBOSE" ]; then
if [ $_VERBOSE == true ]; then
if [ $_LOGGER_VERBOSE == true ]; then
_logger "$prefix$value"
fi
return
@ -2706,12 +2780,12 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$
# In order to keep full path on soft deletion, create parent directories before move
parentdir="$(dirname "$files")"
if [ "$parentdir" != "." ]; then
Logger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR/$parentdir]." "VERBOSE"
$COMMAND_SUDO mkdir -p "$REPLICA_DIR$DELETION_DIR/$parentdir"
$COMMAND_SUDO mv -f "$REPLICA_DIR$files" "$REPLICA_DIR$DELETION_DIR/$parentdir"
Logger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR/$parentdir]." "VERBOSE"
else
$COMMAND_SUDO mv -f "$REPLICA_DIR$files" "$REPLICA_DIR$DELETION_DIR"
Logger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR]." "VERBOSE"
$COMMAND_SUDO mv -f "$REPLICA_DIR$files" "$REPLICA_DIR$DELETION_DIR"
fi
if [ $? != 0 ]; then
Logger "Cannot move [$REPLICA_DIR$files] to deletion directory." "ERROR"
@ -2725,10 +2799,9 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$
else
if [ $_DRYRUN == false ]; then
if [ -e "$REPLICA_DIR$files" ]; then
$COMMAND_SUDO rm -rf "$REPLICA_DIR$files"
$result=$?
Logger "Deleting [$REPLICA_DIR$files]." "VERBOSE"
if [ $result != 0 ]; then
$COMMAND_SUDO rm -rf "$REPLICA_DIR$files"
if [ $? != 0 ]; then
Logger "Cannot delete [$REPLICA_DIR$files]." "ERROR"
echo "$files" >> "$FAILED_DELETE_LIST"
else
@ -2977,8 +3050,7 @@ function Sync {
## Step 2
if [ "$resumeInitiator" == "${SYNC_ACTION[2]}" ] || [ "$resumeTarget" == "${SYNC_ACTION[2]}" ]; then
#TODO(high) only -X and -A (xattr & acl) should trigger this
if [ "$RSYNC_ATTR_ARGS" != "" ]; then
if [[ "$RSYNC_ATTR_ARGS" == *"-X"* ]] || [[ "$RSYNC_ATTR_ARGS" == *"-A"* ]]; then
syncAttrs "${INITIATOR[$__replicaDir]}" "$TARGET_SYNC_DIR"
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME ${FUNCNAME[0]} false $KEEP_LOGGING
if [ $? != 0 ]; then
@ -3152,7 +3224,7 @@ function _SoftDeleteLocal {
Logger "Removing files older than $changeTime days on $replicaType replica for $deletionType deletion." "NOTICE"
fi
if [ $_VERBOSE == true ]; then
if [ $_LOGGER_VERBOSE == true ]; then
# Cannot launch log function from xargs, ugly hack
$COMMAND_SUDO $FIND_CMD "$replicaDeletionPath/" -type f -ctime +$changeTime -print0 | xargs -0 -I {} echo "Will delete file {}" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID"
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "VERBOSE"
@ -3203,7 +3275,7 @@ function _SoftDeleteRemote {
Logger "Removing files older than $changeTime days on $replicaType replica for $deletionType deletion." "NOTICE"
fi
if [ $_VERBOSE == true ]; then
if [ $_LOGGER_VERBOSE == true ]; then
# Cannot launch log function from xargs, ugly hack
cmd=$SSH_CMD' "if [ -d \"'$replicaDeletionPath'\" ]; then '$COMMAND_SUDO' '$REMOTE_FIND_CMD' \"'$replicaDeletionPath'/\" -type f -ctime +'$changeTime' -print0 | xargs -0 -I {} echo Will delete file {} && '$COMMAND_SUDO' '$REMOTE_FIND_CMD' \"'$replicaDeletionPath'/\" -type d -empty -ctime '$changeTime' -print0 | xargs -0 -I {} echo Will delete directory {}; else echo \"The $replicaType replica dir [$replicaDeletionPath] does not exist. Skipping cleaning of old files.\"; fi" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1'
Logger "cmd: $cmd" "DEBUG"
@ -3269,7 +3341,7 @@ function _SummaryFromFile {
local summaryFile="${2}"
local direction="${3}"
__CheckArguments 2 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
__CheckArguments 3 $# "${FUNCNAME[0]}" "$@" #__WITH_PARANOIA_DEBUG
if [ -f "$summaryFile" ]; then
while read -r file; do
@ -3454,7 +3526,7 @@ function Init {
## Set sync only function arguments for rsync
SYNC_OPTS="-u"
if [ $_VERBOSE == true ] || [ $_SUMMARY == true ]; then
if [ $_LOGGER_VERBOSE == true ] || [ $_SUMMARY == true ]; then
SYNC_OPTS=$SYNC_OPTS" -i"
fi
@ -3467,8 +3539,8 @@ function Init {
## Conflict options
if [ "$CONFLICT_BACKUP" != "no" ]; then
INITIATOR_BACKUP="--backup --backup-dir=\"${INITIATOR[$__replicaDir]}${INITIATOR[$__backupDir]}\""
TARGET_BACKUP="--backup --backup-dir=\"${TARGET[$__replicaDir]}${TARGET[$__backupDir]}\""
INITIATOR_BACKUP="--backup --backup-dir=\"${INITIATOR[$__backupDir]}\""
TARGET_BACKUP="--backup --backup-dir=\"${TARGET[$__backupDir]}\""
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)"
@ -3619,11 +3691,11 @@ for i in "$@"; do
opts=$opts" --dry"
;;
--silent)
_SILENT=true
_LOGGER_SILENT=true
opts=$opts" --silent"
;;
--verbose)
_VERBOSE=true
_LOGGER_VERBOSE=true
opts=$opts" --verbose"
;;
--stats)
@ -3671,20 +3743,17 @@ for i in "$@"; do
;;
--skip-deletion=*)
opts=$opts" --skip-deletion=\"${i##*=}\""
IFS=',' read -r -a SKIP_DELETION <<< ${i##*=}
SKIP_DELETION=${##*=}
;;
--on-changes)
sync_on_changes=true
_NOLOCKS=true
_LOGGER_PREFIX="date"
_LOGGER_STDERR=true
;;
--no-locks)
_NOLOCKS=true
;;
--errors-only)
#TODO: let err_only only output to stderr
#_LOGGER_STDERR=true
_LOGGER_ERR_ONLY=true
;;
--summary)
@ -3739,6 +3808,18 @@ opts="${opts# *}"
HARD_MAX_EXEC_TIME=0
fi
if [ "$PRESERVE_ACL" == "" ]; then
PRESERVE_ACL="yes"
fi
if [ "$PRESERVE_XATTR" == "" ]; then
PRESERVE_XATTR="yes"
fi
if [ "$PATH_SEPARATOR_CHAR" == "" ]; then
PATH_SEPARATOR_CHAR=";"
fi
MIN_WAIT=30
else
ConfigFile="${1}"

@ -1,7 +1,7 @@
#!/usr/bin/env bash
PROGRAM=osync
PROGRAM_VERSION=1.2-beta2
PROGRAM_VERSION=1.2-beta3
PROGRAM_BINARY=$PROGRAM".sh"
PROGRAM_BATCH=$PROGRAM"-batch.sh"
SCRIPT_BUILD=2016111201

@ -3,25 +3,30 @@
PROGRAM="osync" # Rsync based two way sync engine with fault tolerance
AUTHOR="(C) 2013-2016 by Orsiris de Jong"
CONTACT="http://www.netpower.fr/osync - ozy@netpower.fr"
PROGRAM_VERSION=1.2-beta2
PROGRAM_BUILD=2016111502
PROGRAM_VERSION=1.2-beta3
PROGRAM_BUILD=2016111704
IS_STABLE=no
#### MINIMAL-FUNCTION-SET BEGIN ####
## FUNC_BUILD=2016111503
## FUNC_BUILD=2016111705
## BEGIN Generic bash functions written in 2013-2016 by Orsiris de Jong - http://www.netpower.fr - ozy@netpower.fr
## To use in a program, define the following variables:
## PROGRAM=program-name
## INSTANCE_ID=program-instance-name
## _DEBUG=yes/no
## _LOGGER_STDERR=true/false
## _LOGGER_LOGGER_SILENT=true/false
## _LOGGER_LOGGER_VERBOSE=true/false
## _LOGGER_ERR_ONLY=true/false
## _LOGGER_PREFIX="date"/"time"/""
## Logger sets {ERROR|WARN}_ALERT variable when called with critical / error / warn loglevel
## When called from subprocesses, variable of main process can't be set. Status needs to be get via $RUN_DIR/$PROGRAM.Logger.{error|warn}.$SCRIPT_PID
#TODO: Rewrite Logger so we can decide what to send to stdout, stderr and logfile
#TODO: Windows checks, check sendmail & mailsend
if ! type "$BASH" > /dev/null; then
@ -37,10 +42,10 @@ MAIL_ALERT_MSG="Execution of $PROGRAM instance $INSTANCE_ID on $(date) has warni
# Environment variables that can be overriden by programs
_DRYRUN=false
_SILENT=false
_VERBOSE=false
_LOGGER_SILENT=false
_LOGGER_VERBOSE=false
_LOGGER_ERR_ONLY=false
_LOGGER_PREFIX="date"
_LOGGER_STDERR=false
if [ "$KEEP_LOGGING" == "" ]; then
KEEP_LOGGING=1801
fi
@ -49,21 +54,18 @@ fi
ERROR_ALERT=false
WARN_ALERT=false
# Log from current run
CURRENT_LOG=""
## allow debugging from command line with _DEBUG=yes
if [ ! "$_DEBUG" == "yes" ]; then
_DEBUG=no
SLEEP_TIME=.05 # Tested under linux and FreeBSD bash, #TODO tests on cygwin / msys
_VERBOSE=false
_LOGGER_VERBOSE=false
else
if [ "$SLEEP_TIME" == "" ]; then
SLEEP_TIME=1
if [ "$SLEEP_TIME" == "" ]; then # Set SLEEP_TIME as environment variable when runinng with bash -x in order to avoid spamming console
SLEEP_TIME=.05
fi
trap 'TrapError ${LINENO} $?' ERR
_VERBOSE=true
_LOGGER_VERBOSE=true
fi
SCRIPT_PID=$$
@ -109,28 +111,43 @@ function Dummy {
# Sub function of Logger
function _Logger {
local svalue="${1}" # What to log to stdout
local lvalue="${2:-$svalue}" # What to log to logfile, defaults to screen value
local evalue="${3}" # What to log to stderr
local logValue="${1}" # Log to file
local stdValue="${2}" # Log to screeen
local toStderr="${3:-false}" # Log to stderr instead of stdout
echo -e "$logValue" >> "$LOG_FILE"
# Current log file
echo -e "$logValue" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID"
echo -e "$lvalue" >> "$LOG_FILE"
CURRENT_LOG="$CURRENT_LOG"$'\n'"$lvalue"
if [ "$stdValue" != "" ] && [ "$_LOGGER_SILENT" != true ]; then
if [ $toStderr == true ]; then
# Force stderr color in subshell
(>&2 echo -e "$stdValue")
if [ $_LOGGER_STDERR == true ] && [ "$evalue" != "" ]; then
cat <<< "$evalue" 1>&2
elif [ "$_SILENT" == false ]; then
echo -e "$svalue"
else
echo -e "$stdValue"
fi
fi
}
# General log function with log levels:
# CRITICAL, ERROR, WARN are colored in stdout, prefixed in stderr
# NOTICE is standard level
# VERBOSE is only sent to stdout / stderr if _VERBOSE=true
# DEBUG & PARANOIA_DEBUG are only sent if _DEBUG=yes
# Environment variables
# _LOGGER_SILENT: Disables any output to stdout & stderr
# _LOGGER_STD_ERR: Disables any output to stdout except for ALWAYS loglevel
# _LOGGER_VERBOSE: Allows VERBOSE loglevel messages to be sent to stdout
# Loglevels
# Except for VERBOSE, all loglevels are ALWAYS sent to log file
# CRITICAL, ERROR, WARN sent to stderr, color depending on level, level also logged
# NOTICE sent to stdout
# VERBOSE sent to stdout if _LOGGER_VERBOSE = true
# ALWAYS is sent to stdout unless _LOGGER_SILENT = true
# DEBUG & PARANOIA_DEBUG are only sent to stdout if _DEBUG=yes
function Logger {
local value="${1}" # Sentence to log (in double quotes)
local level="${2}" # Log level: PARANOIA_DEBUG, DEBUG, VERBOSE, NOTICE, WARN, ERROR, CRITIAL
local level="${2}" # Log level
if [ "$_LOGGER_PREFIX" == "time" ]; then
prefix="TIME: $SECONDS - "
@ -141,35 +158,37 @@ function Logger {
fi
if [ "$level" == "CRITICAL" ]; then
_Logger "$prefix\e[41m$value\e[0m" "$prefix$level:$value" "$level:$value"
_Logger "$prefix($level):$value" "$prefix\e[41m$value\e[0m" true
ERROR_ALERT=true
# ERROR_ALERT / WARN_ALERT isn't set in main when Logger is called from a subprocess. Need to keep this flag.
echo "1" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID"
return
elif [ "$level" == "ERROR" ]; then
_Logger "$prefix\e[91m$value\e[0m" "$prefix$level:$value" "$level:$value"
_Logger "$prefix($level):$value" "$prefix\e[91m$value\e[0m" true
ERROR_ALERT=true
echo "1" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.error.$SCRIPT_PID"
return
elif [ "$level" == "WARN" ]; then
_Logger "$prefix\e[33m$value\e[0m" "$prefix$level:$value" "$level:$value"
_Logger "$prefix($level):$value" "$prefix\e[33m$value\e[0m" true
WARN_ALERT=true
echo "1" > "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.warn.$SCRIPT_PID"
return
elif [ "$level" == "NOTICE" ]; then
if [ "$_LOGGER_ERR_ONLY" != true ]; then
_Logger "$prefix$value"
_Logger "$prefix$value" "$prefix$value"
fi
return
elif [ "$level" == "VERBOSE" ]; then
if [ $_VERBOSE == true ]; then
_Logger "$prefix$value"
if [ $_LOGGER_VERBOSE == true ]; then
_Logger "$prefix:$value" "$prefix$value"
fi
return
elif [ "$level" == "ALWAYS" ]; then
if [ $_SILENT != true ]; then
_Logger "$prefix$value" "$prefix$level:$value" "$level:$value"
fi
_Logger "$prefix$value" "$prefix$value"
return
elif [ "$level" == "DEBUG" ]; then
if [ "$_DEBUG" == "yes" ]; then
_Logger "$prefix$value"
_Logger "$prefix$value" "$prefix$value"
return
fi
else
@ -196,7 +215,7 @@ function QuickLogger {
local value="${1}"
if [ $_SILENT == true ]; then
if [ $_LOGGER_SILENT == true ]; then
_QuickLogger "$value" "log"
else
_QuickLogger "$value" "stdout"
@ -256,10 +275,10 @@ function SendAlert {
local runAlert="${1:-false}" # Specifies if current message is sent while running or at the end of a run
local attachment=
local attachmentFile=
local subject=
local body=
local attachment
local attachmentFile
local subject
local body
if [ "$DESTINATION_MAILS" == "" ]; then
return 0
@ -284,7 +303,9 @@ function SendAlert {
else
attachment=true
fi
body="$MAIL_ALERT_MSG"$'\n\n'"$CURRENT_LOG"
if [ -e "$RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID" ]; then
body="$MAIL_ALERT_MSG"$'\n\n'"$(cat $RUN_DIR/$PROGRAM._Logger.$SCRIPT_PID)"
fi
if [ $ERROR_ALERT == true ]; then
subject="Error alert for $INSTANCE_ID"
@ -471,7 +492,7 @@ function TrapError {
local line="$1"
local code="${2:-1}"
if [ $_SILENT == false ]; then
if [ $_LOGGER_SILENT == false ]; then
echo -e "\e[45m/!\ ERROR in ${job}: Near line ${line}, exit code ${code}\e[0m"
fi
}
@ -497,7 +518,7 @@ function LoadConfigFile {
}
function Spinner {
if [ $_SILENT == true ] || [ "$_LOGGER_ERR_ONLY" == true ]; then
if [ $_LOGGER_SILENT == true ] || [ "$_LOGGER_ERR_ONLY" == true ]; then
return 0
fi
@ -1022,7 +1043,7 @@ function RunLocalCommand {
Logger "Command failed." "ERROR"
fi
if [ $_VERBOSE == true ] || [ $retval -ne 0 ]; then
if [ $_LOGGER_VERBOSE == true ] || [ $retval -ne 0 ]; then
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE"
fi
@ -1056,7 +1077,7 @@ function RunRemoteCommand {
Logger "Command failed." "ERROR"
fi
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ] && ([ $_VERBOSE == true ] || [ $retval -ne 0 ])
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ] && ([ $_LOGGER_VERBOSE == true ] || [ $retval -ne 0 ])
then
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "NOTICE"
fi
@ -1492,12 +1513,19 @@ function TrapStop {
function TrapQuit {
local exitcode
# Get ERROR / WARN alert flags from subprocesses that call Logger
if [ -f "$RUN_DIR/$PROGRAM.Logger.warn.$SCRIPT_PID" ]; then
WARN_ALERT=true
fi
if [ -f "$RUN_DIR/$PROGRAM.Logger.error.$SCRIPT_PID" ]; then
ERROR_ALERT=true
fi
if [ $ERROR_ALERT == true ]; then
UnlockReplicas
if [ "$RUN_AFTER_CMD_ON_ERROR" == "yes" ]; then
RunAfterHook
fi
CleanUp
Logger "$PROGRAM finished with errors." "ERROR"
if [ "$_DEBUG" != "yes" ]
then
@ -1511,7 +1539,6 @@ function TrapQuit {
if [ "$RUN_AFTER_CMD_ON_ERROR" == "yes" ]; then
RunAfterHook
fi
CleanUp
Logger "$PROGRAM finished with warnings." "WARN"
if [ "$_DEBUG" != "yes" ]
then
@ -1523,11 +1550,11 @@ function TrapQuit {
else
UnlockReplicas
RunAfterHook
CleanUp
Logger "$PROGRAM finished." "NOTICE"
exitcode=0
fi
CleanUp
KillChilds $$ > /dev/null 2>&1
exit $exitcode
@ -1572,6 +1599,8 @@ function CheckCurrentConfig {
function CheckCurrentConfigAll {
local tmp
if [ "$INSTANCE_ID" == "" ]; then
Logger "No INSTANCE_ID defined in config file." "CRITICAL"
exit 1
@ -1593,9 +1622,13 @@ function CheckCurrentConfigAll {
exit 1
fi
if [ "$SKIP_DELETION" != "" ] && [ $(arrayContains "${INITIATOR[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ] && [ $(arrayContains "${TARGET[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then
Logger "Bogus skip deletion parameter." "CRITICAL"
exit 1
if [ "$SKIP_DELETION" != "" ]; then
tmp="$SKIP_DELETION"
IFS=',' read -r -a SKIP_DELETION <<< "$tmp"
if [ $(arrayContains "${INITIATOR[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ] && [ $(arrayContains "${TARGET[$__type]}" "${SKIP_DELETION[@]}") -eq 0 ]; then
Logger "Bogus skip deletion parameter [$SKIP_DELETION]." "CRITICAL"
exit 1
fi
fi
}
@ -1808,26 +1841,40 @@ function CreateStateDirs {
function _CheckLocksLocal {
local lockfile="${1}"
local replicaType="${2}"
local lockfile_content
local lock_pid
local lock_instance_id
if [ -f "$lockfile" ]; then
lockfile_content=$(cat $lockfile)
Logger "Master lock pid present: $lockfile_content" "DEBUG"
lock_pid=${lockfile_content%@*}
lock_instance_id=${lockfile_content#*@}
kill -9 $lock_pid > /dev/null 2>&1
local lockfileContent
local lockPid
local lockInstanceID
if [ -s "$lockfile" ]; then
lockfileContent=$(cat $lockfile)
Logger "Master lock pid present: $lockfileContent" "DEBUG"
lockPid=${lockfileContent%@*}
if [ $(IsInteger $lockPid) -ne 1 ]; then
Logger "Invalid pid [$lockPid] in local replica." "CRITICAL"
exit 1
fi
lockInstanceID=${lockfileContent#*@}
if [ "$lockInstanceID" == "" ]; then
Logger "Invalid instance id [$lockInstanceID] in local replica." "CRITICAL"
exit 1
Logger "Local $replicaType lock is: [$lockPid@$lockInstanceID]." "DEBUG"
fi
kill -0 $lockPid > /dev/null 2>&1
if [ $? != 0 ]; then
Logger "There is a dead osync lock in [$lockfile]. Instance [$lock_pid] no longer running. Resuming." "NOTICE"
#rm "$lockfile"
#if [ $? != 0 ]; then
# Logger "Cannot remove lock in [$lockfile]." "CRITICAL"
# exit 1
#fi
Logger "There is a local dead osync lock [$lockPid@$lockInstanceID] that is no longer running. Resuming." "NOTICE"
if [ "$replicaType" == "${INITIATOR[$__type]}" ]; then
# REPLICA_OVERWRITE_LOCK disables noclobber option in WriteLock functions
INITIATOR_OVERWRITE_LOCK=true
elif [ "$replicaType" == "${TARGET[$__type]}" ]; then
TARGET_OVERWRITE_LOCK=true
fi
else
Logger "There is already a local instance of osync running [$lock_pid] for this replica. Cannot start." "CRITICAL"
Logger "There is already a local instance [$lockPid@$lockInstanceID] of osync running for this replica. Cannot start." "CRITICAL"
exit 1
fi
fi
@ -1837,9 +1884,9 @@ function _CheckLocksRemote {
local lockfile="${1}"
local cmd
local lock_pid
local lock_instance_id
local lockfile_content
local lockPid
local lockInstanceID
local lockfileContent
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
@ -1848,34 +1895,42 @@ function _CheckLocksRemote {
Logger "cmd: $cmd" "DEBUG"
eval "$cmd"
if [ $? != 0 ]; then
if [ -f "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then
lockfile_content=$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)
else
Logger "Cannot get remote lockfile." "CRITICAL"
exit 1
fi
Logger "Cannot check remote replica lock." "CRITICAL"
exit 1
fi
lock_pid=${lockfile_content%@*}
lock_instance_id=${lockfile_content#*@}
if [ -s "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID" ]; then
lockfileContent="$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)"
if [ "$lock_pid" != "" ] && [ "$lock_instance_id" != "" ]; then
Logger "Remote lock is: $lock_pid@$lock_instance_id" "DEBUG"
lockPid=${lockfileContent%@*}
if [ $(IsInteger $lockPid) -ne 1 ]; then
Logger "Invalid pid [$lockPid] in remote replica lock." "CRITICAL"
exit 1
fi
lockInstanceID=${lockfileContent#*@}
if [ "$lockInstanceID" == "" ]; then
Logger "Invalid instance id [$lockInstanceID] in remote replica." "CRITICAL"
exit 1
fi
kill -0 $lock_pid > /dev/null 2>&1
Logger "Remote lock is: [$lockPid@$lockInstanceID]" "DEBUG"
kill -0 $lockPid > /dev/null 2>&1
if [ $? != 0 ]; then
if [ "$lock_instance_id" == "$INSTANCE_ID" ]; then
Logger "There is a dead osync lock on target replica that corresponds to this initiator sync id [$lock_instance_id]. Instance [$lock_pid] no longer running. Resuming." "NOTICE"
if [ "$lockInstanceID" == "$INSTANCE_ID" ]; then
Logger "There is a remote dead osync lock [$lockPid@lockInstanceID] on target replica that corresponds to this initiator INSTANCE_ID. Pid [$lockPid] no longer running. Resuming." "NOTICE"
TARGET_OVERWRITE_LOCK=true
else
if [ "$FORCE_STRANGER_LOCK_RESUME" == "yes" ]; then
Logger "WARNING: There is a dead osync lock on target replica that does not correspond to this initiator sync-id [$lock_instance_id]. Forcing resume." "WARN"
Logger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Forcing resume." "WARN"
TARGET_OVERWRITE_LOCK=true
else
Logger "There is a dead osync lock on target replica that does not correspond to this initiator sync-id [$lock_instance_id]. Will not resume." "CRITICAL"
Logger "There is a remote (maybe dead) osync lock [$lockPid@$lockInstanceID] on target replica that does not correspond to this initiator INSTANCE_ID. Will not resume." "CRITICAL"
exit 1
fi
fi
else
Logger "There is already a local instance of osync that locks target replica [$lock_pid@$lock_instance_id]. Cannot start." "CRITICAL"
Logger "There is already a local instance of osync that locks target replica [$lockPid@$lockInstanceID]. Cannot start." "CRITICAL"
exit 1
fi
fi
@ -1896,10 +1951,10 @@ function CheckLocks {
exit 1
fi
else
_CheckLocksLocal "${INITIATOR[$__lockFile]}" &
_CheckLocksLocal "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}" &
pids="$!"
if [ "$REMOTE_OPERATION" != "yes" ]; then
_CheckLocksLocal "${TARGET[$__lockFile]}" &
_CheckLocksLocal "${TARGET[$__lockFile]}" "${INITIATOR[$__type]}" &
pids="$pids;$!"
else
_CheckLocksRemote "${TARGET[$__lockFile]}" &
@ -1917,9 +1972,13 @@ function CheckLocks {
function _WriteLockFilesLocal {
local lockfile="${1}"
local replicaType="${2}"
local overwrite="${3:-false}"
(
set -o noclobber
if [ $overwrite == true ]; then
set -o noclobber
fi
$COMMAND_SUDO echo "$SCRIPT_PID@$INSTANCE_ID" > "$lockfile" 2> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}-$replicaType.$SCRIPT_PID"
)
if [ $? != 0 ]; then
@ -1934,18 +1993,22 @@ function _WriteLockFilesLocal {
function _WriteLockFilesRemote {
local lockfile="${1}"
local replicaType="${2}"
local overwrite="${3-false}"
local cmd
CheckConnectivity3rdPartyHosts
CheckConnectivityRemoteHost
cmd=$SSH_CMD' "( set -o noclobber; echo '$SCRIPT_PID@$INSTANCE_ID' | '$COMMAND_SUDO' tee \"'$lockfile'\")" > /dev/null 2> $RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID'
cmd=$SSH_CMD' "( if [ $overwrite == true ]; then set -o noclobber; fi; echo '$SCRIPT_PID@$INSTANCE_ID' | '$COMMAND_SUDO' tee \"'$lockfile'\")" > /dev/null 2> $RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID'
#WIP
#cmd=$SSH_CMD' "( set -o noclobber; echo '$SCRIPT_PID@$INSTANCE_ID' | '$COMMAND_SUDO' tee \"'$lockfile'\")" > /dev/null 2> $RUN_DIR/$PROGRAM._WriteLockFilesRemote.$replicaType.$SCRIPT_PID'
Logger "cmd: $cmd" "DEBUG"
eval "$cmd"
if [ $? != 0 ]; then
Logger "Could not create lock file on remote $replicaType in [$lockfile]." "CRITICAL"
Loggxer "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$replicaType.$SCRIPT_PID)" "NOTICE"
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$replicaType.$SCRIPT_PID)" "NOTICE"
return 1
else
Logger "Locked remote $replicaType replica in [$lockfile]." "DEBUG"
@ -1959,14 +2022,14 @@ function WriteLockFiles {
local pidArray
local pid
_WriteLockFilesLocal "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}"&
_WriteLockFilesLocal "${INITIATOR[$__lockFile]}" "${INITIATOR[$__type]}" $INITIATOR_LOCK_OVERWRITE &
initiatorPid="$!"
if [ "$REMOTE_OPERATION" != "yes" ]; then
_WriteLockFilesLocal "${TARGET[$__lockFile]}" "${TARGET[$__type]}" &
_WriteLockFilesLocal "${TARGET[$__lockFile]}" "${TARGET[$__type]}" $TARGET_LOCK_OVERWRITE &
targetPid="$!"
else
_WriteLockFilesRemote "${TARGET[$__lockFile]}" "${TARGET[$__type]}" &
_WriteLockFilesRemote "${TARGET[$__lockFile]}" "${TARGET[$__type]}" $TARGET_LOCK_OVERWRITE &
targetPid="$!"
fi
@ -2061,10 +2124,10 @@ function treeList {
local replicaType="${2}" # replica type: initiator, target
local treeFilename="${3}" # filename to output tree (will be prefixed with $replicaType)
local escapedReplicaPath
local rsyncCmd
escapedReplicaPath=$(EscapeSpaces "$replicaPath")
Logger "Creating $replicaType replica file list [$replicaPath]." "NOTICE"
@ -2102,6 +2165,17 @@ function deleteList {
local cmd
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
Logger "Creating $replicaType replica deleted file list." "NOTICE"
if [ -f "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__treeAfterFileNoSuffix]}" ]; then
## Same functionnality, comm is much faster than grep but is not available on every platform
@ -2117,10 +2191,10 @@ function deleteList {
retval=$?
# Add delete failed file list to current delete list and then empty it
if [ -f "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__failedDeletedListFile]}" ]; then
cat "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__failedDeletedListFile]}" >> "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__deletedListFile]}"
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]}"
if [ $? == 0 ]; then
rm -f "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$replicaType${INITIATOR[$__failedDeletedListFile]}"
rm -f "${INITIATOR[$__replicaDir]}${INITIATOR[$__stateDir]}/$failedDeletionListFromReplica${INITIATOR[$__failedDeletedListFile]}"
else
Logger "Cannot add failed deleted list to current deleted list for replica [$replicaType]." "ERROR"
fi
@ -2476,7 +2550,7 @@ function _deleteRemote {
exit 1
fi
$SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$_DRYRUN _VERBOSE=$_VERBOSE COMMAND_SUDO=$COMMAND_SUDO FILE_LIST="$(EscapeSpaces "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}/$deletionListFromReplica${INITIATOR[$__deletedListFile]}")" REPLICA_DIR="$(EscapeSpaces "$replicaDir")" SOFT_DELETE=$SOFT_DELETE DELETION_DIR="$(EscapeSpaces "$deletionDir")" FAILED_DELETE_LIST="$failedDeleteList" SUCCESS_DELETE_LIST="$successDeleteList" 'bash -s' << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" 2>&1
$SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$_DRYRUN _LOGGER_VERBOSE=$_LOGGER_VERBOSE COMMAND_SUDO=$COMMAND_SUDO FILE_LIST="$(EscapeSpaces "${TARGET[$__replicaDir]}${TARGET[$__stateDir]}/$deletionListFromReplica${INITIATOR[$__deletedListFile]}")" REPLICA_DIR="$(EscapeSpaces "$replicaDir")" SOFT_DELETE=$SOFT_DELETE DELETION_DIR="$(EscapeSpaces "$deletionDir")" FAILED_DELETE_LIST="$failedDeleteList" SUCCESS_DELETE_LIST="$successDeleteList" 'bash -s' << 'ENDSSH' >> "$RUN_DIR/$PROGRAM.remote_deletion.$SCRIPT_PID" 2>&1
## The following lines are executed remotely
function _logger {
@ -2503,7 +2577,7 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$
_logger "$prefix$value"
return
elif [ "$level" == "VERBOSE" ]; then
if [ $_VERBOSE == true ]; then
if [ $_LOGGER_VERBOSE == true ]; then
_logger "$prefix$value"
fi
return
@ -2547,12 +2621,12 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$
# In order to keep full path on soft deletion, create parent directories before move
parentdir="$(dirname "$files")"
if [ "$parentdir" != "." ]; then
Logger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR/$parentdir]." "VERBOSE"
$COMMAND_SUDO mkdir -p "$REPLICA_DIR$DELETION_DIR/$parentdir"
$COMMAND_SUDO mv -f "$REPLICA_DIR$files" "$REPLICA_DIR$DELETION_DIR/$parentdir"
Logger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR/$parentdir]." "VERBOSE"
else
$COMMAND_SUDO mv -f "$REPLICA_DIR$files" "$REPLICA_DIR$DELETION_DIR"
Logger "Moving deleted file [$REPLICA_DIR$files] to [$REPLICA_DIR$DELETION_DIR]." "VERBOSE"
$COMMAND_SUDO mv -f "$REPLICA_DIR$files" "$REPLICA_DIR$DELETION_DIR"
fi
if [ $? != 0 ]; then
Logger "Cannot move [$REPLICA_DIR$files] to deletion directory." "ERROR"
@ -2566,10 +2640,9 @@ $SSH_CMD ERROR_ALERT=0 sync_on_changes=$sync_on_changes _DEBUG=$_DEBUG _DRYRUN=$
else
if [ $_DRYRUN == false ]; then
if [ -e "$REPLICA_DIR$files" ]; then
$COMMAND_SUDO rm -rf "$REPLICA_DIR$files"
$result=$?
Logger "Deleting [$REPLICA_DIR$files]." "VERBOSE"
if [ $result != 0 ]; then
$COMMAND_SUDO rm -rf "$REPLICA_DIR$files"
if [ $? != 0 ]; then
Logger "Cannot delete [$REPLICA_DIR$files]." "ERROR"
echo "$files" >> "$FAILED_DELETE_LIST"
else
@ -2816,8 +2889,7 @@ function Sync {
## Step 2
if [ "$resumeInitiator" == "${SYNC_ACTION[2]}" ] || [ "$resumeTarget" == "${SYNC_ACTION[2]}" ]; then
#TODO(high) only -X and -A (xattr & acl) should trigger this
if [ "$RSYNC_ATTR_ARGS" != "" ]; then
if [[ "$RSYNC_ATTR_ARGS" == *"-X"* ]] || [[ "$RSYNC_ATTR_ARGS" == *"-A"* ]]; then
syncAttrs "${INITIATOR[$__replicaDir]}" "$TARGET_SYNC_DIR"
WaitForTaskCompletion $! $SOFT_MAX_EXEC_TIME $HARD_MAX_EXEC_TIME ${FUNCNAME[0]} false $KEEP_LOGGING
if [ $? != 0 ]; then
@ -2990,7 +3062,7 @@ function _SoftDeleteLocal {
Logger "Removing files older than $changeTime days on $replicaType replica for $deletionType deletion." "NOTICE"
fi
if [ $_VERBOSE == true ]; then
if [ $_LOGGER_VERBOSE == true ]; then
# Cannot launch log function from xargs, ugly hack
$COMMAND_SUDO $FIND_CMD "$replicaDeletionPath/" -type f -ctime +$changeTime -print0 | xargs -0 -I {} echo "Will delete file {}" >> "$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID"
Logger "Command output:\n$(cat $RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID)" "VERBOSE"
@ -3040,7 +3112,7 @@ function _SoftDeleteRemote {
Logger "Removing files older than $changeTime days on $replicaType replica for $deletionType deletion." "NOTICE"
fi
if [ $_VERBOSE == true ]; then
if [ $_LOGGER_VERBOSE == true ]; then
# Cannot launch log function from xargs, ugly hack
cmd=$SSH_CMD' "if [ -d \"'$replicaDeletionPath'\" ]; then '$COMMAND_SUDO' '$REMOTE_FIND_CMD' \"'$replicaDeletionPath'/\" -type f -ctime +'$changeTime' -print0 | xargs -0 -I {} echo Will delete file {} && '$COMMAND_SUDO' '$REMOTE_FIND_CMD' \"'$replicaDeletionPath'/\" -type d -empty -ctime '$changeTime' -print0 | xargs -0 -I {} echo Will delete directory {}; else echo \"The $replicaType replica dir [$replicaDeletionPath] does not exist. Skipping cleaning of old files.\"; fi" > "'$RUN_DIR/$PROGRAM.${FUNCNAME[0]}.$SCRIPT_PID'" 2>&1'
Logger "cmd: $cmd" "DEBUG"
@ -3287,7 +3359,7 @@ function Init {
## Set sync only function arguments for rsync
SYNC_OPTS="-u"
if [ $_VERBOSE == true ] || [ $_SUMMARY == true ]; then
if [ $_LOGGER_VERBOSE == true ] || [ $_SUMMARY == true ]; then
SYNC_OPTS=$SYNC_OPTS" -i"
fi
@ -3300,8 +3372,8 @@ function Init {
## Conflict options
if [ "$CONFLICT_BACKUP" != "no" ]; then
INITIATOR_BACKUP="--backup --backup-dir=\"${INITIATOR[$__replicaDir]}${INITIATOR[$__backupDir]}\""
TARGET_BACKUP="--backup --backup-dir=\"${TARGET[$__replicaDir]}${TARGET[$__backupDir]}\""
INITIATOR_BACKUP="--backup --backup-dir=\"${INITIATOR[$__backupDir]}\""
TARGET_BACKUP="--backup --backup-dir=\"${TARGET[$__backupDir]}\""
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)"
@ -3449,11 +3521,11 @@ for i in "$@"; do
opts=$opts" --dry"
;;
--silent)
_SILENT=true
_LOGGER_SILENT=true
opts=$opts" --silent"
;;
--verbose)
_VERBOSE=true
_LOGGER_VERBOSE=true
opts=$opts" --verbose"
;;
--stats)
@ -3501,20 +3573,17 @@ for i in "$@"; do
;;
--skip-deletion=*)
opts=$opts" --skip-deletion=\"${i##*=}\""
IFS=',' read -r -a SKIP_DELETION <<< ${i##*=}
SKIP_DELETION=${##*=}
;;
--on-changes)
sync_on_changes=true
_NOLOCKS=true
_LOGGER_PREFIX="date"
_LOGGER_STDERR=true
;;
--no-locks)
_NOLOCKS=true
;;
--errors-only)
#TODO: let err_only only output to stderr
#_LOGGER_STDERR=true
_LOGGER_ERR_ONLY=true
;;
--summary)
@ -3569,6 +3638,18 @@ opts="${opts# *}"
HARD_MAX_EXEC_TIME=0
fi
if [ "$PRESERVE_ACL" == "" ]; then
PRESERVE_ACL="yes"
fi
if [ "$PRESERVE_XATTR" == "" ]; then
PRESERVE_XATTR="yes"
fi
if [ "$PATH_SEPARATOR_CHAR" == "" ]; then
PATH_SEPARATOR_CHAR=";"
fi
MIN_WAIT=30
else
ConfigFile="${1}"

Loading…
Cancel
Save