Lsyncd
Lsyncd - демон на Lua, позволяющий синхронизировать между собой каталоги между несколькими серверами по событиям изменения содержимого файловой системы. Это позволяет без особой нагрузки на сервер (свойственной, например, запускаемому для той же цели по cron'у rsync'у) зеркалировать, например, веб-контент между основным сервером (где запущен lsyncd) и рядом веб-серверов, которые отдают этот контент в Интернет.
Для работы использует inotify - средство ядра для оповещения про изменение содержимого файловой системы.
В качестве "исполнительных механизмов" может работать как напрямую с файлами (при этом набор функций ограничен - например, нельзя менять права/владельца обрабатываемых файлов), так и через rsync, в том числе с использованием SSH. Позволяет для разных хостов задавать разные наборы правил для синхронизации и опции для rsync'a.
Особенности использования:
- Иногда демон падал при недоступности одного из перечисленных хостов. Решил строчкой в crontab'e, отслеживающей состояние демона и перезапускающей его:
*/5 * * * * kill -0 $(cat /var/run/lsyncd/lsyncd.pid 2>/dev/null) 2>/dev/null || { /etc/init.d/lsyncd restart | mail -s 'S' adminmail@gmail.com ; }
- Для больших каталогов может потребоваться увеличить значение параметра ядра fs.inotify.max_user_watches до нужной величины - дефолтное значение там 8192 - иначе некоторые каталоги будут выпадать из синхронизации:
root ~# sysctl fs.inotify.max_user_watches fs.inotify.max_user_watches = 131072
Пример init-скрипта для запуска и остановки демона:
#! /bin/sh
### BEGIN INIT INFO
# Provides: lsyncd
# Required-Start: $remote_fs
# Required-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: lsyncd daemon init script
# Description: This script launches the lsyncd daemon.
### END INIT INFO
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="synchronization daemon"
NAME=lsyncd
DAEMON=/usr/bin/$NAME
CONFIG=/etc/lsyncd.conf.lua
DAEMON_ARGS="${CONFIG}"
PIDFILE=/var/run/${NAME}/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
DAEMONUID='user'
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Exit if config file does not exist
[ -r "$CONFIG" ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
[ -d "${PIDFILE}/${NAME}" ] || { mkdir -p "/var/run/${NAME}" && chown "${DAEMONUID}" "/var/run/${NAME}" ; }
case "$1" in
start)
logger "Starting $DESC" "$NAME"
echo "Starting $DESC" "$NAME"
su -l "${DAEMONUID}" -c "${DAEMON} -pidfile ${PIDFILE} ${DAEMON_ARGS}"
;;
stop)
logger "Stopping $DESC" "$NAME"
echo "Stopping $DESC" "$NAME"
kill -TERM "$(cat ${PIDFILE})"
;;
restart|force-reload)
logger "Restarting $DESC" "$NAME"
echo "Stopping $DESC" "$NAME"
kill -TERM "$(cat ${PIDFILE})"
echo "Starting $DESC" "$NAME"
su -l "${DAEMONUID}" -c "${DAEMON} -pidfile ${PIDFILE} ${DAEMON_ARGS}"
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac
: