mirror of https://github.com/octoleo/lsyncd.git
allowing multiple config files, allowing stdin as config, allowing commandline commands as configs
This commit is contained in:
parent
4d9f3d9f7e
commit
d0c6770b7c
|
@ -24,6 +24,7 @@ set( LSYNCD_SRC
|
|||
core/mci.c
|
||||
core/mem.c
|
||||
core/signal.c
|
||||
core/stdin.c
|
||||
core/time.c
|
||||
core/userobs.c
|
||||
core/util.c
|
||||
|
|
26
ChangeLog
26
ChangeLog
|
@ -1,13 +1,21 @@
|
|||
????-??-??: 3.0.0
|
||||
change: switched to systemd-style daemon (that is Lsyncd will no longer fork itself)
|
||||
change: dropping /dev/fsevents hack (OSX support)
|
||||
change: dropping exclude and excludeFrom (replaced by filter and filterFrom)
|
||||
change: "insist" by default
|
||||
change: removed _extra (if someone is hacky enough to really need it,
|
||||
they can hack Lsyncd itself)
|
||||
change: user scripts run in their own global lua environment
|
||||
change: removed _merge
|
||||
change: moved the default layer 1 functions to default.proto
|
||||
* switching to systemd-style daemon
|
||||
this means Lsyncd will no longer fork itself
|
||||
* heavily modularized source code
|
||||
* dropping /dev/fsevents hack
|
||||
this means, no more OSX support, sorry
|
||||
* "insist" by default and no longer an option
|
||||
* remove the command line configs -rsync -rsyncssh and -direct
|
||||
* allowing multiple config files in the command line
|
||||
* allowing "-" to read config from stdin
|
||||
* added "-c" for command line lua configs
|
||||
* removed _extra
|
||||
if someone is hacky enough to really need it, they can hack Lsyncd source themself
|
||||
* added uses overloadable signal handling
|
||||
* signal TERM is forwarded to (rsync) subprocesses
|
||||
* user scripts run in their own lua environment
|
||||
* removed _merge inheritance template
|
||||
* moved the default layer 1 functions to default.proto
|
||||
|
||||
2018-03-09: 2.2.3
|
||||
enhaencement: supporting includes with new filter and filterFrom options
|
||||
|
|
82
core/main.c
82
core/main.c
|
@ -8,27 +8,13 @@
|
|||
*/
|
||||
#include "feature.h"
|
||||
|
||||
// FIXME remove unneeded headers
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <syslog.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LUA_USE_APICHECK 1
|
||||
#include <lua.h>
|
||||
|
@ -46,7 +32,7 @@
|
|||
#include "userobs.h"
|
||||
|
||||
#ifdef WITH_INOTIFY
|
||||
#include "inotify.h"
|
||||
# include "inotify.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -95,12 +81,6 @@ struct settings settings = {
|
|||
bool no_output = false;
|
||||
|
||||
|
||||
/*
|
||||
| The config file loaded by Lsyncd.
|
||||
*/
|
||||
char * lsyncd_config_file = NULL;
|
||||
|
||||
|
||||
/*
|
||||
| False after first time Lsyncd started up.
|
||||
|
|
||||
|
@ -376,69 +356,9 @@ main1( int argc, char *argv[] )
|
|||
|
||||
if( lua_pcall( L, 2, 1, -4 ) ) exit( -1 );
|
||||
|
||||
if( first_time )
|
||||
{
|
||||
// If not first time, simply retains the config file given
|
||||
s = lua_tostring( L, -1 );
|
||||
|
||||
if( s ) lsyncd_config_file = s_strdup( s );
|
||||
}
|
||||
|
||||
lua_pop( L, 2 );
|
||||
}
|
||||
|
||||
// checks existence of the config file
|
||||
if( lsyncd_config_file )
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
// gets the absolute path to the config file
|
||||
// so in case of HUPing the daemon, it finds it again
|
||||
char * apath = get_realpath( lsyncd_config_file );
|
||||
if( !apath )
|
||||
{
|
||||
printlogf( L, "Error", "Cannot find config file at '%s'.", lsyncd_config_file );
|
||||
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
free( lsyncd_config_file );
|
||||
|
||||
lsyncd_config_file = apath;
|
||||
|
||||
if( stat( lsyncd_config_file, &st ) )
|
||||
{
|
||||
printlogf( L, "Error", "Cannot find config file at '%s'.", lsyncd_config_file );
|
||||
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
// loads and executes the config file
|
||||
if( luaL_loadfile( L, lsyncd_config_file ) )
|
||||
{
|
||||
printlogf(
|
||||
L, "Error",
|
||||
"error loading %s: %s", lsyncd_config_file, lua_tostring( L, -1 )
|
||||
);
|
||||
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
// loads the user enivornment
|
||||
lua_getglobal( L, "userenv" );
|
||||
lua_setupvalue( L, -2, 1 );
|
||||
|
||||
if( lua_pcall( L, 0, LUA_MULTRET, 0) )
|
||||
{
|
||||
printlogf(
|
||||
L, "Error",
|
||||
"error preparing %s: %s", lsyncd_config_file, lua_tostring( L, -1 )
|
||||
);
|
||||
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
// runs initializations from mantle
|
||||
// it will set the configuration and add watches
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "observe.h"
|
||||
#include "pipe.h"
|
||||
#include "signal.h"
|
||||
#include "stdin.h"
|
||||
#include "time.h"
|
||||
#include "userobs.h"
|
||||
#include "util.h"
|
||||
|
@ -673,6 +674,7 @@ static const luaL_Reg corelib[ ] =
|
|||
{ "realdir", l_realdir },
|
||||
{ "softreset", l_softreset },
|
||||
{ "stackdump", l_stackdump },
|
||||
{ "stdin", l_stdin },
|
||||
{ "terminate", l_terminate },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
| stdin.c from Lsyncd -- the Live (Mirror) Syncing Demon
|
||||
|
|
||||
| Reads a config file from stdin and buffers it.
|
||||
|
|
||||
| On every run of Lsyncd a config file from stdin is
|
||||
| read only once, in case of a HUP soft reset the buffered
|
||||
| version is used.
|
||||
|
|
||||
| License: GPLv2 (see COPYING) or any later version
|
||||
| Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
*/
|
||||
#include "feature.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define LUA_USE_APICHECK 1
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
/*
|
||||
| Stdin read buffer.
|
||||
*/
|
||||
static char * buf = NULL;
|
||||
|
||||
|
||||
/*
|
||||
| Size of stdin buffer.
|
||||
*/
|
||||
static size_t bsize = 0;
|
||||
|
||||
|
||||
/*
|
||||
| Bytes read from stdin
|
||||
*/
|
||||
static size_t bread = 0;
|
||||
|
||||
|
||||
/*
|
||||
| Reads a config file from stdin.
|
||||
| Or returns an already read file.
|
||||
*/
|
||||
char const *
|
||||
read_stdin(
|
||||
lua_State *L
|
||||
)
|
||||
{
|
||||
if( buf ) return buf;
|
||||
|
||||
bsize = 1024;
|
||||
buf = s_malloc( bsize );
|
||||
|
||||
while( true )
|
||||
{
|
||||
bread += fread( buf + bread, 1, bsize - bread - 1, stdin );
|
||||
|
||||
if( ferror( stdin ) )
|
||||
{
|
||||
printlogf( L, "Error", "Failure reading stdin" );
|
||||
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
if( feof( stdin ) ) break;
|
||||
|
||||
if( bsize - bread < 1024 ) buf = s_realloc( buf, bsize *= 2 );
|
||||
}
|
||||
|
||||
buf[ bread ] = 0;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
| Lua wrapper to read_stdin( ).
|
||||
|
|
||||
| Params on Lua stack:
|
||||
| none
|
||||
|
|
||||
| Returns on Lua stack:
|
||||
| the config file
|
||||
*/
|
||||
int
|
||||
l_stdin(
|
||||
lua_State *L
|
||||
)
|
||||
{
|
||||
char const * b = read_stdin( L );
|
||||
|
||||
lua_pushstring( L, b );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
| stdinh from Lsyncd -- the Live (Mirror) Syncing Demon
|
||||
|
|
||||
| Reads a config file from stdin and buffers it.
|
||||
|
|
||||
| On every run of Lsyncd a config file from stdin is
|
||||
| read only once, in case of a HUP soft reset the buffered
|
||||
| version is used.
|
||||
|
|
||||
| License: GPLv2 (see COPYING) or any later version
|
||||
| Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
*/
|
||||
#ifndef LSYNCD_STDIN_H
|
||||
#define LSYNCD_STDIN_H
|
||||
|
||||
|
||||
/*
|
||||
| Reads a config file from stdin.
|
||||
| Or returns an already read file.
|
||||
*/
|
||||
extern char const * read_stdin( lua_State *L );
|
||||
|
||||
|
||||
/*
|
||||
| Lua wrapper to read_stdin( ).
|
||||
*/
|
||||
extern int l_stdin( lua_State *L );
|
||||
|
||||
|
||||
#endif
|
|
@ -115,17 +115,14 @@ proto.collect = function
|
|||
return 'ok'
|
||||
elseif rc == 'again'
|
||||
then
|
||||
if settings( 'insist' )
|
||||
then
|
||||
log(
|
||||
'Normal',
|
||||
'Retrying startup of ',
|
||||
agent.source, ' -> ', agent.target,
|
||||
': ', exitcode
|
||||
)
|
||||
log(
|
||||
'Normal',
|
||||
'Retrying startup of ',
|
||||
agent.source, ' -> ', agent.target,
|
||||
': ', exitcode
|
||||
)
|
||||
|
||||
return 'again'
|
||||
end
|
||||
return 'again'
|
||||
elseif rc == 'die'
|
||||
then
|
||||
log(
|
||||
|
|
|
@ -94,7 +94,6 @@ init =
|
|||
local hup = getsignal( 'HUP' )
|
||||
local int = getsignal( 'INT' )
|
||||
local term = getsignal( 'TERM' )
|
||||
local usr1 = getsignal( 'USR1' )
|
||||
|
||||
if hup ~= false
|
||||
then
|
||||
|
@ -103,7 +102,7 @@ init =
|
|||
|
||||
if int ~= false
|
||||
then
|
||||
int = makeSignalHandler( 'INT', 'INT', 'terminating', finishInt )
|
||||
int = makeSignalHandler( 'INT', nil, 'terminating', finishInt )
|
||||
end
|
||||
|
||||
if term ~= false
|
||||
|
@ -111,11 +110,6 @@ init =
|
|||
term = makeSignalHandler( 'TERM', 'TERM', 'terminating', finishTerm )
|
||||
end
|
||||
|
||||
if usr1 ~= false
|
||||
then
|
||||
usr1 = makeSignalHandler( 'USR1', nil, 'terminating', finishTerm )
|
||||
end
|
||||
|
||||
onsignal( 'HUP', hup, 'INT', int, 'TERM', term, 'USR1', usr1 )
|
||||
onsignal( 'HUP', hup, 'INT', int, 'TERM', term )
|
||||
end
|
||||
|
||||
|
|
120
mantle/mci.lua
120
mantle/mci.lua
|
@ -222,14 +222,15 @@ function mci.help( )
|
|||
[[
|
||||
|
||||
USAGE:
|
||||
lsyncd [OPTIONS] [CONFIG-FILE]
|
||||
lsyncd [OPTIONS] [CONFIG-FILE(S)]
|
||||
|
||||
OPTIONS:
|
||||
-delay SECS Overrides default delay times
|
||||
-c STRING Executes STRING as Lua config
|
||||
-delay SECS Overrides default delay times
|
||||
-help Shows this
|
||||
-log all Logs everything (debug)
|
||||
-log scarce Logs errors only
|
||||
-log [Category] Turns on logging for a debug category
|
||||
-log all Logs everything (debug)
|
||||
-log scarce Logs errors only
|
||||
-log CATEGORY Turns on logging for a debug category
|
||||
-logfile FILE Writes log to FILE (DEFAULT: uses syslog)
|
||||
-version Prints versions and exits
|
||||
|
||||
|
@ -253,11 +254,19 @@ end
|
|||
-- terminates on invalid arguments.
|
||||
--
|
||||
function mci.configure(
|
||||
args, -- arguments given by user
|
||||
args, -- command line arguments
|
||||
monitors -- list of monitors the core can do
|
||||
)
|
||||
Monitor.initialize( monitors )
|
||||
|
||||
-- confs is filled with
|
||||
-- all config file
|
||||
-- stdin read requests
|
||||
-- inline configs
|
||||
local confs = { }
|
||||
|
||||
local i = 1
|
||||
|
||||
--
|
||||
-- a list of all valid options
|
||||
--
|
||||
|
@ -269,62 +278,41 @@ function mci.configure(
|
|||
--
|
||||
local options =
|
||||
{
|
||||
-- log is handled by core already.
|
||||
c =
|
||||
{ 1, function( string ) table.insert( confs, { command = string, n = i } ) end },
|
||||
|
||||
delay =
|
||||
{
|
||||
1,
|
||||
function( secs )
|
||||
clSettings.delay = secs + 0
|
||||
end
|
||||
},
|
||||
{ 1, function( secs ) clSettings.delay = secs + 0 end },
|
||||
|
||||
log = { 1, nil },
|
||||
-- log is handled by core already.
|
||||
log =
|
||||
{ 1, nil },
|
||||
|
||||
logfile =
|
||||
{
|
||||
1,
|
||||
function( file )
|
||||
clSettings.logfile = file
|
||||
end
|
||||
},
|
||||
{ 1, function( file ) clSettings.logfile = file end },
|
||||
|
||||
version =
|
||||
{
|
||||
0,
|
||||
function( )
|
||||
io.stdout:write( 'Version: ', lsyncd_version, '\n' )
|
||||
|
||||
os.exit( 0 )
|
||||
end
|
||||
}
|
||||
{ 0, function( ) io.stdout:write( 'Version: ', lsyncd_version, '\n' ) os.exit( 0 ) end }
|
||||
}
|
||||
|
||||
-- non-opts is filled with all args that were no part dash options
|
||||
local nonopts = { }
|
||||
|
||||
local i = 1
|
||||
|
||||
while i <= #args
|
||||
do
|
||||
local a = args[ i ]
|
||||
|
||||
if a:sub( 1, 1 ) ~= '-'
|
||||
then
|
||||
table.insert( nonopts, args[ i ] )
|
||||
table.insert( confs, { file = args[ i ] } )
|
||||
elseif a == '-'
|
||||
then
|
||||
table.insert( confs, { stdin = true } )
|
||||
else
|
||||
if a:sub( 1, 2 ) == '--'
|
||||
then
|
||||
a = a:sub( 3 )
|
||||
else
|
||||
a = a:sub( 2 )
|
||||
end
|
||||
if a:sub( 1, 2 ) == '--' then a = a:sub( 3 ) else a = a:sub( 2 ) end
|
||||
|
||||
local o = options[ a ]
|
||||
|
||||
if not o
|
||||
then
|
||||
log( 'Error', 'unknown option command line option ', args[ i ] )
|
||||
log( 'Error', 'unknown command line option ', args[ i ] )
|
||||
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
@ -346,33 +334,53 @@ function mci.configure(
|
|||
o[ 2 ]( )
|
||||
elseif o[ 1 ] == 1
|
||||
then
|
||||
o[ 2 ]( args[ i + 1] )
|
||||
o[ 2 ]( args[ i + 1 ] )
|
||||
elseif o[ 1 ] == 2
|
||||
then
|
||||
o[ 2 ]( args[ i + 1], args[ i + 2] )
|
||||
o[ 2 ]( args[ i + 1 ], args[ i + 2 ] )
|
||||
elseif o[ 1 ] == 3
|
||||
then
|
||||
o[ 2 ]( args[ i + 1], args[ i + 2], args[ i + 3] )
|
||||
then
|
||||
o[ 2 ]( args[ i + 1 ], args[ i + 2 ], args[ i + 3 ] )
|
||||
end
|
||||
end
|
||||
|
||||
i = i + o[1]
|
||||
i = i + o[ 1 ]
|
||||
end
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
if #nonopts == 0
|
||||
then
|
||||
mci.help( args[ 0 ] )
|
||||
elseif #nonopts == 1
|
||||
then
|
||||
return nonopts[ 1 ]
|
||||
else
|
||||
-- TODO make this possible
|
||||
log( 'Error', 'There can only be one config file in the command line.' )
|
||||
if #confs == 0 then mci.help( args[ 0 ] ) end
|
||||
|
||||
os.exit( -1 )
|
||||
for _, conf in ipairs( confs )
|
||||
do
|
||||
local f, err, status
|
||||
|
||||
if conf.stdin
|
||||
then
|
||||
f, err = load( core.stdin( ), 'stdin', 't', userenv )
|
||||
elseif conf.command
|
||||
then
|
||||
f, err = load( conf.command, 'arg: '..conf.n, 't', userenv )
|
||||
else
|
||||
f, err = loadfile( conf.file, 't', userenv )
|
||||
end
|
||||
|
||||
if not f
|
||||
then
|
||||
log( 'Error', err )
|
||||
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
status, err = pcall( f )
|
||||
|
||||
if not status
|
||||
then
|
||||
log( 'Error', err )
|
||||
|
||||
os.exit( -1 )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue