Update: 09/03/2012

Lsync has been added to Redhat’s repository, so those of you using redhat can do:

yum install epel-release
yum install lsync

to get lsync installed even easier than the below guide.

I’ve mentioned Lsync here before, but I figured I could do a bit more documentation on this service.

Lsync is a very handy software package for doing near instantanious updates of files/directories from a central location to many external locations. Think star topology. It works particularly well in the cloud where you tend to find large number of web servers that need the same content across them at any given moment. It will NOT work if you can not isolate your application to doing uploads to a single server in such a load balanced configuration. You were warned. That said, as long as all your file uploads are going to a single server, lsync can keep your other web servers current and up to date with, at most, a 20 second delay.

All that being said…here is how you install it.

Configure SSH

First, set up passwordless SSH between your web1 server and the clones.

Generate SSH keypair on master:

# ssh-keygen -t rsa

Then copy /root/.ssh/id_rsa.pub on master to /root/.ssh/authorized_keys on the slave servers

Then ensure the following lines are uncommented in /etc/ssh/sshd_config on the slave servers

PermitRootLogin yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

Restart SSH after changes are made.

IMPORTANT: It is vital that you ssh from the command line of the master server to the clones one by one the first time. If you do not and don’t save the key? Lsync will fail. So make sure that the bit about:

The authenticity of host ‘yourdomain.com (your.ip.here)’ can’t be established.
RSA key fingerprint is blah.blah.blah.blah.
Are you sure you want to continue connecting (yes/no)?

does not appear when doing SSH between the servers.

Open Firewall ports

For Cent:

add the following line to /etc/sysconfig/iptables to all slave servers.

-A RH-Firewall-1-INPUT -s 10.x.x.x -p tcp -m tcp –dport 873 -j ACCEPT (10.x.x.x being the master’s private IP)

Then restart iptables to add rule.

For Ubuntu

ufw allow from 10.x.x.x to any port 873

Installing Lsync

first you need to ensure the following packages are installed, that are not within the default LAMP build

CentOS and RHEL

# yum install lua lua-devel pkgconfig

Ubuntu

# apt-get install lua5.1 liblua5.1-dev pkg-config rsync

Then grab the source tarball from http://code.google.com/p/lsyncd/

untar and run the standard ./configure, make, make install

Only thing I noticed I had to do manually was create the directory /var/log/lsyncd for the logs files

The source code install does not add the init.d script or configuration file by default, those have to be manually added after installation.

Create init.d script from template below. /etc/init.d/lsyncd

USE BELOW FOR CentOS and RHEL:

#!/bin/bash
#
# lsyncd: Starts the lsync Daemon
#
# chkconfig: 345 99 90
# description: Lsyncd uses rsync to synchronize local directories with a remote
# machine running rsyncd. Lsyncd watches multiple directories
# trees through inotify. The first step after adding the watches
# is to, rsync all directories with the remote host, and then sync
# single file buy collecting the inotify events.
# processname: lsyncd

. /etc/rc.d/init.d/functions

config="/etc/lsyncd.lau"
lsyncd="/usr/local/bin/lsyncd"
lockfile="/var/lock/subsys/lsyncd"
prog="lsyncd"
RETVAL=0

start() {
if [ -f $lockfile ]; then
echo -n $"$prog is already running: "
echo
else
echo -n $"Starting $prog: "
daemon $lsyncd $config
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch $lockfile
return $RETVAL
fi
}

stop() {
echo -n $"Stopping $prog: "
killproc $lsyncd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f $lockfile
return $RETVAL
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status $lsyncd
;;
*)

echo "Usage: lsyncd {start|stop|restart|status}"
exit 1
esac

exit $?

Use this block for Ubuntu:

#!/bin/bash
#
# lsyncd: Starts the lsync Daemon
#
# chkconfig: 345 99 90
# description: Lsyncd uses rsync to synchronize local directories with a remote
# machine running rsyncd. Lsyncd watches multiple directories
# trees through inotify. The first step after adding the watches
# is to, rsync all directories with the remote host, and then sync
# single file buy collecting the inotify events.
# processname: lsyncd

# . /etc/rc.d/init.d/functions

config="/etc/lsyncd.lau"
lsyncd="/usr/local/bin/lsyncd"
lockfile="/var/lock/lsyncd"
prog="lsyncd"
RETVAL=0

start() {
if [ -f $lockfile ]; then
echo -n $"$prog is already running: "
echo
else
echo -n $"Starting $prog: "
$lsyncd $config
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch $lockfile
return $RETVAL
fi
}

stop() {
echo -n $"Stopping $prog: "
killall $lsyncd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f $lockfile
return $RETVAL
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status $lsyncd
;;
*)

echo "Usage: lsyncd {start|stop|restart|status}"
exit 1
esac

exit $?

