syntax highlighting, improve this

This commit is contained in:
Axel Kittenberger 2016-06-08 09:01:58 +02:00
parent 9a6fe7562e
commit 3274bc0087
14 changed files with 390 additions and 138 deletions

View File

@ -1,9 +1,14 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
{% if page.url != "/" %}
<title>Lsyncd - {{ page.title }}</title>
{% else %}
<title>{{ page.title }}</title> <title>{{ page.title }}</title>
{% endif %}
<!-- link to main stylesheet --> <!-- link to main stylesheet -->
<link rel="stylesheet" type="text/css" href="{{ site.url }}/css/main.css"> <link rel="stylesheet" type="text/css" href="{{ site.url }}/css/main.css">
<link rel="stylesheet" type="text/css" href="{{ site.url }}/css/syntax.css">
</head> </head>
<body> <body>
<div id="pillar"> <div id="pillar">
@ -35,6 +40,7 @@
<div id="ribbonwrap"><a href="https://github.com/axkibe/lsyncd" id="ribbon"></a></div> <div id="ribbonwrap"><a href="https://github.com/axkibe/lsyncd" id="ribbon"></a></div>
</nav> </nav>
<div id="container"> <div id="container">
<a href="https://github.com/axkibe/lsyncd/edit/gh-pages{{ page.url }}index.md" id="improvethis"></a>
<h1>{{ page.title }}</h1> <h1>{{ page.title }}</h1>
{{ content }} {{ content }}
@ -67,11 +73,5 @@
</div> </div>
</div> </div>
<!--footer>
<ul>
<li><a href="https://github.com/lsyncd">github.com/lsyncd</a></li>
</ul>
</footer-->
</body> </body>
</html> </html>

View File

@ -123,10 +123,36 @@ tr:first-child td {
border-top : 1px solid rgb( 220, 220, 220 ) border-top : 1px solid rgb( 220, 220, 220 )
} }
tr td:first-child { tr td:first-child, tr th:first-child {
border-left : 1px solid rgb( 220, 220, 220 ) border-left : 1px solid rgb( 220, 220, 220 )
} }
thead::after {
line-height: 0.4em;
content: "\200C";
display:block;
}
th {
background-color: rgb( 230, 230, 230 );
border-top : 1px solid rgb( 210, 210, 210 );
border-bottom : 1px solid rgb( 210, 210, 210 );
border-right : 1px solid rgb( 210, 210, 210 );
padding : 0.8em 1em;
margin : 0;
font-weight: bold;
}
th:first-child {
border-top-left-radius: 1em;
border-bottom-left-radius: 1em;
}
th:last-child {
border-top-right-radius: 1em;
border-bottom-right-radius: 1em;
}
td { td {
border-bottom : 1px solid rgb( 220, 220, 220 ); border-bottom : 1px solid rgb( 220, 220, 220 );
border-right : 1px solid rgb( 220, 220, 220 ); border-right : 1px solid rgb( 220, 220, 220 );
@ -139,13 +165,6 @@ tr:first-child td:last-child { border-top-right-radius: 1em; }
tr:last-child td:first-child { border-bottom-left-radius: 1em; } tr:last-child td:first-child { border-bottom-left-radius: 1em; }
tr:last-child td:last-child { border-bottom-right-radius: 1em; } tr:last-child td:last-child { border-bottom-right-radius: 1em; }
pre {
background-color: rgb( 245, 245, 245 );
padding: 1em;
border-radius: 1em;
}
#ribbonwrap { #ribbonwrap {
position: absolute; position: absolute;
right: 14.1em; right: 14.1em;
@ -207,7 +226,7 @@ pre {
background-color: rgb( 240, 240, 240 ); background-color: rgb( 240, 240, 240 );
padding: 0.2em 0.8em; padding: 0.2em 0.8em;
border-radius: 0.8em; border-radius: 0.8em;
margin: 0.1em 0 1em 0; margin: 1em 0 1em 0;
} }
.prenext .prev::before { .prenext .prev::before {
@ -219,3 +238,20 @@ pre {
content : "next\00a0\203A\203A"; content : "next\00a0\203A\203A";
float: right; float: right;
} }
#improvethis {
float: right;
color: #bbb;
margin: 1em 0 0 0;
}
#improvethis::before {
content : "\f040\00a0Improve\00a0this\00a0page";
}
.highlighter-rouge {
background-color: #f8f8f8;
border-radius: 0.4em;
padding: 0.1em 0.2em;
}

212
css/syntax.css Normal file
View File

@ -0,0 +1,212 @@
.highlight table td { padding: 5px; }
.highlight table pre { margin: 0; }
.highlight .cm {
color: #999988;
font-style: italic;
}
.highlight .cp {
color: #999999;
font-weight: bold;
}
.highlight .c1 {
color: #999988;
font-style: italic;
}
.highlight .cs {
color: #999999;
font-weight: bold;
font-style: italic;
}
.highlight .c, .highlight .cd {
color: #999988;
font-style: italic;
}
.highlight .err {
color: #a61717;
background-color: #e3d2d2;
}
.highlight .gd {
color: #000000;
background-color: #ffdddd;
}
.highlight .ge {
color: #000000;
font-style: italic;
}
.highlight .gr {
color: #aa0000;
}
.highlight .gh {
color: #999999;
}
.highlight .gi {
color: #000000;
background-color: #ddffdd;
}
.highlight .go {
color: #888888;
}
.highlight .gp {
color: #555555;
}
.highlight .gs {
font-weight: bold;
}
.highlight .gu {
color: #aaaaaa;
}
.highlight .gt {
color: #aa0000;
}
.highlight .kc {
color: #000000;
font-weight: bold;
}
.highlight .kd {
color: #000000;
font-weight: bold;
}
.highlight .kn {
color: #000000;
font-weight: bold;
}
.highlight .kp {
color: #000000;
font-weight: bold;
}
.highlight .kr {
color: #000000;
font-weight: bold;
}
.highlight .kt {
color: #445588;
font-weight: bold;
}
.highlight .k, .highlight .kv {
color: #000000;
font-weight: bold;
}
.highlight .mf {
color: #009999;
}
.highlight .mh {
color: #009999;
}
.highlight .il {
color: #009999;
}
.highlight .mi {
color: #009999;
}
.highlight .mo {
color: #009999;
}
.highlight .m, .highlight .mb, .highlight .mx {
color: #009999;
}
.highlight .sb {
color: #d14;
}
.highlight .sc {
color: #d14;
}
.highlight .sd {
color: #d14;
}
.highlight .s2 {
color: #d14;
}
.highlight .se {
color: #d14;
}
.highlight .sh {
color: #d14;
}
.highlight .si {
color: #d14;
}
.highlight .sx {
color: #d14;
}
.highlight .sr {
color: #009926;
}
.highlight .s1 {
color: #d14;
}
.highlight .ss {
color: #990073;
}
.highlight .s {
color: #d14;
}
.highlight .na {
color: #008080;
}
.highlight .bp {
color: #999999;
}
.highlight .nb {
color: #0086B3;
}
.highlight .nc {
color: #445588;
font-weight: bold;
}
.highlight .no {
color: #008080;
}
.highlight .nd {
color: #3c5d5d;
font-weight: bold;
}
.highlight .ni {
color: #800080;
}
.highlight .ne {
color: #990000;
font-weight: bold;
}
.highlight .nf {
color: #990000;
font-weight: bold;
}
.highlight .nl {
color: #990000;
font-weight: bold;
}
.highlight .nn {
color: #555555;
}
.highlight .nt {
color: #000080;
}
.highlight .vc {
color: #008080;
}
.highlight .vg {
color: #008080;
}
.highlight .vi {
color: #008080;
}
.highlight .nv {
color: #008080;
}
.highlight .ow {
color: #000000;
font-weight: bold;
}
.highlight .o {
color: #000000;
font-weight: bold;
}
.highlight .w {
color: #bbbbbb;
}
.highlight {
background-color: #f8f8f8;
border-radius: 1em;
padding: 0.1em 1em;
margin: 0;
}

View File

