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
|
@ -11,7 +11,9 @@
|
||||||
configured correctly.
|
configured correctly.
|
||||||
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.
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ Lsyncd is designed to synchronize a local directory tree with low profile of exp
|
||||||
|
|
||||||
Other synchronization tools
|
Other synchronization tools
|
||||||
------------------------
|
------------------------
|
||||||
[DRBD](http://www.drbd.org) operates on block device level. This makes it useful for synchronizing systems that are under heavy load. Lsyncd on the other hand does not require you to change block devices and/or mount points, allows you to change uid/gid of the transferred files, separates the receiver through the one-way nature of rsync. DRBD is likely the better option if you are syncing Databases.
|
[DRBD](http://www.drbd.org) operates on block device level. This makes it useful for synchronizing systems that are under heavy load. Lsyncd on the other hand does not require you to change block devices and/or mount points, allows you to change uid/gid of the transferred files, separates the receiver through the one-way nature of rsync. DRBD is likely the better option if you are syncing Databases.
|
||||||
|
|
||||||
[GlusterFS](http://www.gluster.org) and [BindFS](http://www.cs.helsinki.fi/u/partel/bindfs/) use a FUSE-Filesystem to interject kernel/userspace filesystem events.
|
[GlusterFS](http://www.gluster.org) and [BindFS](http://www.cs.helsinki.fi/u/partel/bindfs/) use a FUSE-Filesystem to interject kernel/userspace filesystem events.
|
||||||
|
|
||||||
|
@ -36,4 +36,4 @@ Some more complicated examples, tips and tricks you can find in the [Lsyncd20Man
|
||||||
Disclaimer
|
Disclaimer
|
||||||
----------
|
----------
|
||||||
Besides the usual disclaimer in the license, we want to specifically emphasize that neither the authors nor any organization the authors are associated with can and will hold responsible for data-loss caused by possible malfunctions of Lsyncd.
|
Besides the usual disclaimer in the license, we want to specifically emphasize that neither the authors nor any organization the authors are associated with can and will hold responsible for data-loss caused by possible malfunctions of Lsyncd.
|
||||||
|
|
||||||
|
|
|
@ -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