Config Layer 3: Simple onAction

Simple onAction

In this layer, custom configurations can be created. This example will use bash commands to keep a local directory in sync.

bash = {
    delay = 5,
    maxProcesses = 3,
    onCreate = "cp -r ^sourcePathname ^targetPathname",
    onModify = "cp -r ^sourcePathname ^targetPathname",
    onDelete = "rm -rf ^targetPathname",
    onMove   = "mv ^o.targetPathname ^d.targetPathname",
    onStartup = '[[ if [ "$(ls -A ^source)" ]; then cp -r ^source* ^target; fi]]',
}

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 = { … }.

bash = {
  ...
}

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:

    delay = 5,

And a comma is needed since to mark the end of an entry.

Actions

Actions are specified by the 6 keys:

onAttrib called when only attributes changed
onCreate called on a new file or directory
onModify called when a file has changed
onDelete called when a file or directory has been deleted
onMove called when a file or directory has been moved within the observed directory tree
onStartup called on the start of Lsyncd

When there is no onMove or the move goes into or out of the observed directory tree, it is split into an onDelete of the move origin and an onCreate of the move destination. That is if either is within the observed directory tree. onStartup will always block all other actions for this Sync until completed.

The action to be taken is specified as a Lua string. Thus actions can be delimited with anything Lua allows, these are ‘TEXT’, “TEXT”, or ‘[[TEXT]] as used in onStartup in the example above.

Any action starting with a “/” instructs Lsyncd to directly call the binary file at the beginning instead of spawning an additional shell. For example

   onCreate = "/usr/bin/zip /usr/var/all.zip ^sourcePath"
   onModify = "/usr/bin/zip /usr/var/all.zip ^sourcePath"

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.

Variables

Variable arguments are specified with the caret symbol ^. It has been chosen over $ or other symbols to be less conflicting with standard shell conventions.

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.

    onCreate   = '[[ su user -c "/usr/bin/zip /usr/var/all.zip ^o.sourcePath " ]],

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

  onCreate = function(event)
    spawnShell('[[ su user -c "/usr/bin/zip /usr/var/all.zip \"$1\"" ]], event.sourcePath)
  end

All possible variables

^source the absolute path of the observed source directory
^target the "target" attribute of the config
^path the relative path of the file or directory to the observed directory; directories have a slash at the end.
^pathname the relative path of the file or directory to the observed directory; directories have no slash at the end.
^sourcePath the absolute path of the observed source directory and the relative path of the file or directory; this equals the absolute local path of the file or directory. Directories have a slash at the end.
^sourcePathname same as ^sourcePath, but directories have no slash at the end.
^targetPath The "target" attributed of the config appended by the relative path of the file or directory. Directories have a slash at the end.
^targetPathname same as ^targetPath, but directories have no slash at the end.

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.

    onMove   = "mv ^o.targetPathname ^d.targetPathname",

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.

    onStartup = '[[if [ "$(ls -A ^source)" ]; then cp -r ^source* ^target; fi]],

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.

    exitcodes = {[0] = "ok", [1] = "again", [2] = "die"}

The keys specify for the exit code the string of the desired action.

again respawns the action after seconds, or 1 second if delay is immediate
die lets Lsyncd terminate.

All other values let Lsyncd continue normally.