mirror of https://github.com/octoleo/lsyncd.git
Added 'delete=false' flag. if deleting set rsync to force it (otherwise this could result in some deletes not being transfered in the tests
This commit is contained in:
parent
f172c69dee
commit
770d1880d6
|
@ -12,6 +12,8 @@
|
||||||
fix: a series of typos in comments, manpage etc.
|
fix: a series of typos in comments, manpage etc.
|
||||||
fix: moves to and from deleted directories (deleted when Lsyncd gets notified)
|
fix: moves to and from deleted directories (deleted when Lsyncd gets notified)
|
||||||
were not correctly translated
|
were not correctly translated
|
||||||
|
fix: added --ignore-errors to rsync when deleting files, so it will not miss a delete
|
||||||
|
even when another part of the tree made an IO-error.
|
||||||
change: complain if any "rsyncOps" is given
|
change: complain if any "rsyncOps" is given
|
||||||
change: splitted the default configurations in their own files.
|
change: splitted the default configurations in their own files.
|
||||||
more cleanly seperated from the Lsyncd runner, and highlights it are just
|
more cleanly seperated from the Lsyncd runner, and highlights it are just
|
||||||
|
@ -19,6 +21,10 @@
|
||||||
change: Beautified the code, no extra spaces at line end, ' instead of ",
|
change: Beautified the code, no extra spaces at line end, ' instead of ",
|
||||||
supposing 100 char width to view,
|
supposing 100 char width to view,
|
||||||
change: Lsyncd now remembers the absolute path of its config file during HUPs
|
change: Lsyncd now remembers the absolute path of its config file during HUPs
|
||||||
|
enhancement: Defaults not respect a 'delete=false' flag when set as parameter to sync{}
|
||||||
|
default.rsync: does not add --delete to rsync
|
||||||
|
default.rsyncssh: does not add --delete to rsync, and does not use rm via ssh tunnel
|
||||||
|
default.direct: does not add --delete to startup rsync and does not use rm
|
||||||
|
|
||||||
25-08-2011: 2.0.5
|
25-08-2011: 2.0.5
|
||||||
fix: Lsyncd will now terminate if it inotify watching exceeds
|
fix: Lsyncd will now terminate if it inotify watching exceeds
|
||||||
|
|
|
@ -2,7 +2,7 @@ Lsyncd -- Live Syncing (Mirror) Daemon
|
||||||
======================================
|
======================================
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
Lsyncd watches a local directory trees event monitor interface (inotify). It aggregates and combines events for a few seconds and then spawns one (or more) process(es) to synchronize the changes. By default this is [rsync](http://rsync.samba.org/). Lsyncd is thus a light-weight live mirror solution that is comparatively easy to install not requiring new filesystems or blockdevices and does not hamper local filesystem performance.
|
Lsyncd watches a local directory trees event monitor interface (inotify or fsevents). It aggregates and combines events for a few seconds and then spawns one (or more) process(es) to synchronize the changes. By default this is [rsync](http://rsync.samba.org/). Lsyncd is thus a light-weight live mirror solution that is comparatively easy to install not requiring new filesystems or blockdevices and does not hamper local filesystem performance.
|
||||||
|
|
||||||
Rsync+ssh is an advanced action configuration that uses a SSH to act file and directory moves directly on the target instead of retransmitting the move destination over the wire.
|
Rsync+ssh is an advanced action configuration that uses a SSH to act file and directory moves directly on the target instead of retransmitting the move destination over the wire.
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ default.direct = {
|
||||||
action = function(inlet)
|
action = function(inlet)
|
||||||
-- gets all events ready for syncing
|
-- gets all events ready for syncing
|
||||||
local event, event2 = inlet.getEvent()
|
local event, event2 = inlet.getEvent()
|
||||||
|
local config = inlet.getConfig()
|
||||||
|
|
||||||
if event.etype == 'Create' then
|
if event.etype == 'Create' then
|
||||||
if event.isdir then
|
if event.isdir then
|
||||||
|
@ -57,6 +58,10 @@ default.direct = {
|
||||||
event.sourcePath
|
event.sourcePath
|
||||||
)
|
)
|
||||||
elseif event.etype == 'Delete' then
|
elseif event.etype == 'Delete' then
|
||||||
|
if not config.delete then
|
||||||
|
inlet.discardEvent(event)
|
||||||
|
end
|
||||||
|
|
||||||
local tp = event.targetPath
|
local tp = event.targetPath
|
||||||
-- extra security check
|
-- extra security check
|
||||||
if tp == '' or tp == '/' or not tp then
|
if tp == '' or tp == '/' or not tp then
|
||||||
|
@ -69,9 +74,11 @@ default.direct = {
|
||||||
if tp == '' or tp == '/' or not tp then
|
if tp == '' or tp == '/' or not tp then
|
||||||
error('Refusing to erase your harddisk!')
|
error('Refusing to erase your harddisk!')
|
||||||
end
|
end
|
||||||
|
local command = '/bin/mv $1 $2 || /bin/rm -rf $1'
|
||||||
|
if not config.delete then command = '/bin/mv $1 $2'; end
|
||||||
spawnShell(
|
spawnShell(
|
||||||
event,
|
event,
|
||||||
'/bin/mv $1 $2 || /bin/rm -rf $1',
|
command,
|
||||||
event.targetPath,
|
event.targetPath,
|
||||||
event2.targetPath)
|
event2.targetPath)
|
||||||
else
|
else
|
||||||
|
@ -151,6 +158,11 @@ default.direct = {
|
||||||
--
|
--
|
||||||
rsyncOpts = '-lts',
|
rsyncOpts = '-lts',
|
||||||
|
|
||||||
|
-----
|
||||||
|
-- By default do deletes.
|
||||||
|
--
|
||||||
|
delete = true,
|
||||||
|
|
||||||
-----
|
-----
|
||||||
-- rsync exit codes
|
-- rsync exit codes
|
||||||
--
|
--
|
||||||
|
|
|
@ -88,11 +88,13 @@ default.rsync = {
|
||||||
local filter0 = table.concat(filterI, '\000')
|
local filter0 = table.concat(filterI, '\000')
|
||||||
log('Normal', 'Calling rsync with filter-list of new/modified files/dirs\n', filterS)
|
log('Normal', 'Calling rsync with filter-list of new/modified files/dirs\n', filterS)
|
||||||
local config = inlet.getConfig()
|
local config = inlet.getConfig()
|
||||||
|
local delete = nil
|
||||||
|
if config.delete then delete = { '--delete', '--ignore-errors' }; end
|
||||||
spawn(elist, config.rsyncBinary,
|
spawn(elist, config.rsyncBinary,
|
||||||
'<', filter0,
|
'<', filter0,
|
||||||
config.rsyncOpts,
|
config.rsyncOpts,
|
||||||
'-r',
|
'-r',
|
||||||
'--delete',
|
delete,
|
||||||
'--force',
|
'--force',
|
||||||
'--from0',
|
'--from0',
|
||||||
'--include-from=-',
|
'--include-from=-',
|
||||||
|
@ -105,13 +107,16 @@ default.rsync = {
|
||||||
-- Spawns the recursive startup sync
|
-- Spawns the recursive startup sync
|
||||||
--
|
--
|
||||||
init = function(event)
|
init = function(event)
|
||||||
local config = event.config;
|
local config = event.config
|
||||||
local inlet = event.inlet;
|
local inlet = event.inlet
|
||||||
local excludes = inlet.getExcludes();
|
local excludes = inlet.getExcludes()
|
||||||
|
local delete = nil
|
||||||
|
if config.delete then delete = { '--delete', '--ignore-errors' }; end
|
||||||
|
|
||||||
if #excludes == 0 then
|
if #excludes == 0 then
|
||||||
log('Normal', 'recursive startup rsync: ', config.source, ' -> ', config.target)
|
log('Normal', 'recursive startup rsync: ', config.source, ' -> ', config.target)
|
||||||
spawn(event, config.rsyncBinary,
|
spawn(event, config.rsyncBinary,
|
||||||
'--delete',
|
delete,
|
||||||
config.rsyncOpts,
|
config.rsyncOpts,
|
||||||
'-r',
|
'-r',
|
||||||
config.source,
|
config.source,
|
||||||
|
@ -123,8 +128,9 @@ default.rsync = {
|
||||||
spawn(event, config.rsyncBinary,
|
spawn(event, config.rsyncBinary,
|
||||||
'<', exS,
|
'<', exS,
|
||||||
'--exclude-from=-',
|
'--exclude-from=-',
|
||||||
'--delete',
|
delete,
|
||||||
config.rsyncOpts, '-r',
|
config.rsyncOpts,
|
||||||
|
'-r',
|
||||||
config.source,
|
config.source,
|
||||||
config.target)
|
config.target)
|
||||||
end
|
end
|
||||||
|
@ -152,6 +158,11 @@ default.rsync = {
|
||||||
-- rsync uses default collect
|
-- rsync uses default collect
|
||||||
----
|
----
|
||||||
|
|
||||||
|
-----
|
||||||
|
-- By default do deletes.
|
||||||
|
--
|
||||||
|
delete = true,
|
||||||
|
|
||||||
-----
|
-----
|
||||||
-- The rsync binary to be called.
|
-- The rsync binary to be called.
|
||||||
--
|
--
|
||||||
|
|
|
@ -43,6 +43,11 @@ default.rsyncssh = {
|
||||||
-- uses ssh to delete files on remote host
|
-- uses ssh to delete files on remote host
|
||||||
-- instead of constructing rsync filters
|
-- instead of constructing rsync filters
|
||||||
if event.etype == 'Delete' then
|
if event.etype == 'Delete' then
|
||||||
|
if not config.delete then
|
||||||
|
inlet.discardEvent(event)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local elist = inlet.getEvents(
|
local elist = inlet.getEvents(
|
||||||
function(e)
|
function(e)
|
||||||
return e.etype == 'Delete'
|
return e.etype == 'Delete'
|
||||||
|
@ -166,12 +171,14 @@ default.rsyncssh = {
|
||||||
local inlet = event.inlet
|
local inlet = event.inlet
|
||||||
local excludes = inlet.getExcludes()
|
local excludes = inlet.getExcludes()
|
||||||
local target = config.host .. ':' .. config.targetdir
|
local target = config.host .. ':' .. config.targetdir
|
||||||
|
local delete = nil
|
||||||
|
if config.delete then delete = { '--delete', '--ignore-errors' }; end
|
||||||
|
|
||||||
if #excludes == 0 then
|
if #excludes == 0 then
|
||||||
log('Normal', 'Recursive startup rsync: ',config.source,' -> ',target)
|
log('Normal', 'Recursive startup rsync: ',config.source,' -> ',target)
|
||||||
spawn(
|
spawn(
|
||||||
event, config.rsyncBinary,
|
event, config.rsyncBinary,
|
||||||
'--delete',
|
delete,
|
||||||
'-r',
|
'-r',
|
||||||
config.rsyncOpts,
|
config.rsyncOpts,
|
||||||
config.source,
|
config.source,
|
||||||
|
@ -185,7 +192,7 @@ default.rsyncssh = {
|
||||||
event, config.rsyncBinary,
|
event, config.rsyncBinary,
|
||||||
'<', exS,
|
'<', exS,
|
||||||
'--exclude-from=-',
|
'--exclude-from=-',
|
||||||
'--delete',
|
delete,
|
||||||
'-r',
|
'-r',
|
||||||
config.rsyncOpts,
|
config.rsyncOpts,
|
||||||
config.source,
|
config.source,
|
||||||
|
@ -236,11 +243,22 @@ default.rsyncssh = {
|
||||||
--
|
--
|
||||||
delay = 15,
|
delay = 15,
|
||||||
|
|
||||||
|
|
||||||
|
-----
|
||||||
|
-- By default do deletes.
|
||||||
|
--
|
||||||
|
delete = true,
|
||||||
|
|
||||||
-----
|
-----
|
||||||
-- rsync exit codes
|
-- rsync exit codes
|
||||||
--
|
--
|
||||||
rsyncExitCodes = default.rsyncExitCodes,
|
rsyncExitCodes = default.rsyncExitCodes,
|
||||||
|
|
||||||
|
-----
|
||||||
|
-- ssh exit codes
|
||||||
|
--
|
||||||
|
sshExitCodes = default.sshExitCodes,
|
||||||
|
|
||||||
-----
|
-----
|
||||||
-- Delimiter, the binary and the paramters passed to xargs
|
-- Delimiter, the binary and the paramters passed to xargs
|
||||||
-- xargs is used to delete multiple remote files, when ssh access is
|
-- xargs is used to delete multiple remote files, when ssh access is
|
||||||
|
|
11
lsyncd.c
11
lsyncd.c
|
@ -831,13 +831,20 @@ l_exec(lua_State *L)
|
||||||
int pipefd[2]; // pipe file descriptors
|
int pipefd[2]; // pipe file descriptors
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// expands tables if there are any
|
// expands tables if there are any, removes nils
|
||||||
for(i = 1; i <= lua_gettop(L); i++) {
|
for(i = 1; i <= lua_gettop(L); i++) {
|
||||||
|
if (lua_isnil(L, i)) {
|
||||||
|
lua_remove(L, i);
|
||||||
|
i--;
|
||||||
|
argc--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (lua_istable(L, i)) {
|
if (lua_istable(L, i)) {
|
||||||
int tlen;
|
int tlen;
|
||||||
int it;
|
int it;
|
||||||
// table is now on top of stack
|
|
||||||
lua_checkstack(L, lua_gettop(L) + lua_objlen(L, i) + 1);
|
lua_checkstack(L, lua_gettop(L) + lua_objlen(L, i) + 1);
|
||||||
|
// move table to top of stack
|
||||||
lua_pushvalue(L, i);
|
lua_pushvalue(L, i);
|
||||||
lua_remove(L, i);
|
lua_remove(L, i);
|
||||||
argc--;
|
argc--;
|
||||||
|
|
|
@ -2962,17 +2962,18 @@ function spawn(agent, binary, ...)
|
||||||
if agent == nil or type(agent) ~= 'table' then
|
if agent == nil or type(agent) ~= 'table' then
|
||||||
error('spawning with an invalid agent', 2)
|
error('spawning with an invalid agent', 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
if lsyncdStatus == 'fade' then
|
if lsyncdStatus == 'fade' then
|
||||||
log('Normal', 'ignored process spawning while fading')
|
log('Normal', 'ignored process spawning while fading')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(binary) ~= 'string' then
|
if type(binary) ~= 'string' then
|
||||||
error('calling spawn(agent, binary, ...), binary is not a string', 2)
|
error('calling spawn(agent, binary, ...), binary is not a string', 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local dol = InletFactory.getDelayOrList(agent)
|
local dol = InletFactory.getDelayOrList(agent)
|
||||||
if not dol then
|
if not dol then error('spawning with an unknown agent', 2) end
|
||||||
error('spawning with an unknown agent', 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- checks if spawn is called on already active event
|
-- checks if spawn is called on already active event
|
||||||
if dol.status then
|
if dol.status then
|
||||||
|
|
Loading…
Reference in New Issue