mirror of
https://github.com/octoleo/lsyncd.git
synced 2024-09-27 22:49:02 +00:00
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/mci.c
|
||||||
core/mem.c
|
core/mem.c
|
||||||
core/signal.c
|
core/signal.c
|
||||||
|
core/stdin.c
|
||||||
core/time.c
|
core/time.c
|
||||||
core/userobs.c
|
core/userobs.c
|
||||||
core/util.c
|
core/util.c
|
||||||
|
26
ChangeLog
26
ChangeLog
@ -1,13 +1,21 @@
|
|||||||
????-??-??: 3.0.0
|
????-??-??: 3.0.0
|
||||||
change: switched to systemd-style daemon (that is Lsyncd will no longer fork itself)
|
* switching to systemd-style daemon
|
||||||
change: dropping /dev/fsevents hack (OSX support)
|
this means Lsyncd will no longer fork itself
|
||||||
change: dropping exclude and excludeFrom (replaced by filter and filterFrom)
|
* heavily modularized source code
|
||||||
change: "insist" by default
|
* dropping /dev/fsevents hack
|
||||||
change: removed _extra (if someone is hacky enough to really need it,
|
this means, no more OSX support, sorry
|
||||||
they can hack Lsyncd itself)
|
* "insist" by default and no longer an option
|
||||||
change: user scripts run in their own global lua environment
|
* remove the command line configs -rsync -rsyncssh and -direct
|
||||||
change: removed _merge
|
* allowing multiple config files in the command line
|
||||||
change: moved the default layer 1 functions to default.proto
|
* 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
|
2018-03-09: 2.2.3
|
||||||
enhaencement: supporting includes with new filter and filterFrom options
|
enhaencement: supporting includes with new filter and filterFrom options
|
||||||
|
80
core/main.c
80
core/main.c
@ -8,27 +8,13 @@
|
|||||||
*/
|
*/
|
||||||
#include "feature.h"
|
#include "feature.h"
|
||||||
|
|
||||||
// FIXME remove unneeded headers
|
|
||||||
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/times.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <math.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define LUA_USE_APICHECK 1
|
#define LUA_USE_APICHECK 1
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
@ -95,12 +81,6 @@ struct settings settings = {
|
|||||||
bool no_output = false;
|
bool no_output = false;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
| The config file loaded by Lsyncd.
|
|
||||||
*/
|
|
||||||
char * lsyncd_config_file = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
| False after first time Lsyncd started up.
|
| 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( 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 );
|
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
|
// runs initializations from mantle
|
||||||
// it will set the configuration and add watches
|
// it will set the configuration and add watches
|
||||||
{
|
{
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "observe.h"
|
#include "observe.h"
|
||||||
#include "pipe.h"
|
#include "pipe.h"
|
||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
|
#include "stdin.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "userobs.h"
|
#include "userobs.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -673,6 +674,7 @@ static const luaL_Reg corelib[ ] =
|
|||||||
{ "realdir", l_realdir },
|
{ "realdir", l_realdir },
|
||||||
{ "softreset", l_softreset },
|
{ "softreset", l_softreset },
|
||||||
{ "stackdump", l_stackdump },
|
{ "stackdump", l_stackdump },
|
||||||
|
{ "stdin", l_stdin },
|
||||||
{ "terminate", l_terminate },
|
{ "terminate", l_terminate },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
102
core/stdin.c
Normal file
102
core/stdin.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
30
core/stdin.h
Normal file
30
core/stdin.h
Normal file
@ -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
|
@ -114,8 +114,6 @@ proto.collect = function
|
|||||||
|
|
||||||
return 'ok'
|
return 'ok'
|
||||||
elseif rc == 'again'
|
elseif rc == 'again'
|
||||||
then
|
|
||||||
if settings( 'insist' )
|
|
||||||
then
|
then
|
||||||
log(
|
log(
|
||||||
'Normal',
|
'Normal',
|
||||||
@ -125,7 +123,6 @@ proto.collect = function
|
|||||||
)
|
)
|
||||||
|
|
||||||
return 'again'
|
return 'again'
|
||||||
end
|
|
||||||
elseif rc == 'die'
|
elseif rc == 'die'
|
||||||
then
|
then
|
||||||
log(
|
log(
|
||||||
|
@ -94,7 +94,6 @@ init =
|
|||||||
local hup = getsignal( 'HUP' )
|
local hup = getsignal( 'HUP' )
|
||||||
local int = getsignal( 'INT' )
|
local int = getsignal( 'INT' )
|
||||||
local term = getsignal( 'TERM' )
|
local term = getsignal( 'TERM' )
|
||||||
local usr1 = getsignal( 'USR1' )
|
|
||||||
|
|
||||||
if hup ~= false
|
if hup ~= false
|
||||||
then
|
then
|
||||||
@ -103,7 +102,7 @@ init =
|
|||||||
|
|
||||||
if int ~= false
|
if int ~= false
|
||||||
then
|
then
|
||||||
int = makeSignalHandler( 'INT', 'INT', 'terminating', finishInt )
|
int = makeSignalHandler( 'INT', nil, 'terminating', finishInt )
|
||||||
end
|
end
|
||||||
|
|
||||||
if term ~= false
|
if term ~= false
|
||||||
@ -111,11 +110,6 @@ init =
|
|||||||
term = makeSignalHandler( 'TERM', 'TERM', 'terminating', finishTerm )
|
term = makeSignalHandler( 'TERM', 'TERM', 'terminating', finishTerm )
|
||||||
end
|
end
|
||||||
|
|
||||||
if usr1 ~= false
|
onsignal( 'HUP', hup, 'INT', int, 'TERM', term )
|
||||||
then
|
|
||||||
usr1 = makeSignalHandler( 'USR1', nil, 'terminating', finishTerm )
|
|
||||||
end
|
|
||||||
|
|
||||||
onsignal( 'HUP', hup, 'INT', int, 'TERM', term, 'USR1', usr1 )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -222,14 +222,15 @@ function mci.help( )
|
|||||||
[[
|
[[
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
lsyncd [OPTIONS] [CONFIG-FILE]
|
lsyncd [OPTIONS] [CONFIG-FILE(S)]
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
|
-c STRING Executes STRING as Lua config
|
||||||
-delay SECS Overrides default delay times
|
-delay SECS Overrides default delay times
|
||||||
-help Shows this
|
-help Shows this
|
||||||
-log all Logs everything (debug)
|
-log all Logs everything (debug)
|
||||||
-log scarce Logs errors only
|
-log scarce Logs errors only
|
||||||
-log [Category] Turns on logging for a debug category
|
-log CATEGORY Turns on logging for a debug category
|
||||||
-logfile FILE Writes log to FILE (DEFAULT: uses syslog)
|
-logfile FILE Writes log to FILE (DEFAULT: uses syslog)
|
||||||
-version Prints versions and exits
|
-version Prints versions and exits
|
||||||
|
|
||||||
@ -253,11 +254,19 @@ end
|
|||||||
-- terminates on invalid arguments.
|
-- terminates on invalid arguments.
|
||||||
--
|
--
|
||||||
function mci.configure(
|
function mci.configure(
|
||||||
args, -- arguments given by user
|
args, -- command line arguments
|
||||||
monitors -- list of monitors the core can do
|
monitors -- list of monitors the core can do
|
||||||
)
|
)
|
||||||
Monitor.initialize( monitors )
|
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
|
-- a list of all valid options
|
||||||
--
|
--
|
||||||
@ -269,41 +278,22 @@ function mci.configure(
|
|||||||
--
|
--
|
||||||
local options =
|
local options =
|
||||||
{
|
{
|
||||||
-- log is handled by core already.
|
c =
|
||||||
|
{ 1, function( string ) table.insert( confs, { command = string, n = i } ) end },
|
||||||
|
|
||||||
delay =
|
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 =
|
logfile =
|
||||||
{
|
{ 1, function( file ) clSettings.logfile = file end },
|
||||||
1,
|
|
||||||
function( file )
|
|
||||||
clSettings.logfile = file
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
version =
|
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
|
while i <= #args
|
||||||
do
|
do
|
||||||
@ -311,20 +301,18 @@ function mci.configure(
|
|||||||
|
|
||||||
if a:sub( 1, 1 ) ~= '-'
|
if a:sub( 1, 1 ) ~= '-'
|
||||||
then
|
then
|
||||||
table.insert( nonopts, args[ i ] )
|
table.insert( confs, { file = args[ i ] } )
|
||||||
else
|
elseif a == '-'
|
||||||
if a:sub( 1, 2 ) == '--'
|
|
||||||
then
|
then
|
||||||
a = a:sub( 3 )
|
table.insert( confs, { stdin = true } )
|
||||||
else
|
else
|
||||||
a = a:sub( 2 )
|
if a:sub( 1, 2 ) == '--' then a = a:sub( 3 ) else a = a:sub( 2 ) end
|
||||||
end
|
|
||||||
|
|
||||||
local o = options[ a ]
|
local o = options[ a ]
|
||||||
|
|
||||||
if not o
|
if not o
|
||||||
then
|
then
|
||||||
log( 'Error', 'unknown option command line option ', args[ i ] )
|
log( 'Error', 'unknown command line option ', args[ i ] )
|
||||||
|
|
||||||
os.exit( -1 )
|
os.exit( -1 )
|
||||||
end
|
end
|
||||||
@ -362,18 +350,38 @@ function mci.configure(
|
|||||||
i = i + 1
|
i = i + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if #nonopts == 0
|
if #confs == 0 then mci.help( args[ 0 ] ) end
|
||||||
|
|
||||||
|
for _, conf in ipairs( confs )
|
||||||
|
do
|
||||||
|
local f, err, status
|
||||||
|
|
||||||
|
if conf.stdin
|
||||||
then
|
then
|
||||||
mci.help( args[ 0 ] )
|
f, err = load( core.stdin( ), 'stdin', 't', userenv )
|
||||||
elseif #nonopts == 1
|
elseif conf.command
|
||||||
then
|
then
|
||||||
return nonopts[ 1 ]
|
f, err = load( conf.command, 'arg: '..conf.n, 't', userenv )
|
||||||
else
|
else
|
||||||
-- TODO make this possible
|
f, err = loadfile( conf.file, 't', userenv )
|
||||||
log( 'Error', 'There can only be one config file in the command line.' )
|
end
|
||||||
|
|
||||||
|
if not f
|
||||||
|
then
|
||||||
|
log( 'Error', err )
|
||||||
|
|
||||||
os.exit( -1 )
|
os.exit( -1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
status, err = pcall( f )
|
||||||
|
|
||||||
|
if not status
|
||||||
|
then
|
||||||
|
log( 'Error', err )
|
||||||
|
|
||||||
|
os.exit( -1 )
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user