Set permissions and ownership on init.d file:

# chmod 775 /etc/init.d/lsyncd
# chown root:root /etc/init.d/lsyncd

Configuration file examples

The config file for lsync is /etc/lsyncd.lau

Here is an example of a master, single slave configuration file (10.x.x.x is the private IP of the slave server).

settings = {
logfile = “/var/log/lsyncd/lsyncd.log”,
statusFile = “/var/log/lsyncd/lsyncd-status.log”,
statusInterval = 20

}

sync{
default.rsyncssh,
source=”/var/www/html”,
host=”10.x.x.x”,
targetdir=”/var/www/html”,
rsyncOpts=”-avz”

}

Here is an example for a master, two slave configuration (10.x.x.x is the IP’s for the slave servers (one at each area).

settings = {
logfile = “/var/log/lsyncd/lsyncd.log”,
statusFile = “/var/log/lsyncd/lsyncd-status.log”,
statusInterval = 20

}

sync{
default.rsyncssh,
source=”/var/www/html”,
host=”10.x.x.x”,
targetdir=”/var/www/html”,
rsyncOpts=”-avz”

}

sync{
default.rsyncssh,
source=”/var/www/html”,
host=”10.x.x.x”,
targetdir=”/var/www/html”,
rsyncOpts=”-avz”

}

If you want to exclude a directory, use an exclude file and the excludeFrom directive:

/etc/lsyncd-excludes.txt:

cache/
uploads/
dontcopymebro/

/etc/lsyncd.lau:

settings = {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd-status.log",
statusInterval = 20

}

sync{
default.rsyncssh,
source="/var/www/html",
host="10.x.x.x",
targetdir="/var/www/html",
excludeFrom="/etc/lsyncd-excludes.txt",
rsyncOpts="-avz"

}

Here is the manual for more configuration options.

Set up log rotate

Add this file as /etc/logrotate.d/lsyncd (same on all OS’es):

/var/log/lsyncd/*log {
missingok
notifempty
sharedscripts
postrotate

/sbin/service lsyncd restart > /dev/null 2>/dev/null || true

endscript
}

For Ubuntu, you will need to also create the file /etc/init/lsyncd.conf for setting the lsyncd service to start upon boot with 644 permissions:

# lsyncd – synchronization program
#
#

description “lsyncd”

# Make sure we start before an interface receives traffic
start on (starting network-interface
or starting network-manager
or starting networking)

stop on runlevel [!023456]

respawn
respawn limit 10 5

pre-start exec /etc/init.d/lsyncd start
post-stop exec /etc/init.d/lsyncd stop

For RHEL and CentOS, this is much easier:

# chkconfig lsyncd on

And as previously blogged, the most common reason that lsync stops working is due to the inotify watch limit documented here. So if your lsync suddenly stops working, the most likely reason is that you’ve hit this limit.


Category: linux, replication

8 Responses to Installing Lsync

  1. Carl says:

    Hey, thanks for this guide! I did run into an issue with the RHEL init script. When I copied it to a server (using vim), the quotes showed up as weird slanted quote characters(โ€œโ€), which bash did not care for. I had to change them all to the normal quotes (“”). Is there any way to display those code blocks as raw text?

  2. alex says:

    Glad it helped, Carl. I’ve modified the two init script blocks to add the “code” tag, so it should stop converting the paragraphs now. Thanks for the pointer.

  3. Austin says:

    Any way to run a shell script onCreate in a specified directory? I don’t want to use rsync, rsyncssh, or direct. I simply want to trigger a script when a file is created in a directory I specified.

  4. chud says:

    Lsync won’t start. I get:

    Parameter “rsync.excludeFrom” unknown

  5. Stuart says:

    @Austin, This is way past the asking date, but I thought I would pipe in here for anyone potentially asking the same question. If you look at the lsync manual for Layer 2 functionality, you can easily spawn a shell script. Here is my example:

    runScript = {
    onCreate = function(event)
    log(“A Creation event! \n File created pathname = “, event.path)
    spawn(event, “/path/to/script/myscript.sh”, event.path)
    end
    }

    which is technically itself a Lua scripted function (lsync was written in Lua). In the spawn call, each comma separated input after the full script path are inputs to you shell script. In this example, I am passing the filename of the created file to myscript.sh. See the manual for more details:
    https://github.com/axkibe/lsyncd/wiki/Lsyncd%202.1.x%20%E2%80%96%20Layer%202%20Config%20%E2%80%96%20Advanced%20onAction

    • alex says:

      Hey. Thanks! I’ve not really played with lsync a great deal lately, but this will potentially come in handy down the road if I do. So thanks for sharing it. ๐Ÿ™‚

Leave a Reply

Categories


gives good tech

tech.superhappykittymeow.com
Kale is one of the smartest people I know

Racker Hacker
Major is always good for leet deetz