@ -8,6 +8,6 @@ Source Tar Ball: [release-2.1.6.tar.gz](https://github.com/axkibe/lsyncd/archive
HEAD Development HEAD Development
================ ================
``` {% highlight shell %}
git clone https://github.com/axkibe/lsyncd.git git clone https://github.com/axkibe/lsyncd.git
``` {% endhighlight %}

View File

@ -1,6 +1,6 @@
--- ---
layout: default layout: default
title: "Lsyncd Live Syncing (Mirror) Daemon" title: "Lsyncd - Live Syncing (Mirror) Daemon"
short: "Welcome" short: "Welcome"
--- ---
Description Description
@ -25,17 +25,19 @@ Other synchronization tools
Lsyncd usage examples Lsyncd usage examples
--------------------- ---------------------
```lsyncd -rsync /home remotehost.org::share/``` {% highlight shell %}
lsyncd -rsync /home remotehost.org::share/
{% endhighlight %}
This watches and rsyncs the local directory /home with all sub-directories and This watches and rsyncs the local directory /home with all sub-directories and
transfers them to 'remotehost' using the rsync-share 'share'. transfers them to 'remotehost' using the rsync-share 'share'.
```lsyncd -rsyncssh /home remotehost.org backup-home/``` {% highlight shell %}
lsyncd -rsyncssh /home remotehost.org backup-home/
{% endhighlight %}
This will also rsync/watch '/home', but it uses a ssh connection to make moves local on the remotehost instead of re-transmitting the moved file over the wire. This will also rsync/watch '/home', but it uses a ssh connection to make moves local on the remotehost instead of re-transmitting the moved file over the wire.
Some more complicated examples, tips and tricks you can find in the [Lsyncd21Manual](https://github.com/axkibe/lsyncd/wiki/Manual-to-Lsyncd-2.1.x).
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.

View File

@ -4,8 +4,8 @@ title: Compiling
--- ---
Building Lsyncd should be a straight forward process. Unpack the downloaded tar.gz file and run: Building Lsyncd should be a straight forward process. Unpack the downloaded tar.gz file and run:
```shell {% highlight shell %}
cmake . cmake .
make make
sudo make install sudo make install
``` {% endhighlight %}

View File

@ -11,13 +11,13 @@ For scripts of all layers, the ```settings``` call can be used to alter daemon-w
For example, the following code will instruct Lsyncd to log into ```/tmp/lsyncd.log```, periodically update the file ```/tmp/lsyncd.status``` with its status and to not detach as a daemon. For example, the following code will instruct Lsyncd to log into ```/tmp/lsyncd.log```, periodically update the file ```/tmp/lsyncd.status``` with its status and to not detach as a daemon.
```Lua {% highlight lua %}
settings { settings {
logfile = "/tmp/lsyncd.log", logfile = "/tmp/lsyncd.log",
statusFile = "/tmp/lsyncd.status", statusFile = "/tmp/lsyncd.status",
nodaemon = true, nodaemon = true,
} }
``` {% endhighlight %}
**Caution** **Caution**
If you are upgrading from 2.0.x, please notice that `settings` became a function from a variable, so you **MUST** delete the equal sign '=' between `settings` and the `{`. If you are upgrading from 2.0.x, please notice that `settings` became a function from a variable, so you **MUST** delete the equal sign '=' between `settings` and the `{`.

View File

@ -7,7 +7,7 @@ Layer 2 allows you to create one process per one event. However, as with default
For example this is the action used by default.rsync: For example this is the action used by default.rsync:
```Lua {% highlight lua %}
action = function(inlet) action = function(inlet)
local elist = inlet.getEvents() local elist = inlet.getEvents()
local config = inlet.getConfig() local config = inlet.getConfig()
@ -20,12 +20,13 @@ action = function(inlet)
"--include-from=-", "--include-from=-",
"--exclude=*", "--exclude=*",
config.source, config.target) config.source, config.target)
``` end
{% endhighlight %}
Inlet functions are: Inlet functions are:
| **Function** | **Description** | | Function | Description |
|:----------|:------------| |:---------|:------------|
| inlet.getEvent() | Retrieves the next `event` as in Layer 2 configuration. Multiple calls to getEvent() will return the same event unless it has spawn{}ed an action. | | inlet.getEvent() | Retrieves the next `event` as in Layer 2 configuration. Multiple calls to getEvent() will return the same event unless it has spawn{}ed an action. |
| inlet.getEvents(test) | Returns a list of all events that are ready. `test` is optional for a function that will be called for every event to test if it should be included in the list. It has one parameter the `event` and returns true if an event should be included. If nil every ready event will be included in the list | | inlet.getEvents(test) | Returns a list of all events that are ready. `test` is optional for a function that will be called for every event to test if it should be included in the list. It has one parameter the `event` and returns true if an event should be included. If nil every ready event will be included in the list |
| inlet.discardEvent() | Discards an event. The next call to getEvent will thus receive another event, even if no action has been spawned for this event | | inlet.discardEvent() | Discards an event. The next call to getEvent will thus receive another event, even if no action has been spawned for this event |
@ -38,7 +39,7 @@ The list returned by getEvents can be handed to spawn{} as _agent_ just as well
Lists have following functions Lists have following functions
| **Function** | **Description** | | Function | Description |
|:----------|:------------| |:----------|:------------|
| elist.getPaths(delimiter) | returns a string of the paths (as in `event.path` separated by `delimiter`. By default \n is used as delimiter. | | elist.getPaths(delimiter) | returns a string of the paths (as in `event.path` separated by `delimiter`. By default \n is used as delimiter. |
| elist.getSourcePaths(delimiter) | returns a string of the sourcePaths (as in `event.sourcePath` separated by `delimiter`. By default \n is used as delimiter. | | elist.getSourcePaths(delimiter) | returns a string of the sourcePaths (as in `event.sourcePath` separated by `delimiter`. By default \n is used as delimiter. |
@ -47,7 +48,7 @@ Take care calling getEvents() and its function since depending on the amount of
Layer 2 functions is nothing else than following layer 1 action loaded by the default if the user script did not provide one itself. Layer 2 functions is nothing else than following layer 1 action loaded by the default if the user script did not provide one itself.
```Lua {% highlight lua %}
----- -----
-- Default action calls user scripts on**** functions. -- Default action calls user scripts on**** functions.
-- --
@ -65,13 +66,13 @@ action = function(inlet)
inlet.discardEvent(event) inlet.discardEvent(event)
end end
end, end,
``` {% endhighlight %}
Lsyncd will automatically split Move events into Create and Delete events if no "onMove" field is found in the config. When handling moves in layer 1 `action` function, simply set "onMove" to be "true". Lsyncd will automatically split Move events into Create and Delete events if no "onMove" field is found in the config. When handling moves in layer 1 `action` function, simply set "onMove" to be "true".
Other than `action` Lsyncd calls `init` for each sync{} on initialization. This is the default init function which is loaded if the user script does not have one. It provides the onStartup() functionality for layer 2 and 3. Other than `action` Lsyncd calls `init` for each sync{} on initialization. This is the default init function which is loaded if the user script does not have one. It provides the onStartup() functionality for layer 2 and 3.
```Lua {% highlight lua %}
----- -----
-- called on (re)initalizing of lsyncd. -- called on (re)initalizing of lsyncd.
-- --
@ -88,11 +89,11 @@ init = function(inlet)
end end
end end
end, end,
``` {% endhighlight %}
As another example this is the init of `default.rsync`. As specialty it changes the configuration in that it adds a slash to target if not there already. As another example this is the init of `default.rsync`. As specialty it changes the configuration in that it adds a slash to target if not there already.
```Lua {% highlight lua %}
----- -----
-- Spawns the recursive startup sync -- Spawns the recursive startup sync
-- --
@ -110,13 +111,13 @@ init = function(inlet)
config.source, config.source,
config.target) config.target)
end, end,
``` {% endhighlight %}
When child processes are finished and their zombie processes are collected, Lsyncd calls the function of the `collect` entry. When collect return "again" the status of the agent (an event or an event list) will be set on "wait" again, and will become ready in `delay` seconds (or 1 second if smaller). When child processes are finished and their zombie processes are collected, Lsyncd calls the function of the `collect` entry. When collect return "again" the status of the agent (an event or an event list) will be set on "wait" again, and will become ready in `delay` seconds (or 1 second if smaller).
The default collect function looks in the exitcodes[] table for an entry of the exit code. Otherwise most of the unfortunately longer code below does nothing but making nice log message. The default collect function looks in the exitcodes[] table for an entry of the exit code. Otherwise most of the unfortunately longer code below does nothing but making nice log message.
```Lua {% highlight lua %}
----- -----
-- Called when collecting a finished child process -- Called when collecting a finished child process
-- --
@ -161,4 +162,4 @@ collect = function(agent, exitcode)
end end
return rc return rc
end, end,
``` {% endhighlight %}

View File

@ -9,7 +9,7 @@ Instead of designating actions as strings as in Layer 3 Lua functions can used t
This example will convert any file with the suffix ".ps" created in a directory into a PDF. This example will convert any file with the suffix ".ps" created in a directory into a PDF.
```Lua {% highlight lua %}
autopdf = { autopdf = {
onCreate = function(event) onCreate = function(event)
log("Normal", "got an onCreate Event") log("Normal", "got an onCreate Event")
@ -18,7 +18,7 @@ autopdf = {
end end
end end
} }
``` {% endhighlight %}
The function can take any valid Lua code. The function can take any valid Lua code.
@ -42,11 +42,11 @@ The same as spawn(), only it will invoke a shell. Any parameters are referred as
By the way, this is the simple implementation of spawnShell: By the way, this is the simple implementation of spawnShell:
```Lua {% highlight lua %}
function spawnShell(agent, command, ...) function spawnShell(agent, command, ...)
return spawn(agent, "/bin/sh", "-c", command, "/bin/sh", ...) return spawn(agent, "/bin/sh", "-c", command, "/bin/sh", ...)
end end
``` {% endhighlight %}
terminate(exitcode) terminate(exitcode)
------------------- -------------------
@ -78,14 +78,14 @@ onMove actions have two events as parameter, the origin and the destination of t
This example will tattle about all moves within the observed directory tree. This example will tattle about all moves within the observed directory tree.
```Lua {% highlight lua %}
tattleMove = { tattleMove = {
onMove = function(oEvent, dEvent) onMove = function(oEvent, dEvent)
log("Normal", "A moved happened from ", log("Normal", "A moved happened from ",
oEvent.pathname, " to ", dEvent.pathname) oEvent.pathname, " to ", dEvent.pathname)
end, end,
} }
``` {% endhighlight %}
Action functions have to be short and fast. They are running right within Lsyncd's one and only main thread. If you have to do any more time consuming calculations _spawn{}_ a child process instead. Action functions have to be short and fast. They are running right within Lsyncd's one and only main thread. If you have to do any more time consuming calculations _spawn{}_ a child process instead.

View File

@ -7,7 +7,7 @@ Simple onAction
--------------- ---------------
In this layer, custom configurations can be created. This example will use bash commands to keep a local directory in sync. In this layer, custom configurations can be created. This example will use bash commands to keep a local directory in sync.
```Lua {% highlight lua %}
bash = { bash = {
delay = 5, delay = 5,
maxProcesses = 3, maxProcesses = 3,
@ -17,21 +17,21 @@ bash = {
onMove = "mv ^o.targetPathname ^d.targetPathname", onMove = "mv ^o.targetPathname ^d.targetPathname",
onStartup = '[[ if [ "$(ls -A ^source)" ]; then cp -r ^source* ^target; fi]]', onStartup = '[[ if [ "$(ls -A ^source)" ]; then cp -r ^source* ^target; fi]]',
} }
``` {% endhighlight %}
The example explained step by step. Technically, any Lsyncd configuration is a Lua table with a set of keys filled out. Thus it starts by creating a variable called ```bash``` and assigns it a table with = { ... }. The example explained step by step. Technically, any Lsyncd configuration is a Lua table with a set of keys filled out. Thus it starts by creating a variable called ```bash``` and assigns it a table with = { ... }.
```Lua {% highlight lua %}
bash = { bash = {
... ...
} }
``` {% endhighlight %}
Now the table is filled with entries. Every entry having a key left of the equal sign and its value right of it. If no delay is specified, this means immediate actions for Lsyncd. This example wants to aggregate changes for 5 seconds thus the next entry is: Now the table is filled with entries. Every entry having a key left of the equal sign and its value right of it. If no delay is specified, this means immediate actions for Lsyncd. This example wants to aggregate changes for 5 seconds thus the next entry is:
```Lua {% highlight lua %}
delay = 5, delay = 5,
``` {% endhighlight %}
And a comma is needed since to mark the end of an entry. And a comma is needed since to mark the end of an entry.
@ -73,10 +73,10 @@ The action to be taken is specified as a Lua string. Thus actions can be delimit
Any action starting with a "/" instructs Lsyncd to directly call the binary file at the beginning instead of spawning an additional shell. For example Any action starting with a "/" instructs Lsyncd to directly call the binary file at the beginning instead of spawning an additional shell. For example
```Lua {% highlight lua %}
onCreate = "/usr/bin/zip /usr/var/all.zip ^sourceName" onCreate = "/usr/bin/zip /usr/var/all.zip ^sourceName"
onModify = "/usr/bin/zip /usr/var/all.zip ^sourceName" onModify = "/usr/bin/zip /usr/var/all.zip ^sourceName"
``` {% endhighlight %}
will add any newly created and modified files to /usr/var/all.zip using absolute path names. Any action not starting with a "/" will result in Lsyncd spawning a shell to execute the action as command. will add any newly created and modified files to /usr/var/all.zip using absolute path names. Any action not starting with a "/" will result in Lsyncd spawning a shell to execute the action as command.
@ -86,17 +86,17 @@ Variable arguments are specified with the caret symbol ^. It has been chosen ove
Note that variables will always be implicitly quoted in double quotes, so if you want them to be a part of another double-quoted string, you will have to go one layer deeper, e.g. Note that variables will always be implicitly quoted in double quotes, so if you want them to be a part of another double-quoted string, you will have to go one layer deeper, e.g.
```Lua {% highlight lua %}
onCreate = '[[ su user -c "/usr/bin/zip /usr/var/all.zip ^o.sourceName " ]], onCreate = '[[ su user -c "/usr/bin/zip /usr/var/all.zip ^o.sourceName " ]],
``` {% endhighlight %}
will expand to ```su user -c "/usr/bin/zip /usr/var/all.zip "source""``` which is incorrect and will break. You have to rewrite the above statement one layer deeper as will expand to ```su user -c "/usr/bin/zip /usr/var/all.zip "source""``` which is incorrect and will break. You have to rewrite the above statement one layer deeper as
```Lua {% highlight lua %}
onCreate = function(event) onCreate = function(event)
spawnShell('[[ su user -c "/usr/bin/zip /usr/var/all.zip \"$1\"" ]], event.sourceName) spawnShell('[[ su user -c "/usr/bin/zip /usr/var/all.zip \"$1\"" ]], event.sourceName)
end end
``` {% endhighlight %}
All possible variables All possible variables
@ -140,23 +140,23 @@ All possible variables
For ```onMoves``` a _o._ and or _d._ can be prepended to path, pathname, sourcePath sourcePathname, targetPath and targetPathname to specify the move origin or destination. Without neither the variables refers to the move origin. For ```onMoves``` a _o._ and or _d._ can be prepended to path, pathname, sourcePath sourcePathname, targetPath and targetPathname to specify the move origin or destination. Without neither the variables refers to the move origin.
From the example above, it moves the file or directory in the target directory. From the example above, it moves the file or directory in the target directory.
``` {% highlight lua %}
onMove = "mv ^o.targetPathname ^d.targetPathname", onMove = "mv ^o.targetPathname ^d.targetPathname",
``` {% endhighlight %}
Execution control (exit codes) Execution control (exit codes)
------------------------------ ------------------------------
A few words on the startup of the example. It looks a little more complicated, but it is just some bash scripting, nothing Lsyncd specific. It simply does a recursive copy of the source to the target, but first tests if there is anything in the source file. Otherwise the command returns a non-zero error code. A few words on the startup of the example. It looks a little more complicated, but it is just some bash scripting, nothing Lsyncd specific. It simply does a recursive copy of the source to the target, but first tests if there is anything in the source file. Otherwise the command returns a non-zero error code.
```Lua {% highlight lua %}
onStartup = '[[if [ "$(ls -A ^source)" ]; then cp -r ^source* ^target; fi]], onStartup = '[[if [ "$(ls -A ^source)" ]; then cp -r ^source* ^target; fi]],
``` {% endhighlight %}
By default Lsyncd ignores all exit codes except onStartup which must return 0 for it to continue. You can change this behavior by adding a ```exitcodes``` table. By default Lsyncd ignores all exit codes except onStartup which must return 0 for it to continue. You can change this behavior by adding a ```exitcodes``` table.
```Lua {% highlight lua %}
exitcodes = {[0] = "ok", [1] = "again", [2] = "die"} exitcodes = {[0] = "ok", [1] = "again", [2] = "die"}
``` {% endhighlight %}
The keys specify for the exit code the string of the desired action. The keys specify for the exit code the string of the desired action.
<table> <table>

View File

@ -7,26 +7,26 @@ You can simply choose from a set of three default implementations which are: __r
To sync a local directory using the default rsync behavior, just add this to a config file: To sync a local directory using the default rsync behavior, just add this to a config file:
```Lua {% highlight lua %}
sync { sync {
default.rsync, default.rsync,
source = "DIRNAME", source = "DIRNAME",
target = "DIRNAME" target = "DIRNAME"
} }
``` {% endhighlight %}
The order of the arguments is of no importance. If target is a local directory, take care that it is an absolute pathname. You can add multiple syncs that way. The source directories may be identical or differ without problems. ```source``` is an universal parameter that must be given for every sync. All other ```sync``` parameters can differ depending on the behavior selected. Optionally you can override the default or settings values ```maxDelays``` or ```maxProcesses``` per _Sync_. The order of the arguments is of no importance. If target is a local directory, take care that it is an absolute pathname. You can add multiple syncs that way. The source directories may be identical or differ without problems. ```source``` is an universal parameter that must be given for every sync. All other ```sync``` parameters can differ depending on the behavior selected. Optionally you can override the default or settings values ```maxDelays``` or ```maxProcesses``` per _Sync_.
One can also skip the initial rsync process by setting the default ```init``` function to false: One can also skip the initial rsync process by setting the default ```init``` function to false:
```Lua {% highlight lua %}
sync { sync {
default.rsync, default.rsync,
source = "DIRNAME", source = "DIRNAME",
target = "DIRNAME", target = "DIRNAME",
init = false init = false
} }
``` {% endhighlight %}
This is an optimization which can be dangerous; so, please use it only if you are sure that source and target are synchronized when Lsyncd is started. This is an optimization which can be dangerous; so, please use it only if you are sure that source and target are synchronized when Lsyncd is started.
@ -36,15 +36,15 @@ default.rsync
------------- -------------
The default rsync configuration will aggregate events up to ```delay``` seconds or 1000 separate uncollapsible events, which ever happens first. Then it will spawn one Rsync with a filter of all files that changed. The filter list is transmitted to Rsync trough a pipe. A call from Lsyncd to Rsync will thus look like this: The default rsync configuration will aggregate events up to ```delay``` seconds or 1000 separate uncollapsible events, which ever happens first. Then it will spawn one Rsync with a filter of all files that changed. The filter list is transmitted to Rsync trough a pipe. A call from Lsyncd to Rsync will thus look like this:
```shell {% highlight shell %}
/usr/bin/rsync -ltsd --delete --include-from=- --exclude=* SOURCE TARGET /usr/bin/rsync -ltsd --delete --include-from=- --exclude=* SOURCE TARGET
``` {% endhighlight %}
You can change the options Rsync is called and the Rsync binary that is call with the ```rsync``` parameter. You can change the options Rsync is called and the Rsync binary that is call with the ```rsync``` parameter.
Example: Example:
```Lua {% highlight lua %}
sync { sync {
default.rsync, default.rsync,
source = "/home/user/src/", source = "/home/user/src/",
@ -56,7 +56,7 @@ sync {
compress = true compress = true
} }
} }
``` {% endhighlight %}
Below is a table of options for the ```rsync``` parameter. Please have a look at the Rsync documentation for an in depth explanation. Below is a table of options for the ```rsync``` parameter. Please have a look at the Rsync documentation for an in depth explanation.
@ -296,7 +296,8 @@ Additional to that ssh can be configured via the ```ssh``` parameter.
</table> </table>
Example: Example:
```
{% highlight lua %}
settings { settings {
logfile = "/var/log/lsyncd.log", logfile = "/var/log/lsyncd.log",
statusFile = "/var/log/lsyncd-status.log", statusFile = "/var/log/lsyncd-status.log",
@ -318,13 +319,13 @@ sync {
port = 1234 port = 1234
} }
} }
``` {% endhighlight %}
Please note the comma between the ```rsync``` parameter set and the ```ssh``` parameter set. Please note the comma between the ```rsync``` parameter set and the ```ssh``` parameter set.
**Caution** **Caution**
If you are upgrading from 2.0.x, please notice that `settings` became a function from a variable, so you **MUST** delete the equal sign '=' between `settings` and the `{`. If you are upgrading from 2.0.x, please notice that `settings` became a function from a variable, so you **MUST** delete the equal sign '=' between `settings` and the `{`.
Lsyncd will call ```xargs``` on the remote host to handle multiple tasks in a single connection. Xargs options can be specified by, just guessed it, the xargs parameter. Lsyncd will call ```xargs``` on the remote host to handle multiple tasks in a single connection. Xargs options can be specified by, just guessed it, the xargs parameter.
<table> <table>
@ -352,14 +353,14 @@ Lsyncd will call ```xargs``` on the remote host to handle multiple tasks in a si
Example: Example:
```Lua {% highlight lua %}
sync { sync {
default.rsyncssh, default.rsyncssh,
source = "/home/user/src/", source = "/home/user/src/",
host = "foohost.com", host = "foohost.com",
targetdir = "~/trg/", targetdir = "~/trg/",
} }
``` {% endhighlight %}
default.direct default.direct
------------- -------------
@ -367,13 +368,13 @@ Default.direct can be used to keep two local directories in sync with better per
Example: Example:
```Lua {% highlight lua %}
sync { sync {
default.direct, default.direct,
source = "/home/user/src/", source = "/home/user/src/",
target = "/home/user/trg/" target = "/home/user/trg/"
} }
``` {% endhighlight %}
Exclusions Exclusions
---------- ----------
@ -406,14 +407,14 @@ Exclusion rules are modeled after rsync's exclusion patterns but are a bit simpl
Example: Example:
```Lua {% highlight lua %}
sync { sync {
default.rsync, default.rsync,
source = "/home/user/src/", source = "/home/user/src/",
targetdir = "/home/user/dst/", targetdir = "/home/user/dst/",
exclude = { '.bak' , '.tmp' } exclude = { '.bak' , '.tmp' }
} }
``` {% endhighlight %}
Deletions Deletions
--------- ---------

View File

@ -8,7 +8,7 @@ This [example](..) is a layer 1 script to make a special "magic" directory in wh
The full script: The full script:
```lua {% highlight lua %}
local formats = { jpg = true, gif = true, png = true } local formats = { jpg = true, gif = true, png = true }
convert = { convert = {
@ -110,93 +110,93 @@ convert = {
} }
sync{convert, source="magicdir", recursive=false} sync{convert, source="magicdir", recursive=false}
``` {% endhighlight %}
This creates a local table of all supported file formats. The file formats are used as keys. This creates a local table of all supported file formats. The file formats are used as keys.
```Lua {% highlight lua %}
local formats = { jpg=true, gif=true, png=true, } local formats = { jpg=true, gif=true, png=true, }
``` {% endhighlight %}
Configures actions to be instant and there is unlimits the amount the conversion to be done at once. Well not unlimited but set the limit pretty high. Configures actions to be instant and there is unlimits the amount the conversion to be done at once. Well not unlimited but set the limit pretty high.
```Lua {% highlight lua %}
convert = { convert = {
delay = 0, delay = 0,
maxProcesses = 99, maxProcesses = 99,
``` {% endhighlight %}
This script uses the _layer 1_ inlet interface altough it greps only single events and not lists. It does this instead of _layer 2_ as it needs to do common operations for all kind of events. This script uses the _layer 1_ inlet interface altough it greps only single events and not lists. It does this instead of _layer 2_ as it needs to do common operations for all kind of events.
```Lua {% highlight lua %}
action = function(inlet) action = function(inlet)
local event = inlet.getEvent() local event = inlet.getEvent()
``` {% endhighlight %}
Ignores directories. As using _layer 1_ it has to explicitly discard events it does not spawn actions for. Ignores directories. As using _layer 1_ it has to explicitly discard events it does not spawn actions for.
```Lua {% highlight lua %}
if event.isdir then if event.isdir then
-- ignores events on dirs -- ignores events on dirs
inlet.discardEvent(event) inlet.discardEvent(event)
return return
end end
``` {% endhighlight %}
Uses Lua string patterns to extract the file extension from the rest - here called base. Uses Lua string patterns to extract the file extension from the rest - here called base.
```Lua {% highlight lua %}
-- extract extension and basefilename -- extract extension and basefilename
local p = event.pathname local p = event.pathname
local ext = string.match(p, ".*%.([^.]+)$") local ext = string.match(p, ".*%.([^.]+)$")
local base = string.match(p, "(.*)%.[^.]+$") local base = string.match(p, "(.*)%.[^.]+$")
``` {% endhighlight %}
Looks the extension up in the formats table. This can be done, since formats are keys in that table. If not an image format it bails out. Looks the extension up in the formats table. This can be done, since formats are keys in that table. If not an image format it bails out.
```Lua {% highlight lua %}
if not formats[ext] then if not formats[ext] then
-- an unknown extenion -- an unknown extenion
log("Normal", "not doing something on ."..ext) log("Normal", "not doing something on ."..ext)
inlet.discardEvent(event) inlet.discardEvent(event)
return return
end end
``` {% endhighlight %}
Following actions will done on "Create" and "Modify" events. Following actions will done on "Create" and "Modify" events.
```Lua {% highlight lua %}
-- autoconvert on create and modify -- autoconvert on create and modify
if event.etype == "Create" or event.etype == "Modify" then if event.etype == "Create" or event.etype == "Modify" then
``` {% endhighlight %}
This script builds a bash command using a string. This script builds a bash command using a string.
```Lua {% highlight lua %}
-- builds one bash command -- builds one bash command
local cmd = "" local cmd = ""
``` {% endhighlight %}
It iterates for all image formats and excludes the one which is the source image. It iterates for all image formats and excludes the one which is the source image.
```Lua {% highlight lua %}
-- do for all other extensions -- do for all other extensions
for k, _ in pairs(formats) do for k, _ in pairs(formats) do
if k ~= ext then if k ~= ext then
``` {% endhighlight %}
This is a little trick. It creates Exclusions for the converted images. As this images are not placed in a target directory but right next to the source image in the source directory they would otherwise trigger Create actions as well. This is a little trick. It creates Exclusions for the converted images. As this images are not placed in a target directory but right next to the source image in the source directory they would otherwise trigger Create actions as well.
```Lua {% highlight lua %}
-- excludes files to be created, so no -- excludes files to be created, so no
-- followup actions will occur -- followup actions will occur
inlet.addExclude(base..'.'..k) inlet.addExclude(base..'.'..k)
``` {% endhighlight %}
And for every image to be converted adds the calls to the arguments. It uses { || /bin/true } to let the shell continue if one conversion fails. In that it chains the conversion with '&&' they will be called sequentially. And for every image to be converted adds the calls to the arguments. It uses ```" || /bin/true "``` to let the shell continue if one conversion fails. In that it chains the conversion with '&&' they will be called sequentially.
```Lua {% highlight lua %}
if cmd ~= "" then if cmd ~= "" then
cmd = cmd .. " && " cmd = cmd .. " && "
end end
@ -205,22 +205,22 @@ And for every image to be converted adds the calls to the arguments. It uses { |
event.source..p..'" "'.. event.source..p..'" "'..
event.source..base..'.'..k.. event.source..base..'.'..k..
'" || /bin/true' '" || /bin/true'
``` {% endhighlight %}
And eventually it spawns the shell doing the conversions and is finished. And eventually it spawns the shell doing the conversions and is finished.
```Lua {% highlight lua %}
end end
end end
log("Normal", "Converting "..p) log("Normal", "Converting "..p)
spawnShell(event, cmd) spawnShell(event, cmd)
return return
end end
``` {% endhighlight %}
For deletions it does technically something similar, but it deletes all other file formats of the image. For deletions it does technically something similar, but it deletes all other file formats of the image.
```Lua {% highlight lua %}
-- deletes all formats if you delete one -- deletes all formats if you delete one
if event.etype == "Delete" then if event.etype == "Delete" then
-- builds one bash command -- builds one bash command
@ -243,19 +243,19 @@ For deletions it does technically something similar, but it deletes all other fi
spawnShell(event, cmd) spawnShell(event, cmd)
return return
end end
``` {% endhighlight %}
and not to forget to nicely discard all other events. and not to forget to nicely discard all other events.
```Lua {% highlight lua %}
-- ignores other events. -- ignores other events.
inlet.discardEvent(event) inlet.discardEvent(event)
end, end,
``` {% endhighlight %}
collect is called when the conversions finished. It will remove the temporary excludes again. collect is called when the conversions finished. It will remove the temporary excludes again.
```Lua {% highlight lua %}
----- -----
-- Removes excludes when convertions are finished -- Removes excludes when convertions are finished
-- --
@ -274,10 +274,10 @@ collect is called when the conversions finished. It will remove the temporary ex
end end
end end
end, end,
``` {% endhighlight %}
And finally use the configuration to watch "magicdir". And finally use the configuration to watch "magicdir".
```Lua {% highlight lua %}
sync{convert, source="magicdir", recursive=false} sync{convert, source="magicdir", recursive=false}
``` {% endhighlight %}

View File

@ -5,7 +5,7 @@ tab: "manual/examples"
--- ---
A Layer 3 [example](..) that forces a directory tree to be read/writeable by a group. A Layer 3 [example](..) that forces a directory tree to be read/writeable by a group.
```lua {% highlight lua %}
----- -----
-- User configuration file for lsyncd. -- User configuration file for lsyncd.
-- --
@ -87,4 +87,4 @@ gforce = {
} }
sync{gforce, source="/path/to/share"} sync{gforce, source="/path/to/share"}
``` {% endhighlight %}

View File

@ -4,65 +4,65 @@ title: Invoking
--- ---
As most Unix tools, Lsyncd will print a synopsis of its command line options when called with --help. As most Unix tools, Lsyncd will print a synopsis of its command line options when called with --help.
```shell {% highlight shell %}
lsyncd --help lsyncd --help
lsyncd -help lsyncd -help
``` {% endhighlight %}
The two hyphens are redundant for Lsyncd. It has no short one letter options and one hyphen will always result into the same as specifying two. The two hyphens are redundant for Lsyncd. It has no short one letter options and one hyphen will always result into the same as specifying two.
Also like most Unix tools, --version or -version will let Lsyncd print its version number. Also like most Unix tools, ```--version``` or ```-version``` will let Lsyncd print its version number.
``` {% highlight shell %}
lsyncd -version lsyncd -version
``` {% endhighlight %}
Lsyncd 2.1 is designed to be predominantly configured through a config file (see below). The config file can thus be the only command line option. Lsyncd 2.1 is designed to be predominantly configured through a config file (see below). The config file can thus be the only command line option.
```shell {% highlight shell %}
lsyncd CONFIGFILE lsyncd CONFIGFILE
``` {% endhighlight %}
Although for standard use or quick testing it can be cursorily configured by command line options. The following will keep a local source and destination directory in sync using rsync: Although for standard use or quick testing it can be cursorily configured by command line options. The following will keep a local source and destination directory in sync using rsync:
```shell {% highlight shell %}
lsyncd -rsync /home/USER/src /home/USER/dst lsyncd -rsync /home/USER/src /home/USER/dst
``` {% endhighlight %}
The target can here be anything that Rsync recognizes. The target can here be anything that Rsync recognizes.
```shell {% highlight shell %}
lsyncd -rsync /home/USER/src remotehost:dst lsyncd -rsync /home/USER/src remotehost:dst
``` {% endhighlight %}
Two (or more) targets are configured by calling -rsync twice (or several times). Two (or more) targets are configured by calling -rsync twice (or several times).
```shell {% highlight shell %}
lsyncd -rsync /home/USER/src remotehost1:dst -rsync /home/USER/src remotehost2:dst lsyncd -rsync /home/USER/src remotehost1:dst -rsync /home/USER/src remotehost2:dst
``` {% endhighlight %}
A disadvantage with Rsync synchronization is that normally directory and file moves result in a deletion of the move origin and a retransfer of the move destination of the wire. However, Lsyncd 2 can use ssh commands to move the directories and files locally on the target. To use this use ```-rsyncssh``` followed by the local source directory, the remote host and the target directory there. The REMOTEHOST can include a user like ```me@remotehost.com```. A disadvantage with Rsync synchronization is that normally directory and file moves result in a deletion of the move origin and a retransfer of the move destination of the wire. However, Lsyncd 2 can use ssh commands to move the directories and files locally on the target. To use this use ```-rsyncssh``` followed by the local source directory, the remote host and the target directory there. The REMOTEHOST can include a user like ```me@remotehost.com```.
```shell {% highlight shell %}
lsyncd -rsyncssh /home/USER/src REMOTEHOST TARGETDIR lsyncd -rsyncssh /home/USER/src REMOTEHOST TARGETDIR
``` {% endhighlight %}
When testing Lsyncd configurations ```-nodaemon``` is a pretty handy flag. With this option, Lsyncd will not detach and will not become a daemon. All log messages are additionally to the configured logging facilities printed on the console (_stdout_ and _stderr_). When testing Lsyncd configurations ```-nodaemon``` is a pretty handy flag. With this option, Lsyncd will not detach and will not become a daemon. All log messages are additionally to the configured logging facilities printed on the console (_stdout_ and _stderr_).
```shell {% highlight shell %}
lsyncd -nodaemon CONFIGFILE lsyncd -nodaemon CONFIGFILE
``` {% endhighlight %}
Note there is a difference in behaviour. When running with -nodaemon, Lsyncd will not change its working directory to ```/```, as it does when becoming a daemon. Thus relative targets like ```./target``` will work with ```-nodaemon```, but must be specified to absolute paths to work in daemon mode. The source directories will also be turned into absolute paths by Lsyncd. The reason targets are not resolved to absolute paths while sources are is because Lsyncd itself does not care about the format of the target specifier which can also be remote hosts, rsyncd modules, etc. It is opaquely handed to rsync. It cares about the observed directories though. Note there is a difference in behaviour. When running with -nodaemon, Lsyncd will not change its working directory to ```/```, as it does when becoming a daemon. Thus relative targets like ```./target``` will work with ```-nodaemon```, but must be specified to absolute paths to work in daemon mode. The source directories will also be turned into absolute paths by Lsyncd. The reason targets are not resolved to absolute paths while sources are is because Lsyncd itself does not care about the format of the target specifier which can also be remote hosts, rsyncd modules, etc. It is opaquely handed to rsync. It cares about the observed directories though.
All log messages are sorted in categories. By default Lsyncd is scarce with log messages. You can turn Lsyncd into a motormouth by specifying ```-log all```. All log messages are sorted in categories. By default Lsyncd is scarce with log messages. You can turn Lsyncd into a motormouth by specifying ```-log all```.
```shell {% highlight shell %}
lsyncd -log all CONFIGFILE lsyncd -log all CONFIGFILE
``` {% endhighlight %}
This might easily become too much. A particularly useful category is "Exec" which will log the command lines of all processes Lsyncd spawns. This might easily become too much. A particularly useful category is "Exec" which will log the command lines of all processes Lsyncd spawns.
```shell {% highlight shell %}
lsyncd -log Exec CONFIGFILE lsyncd -log Exec CONFIGFILE
``` {% endhighlight %}