从rsync手册文档中我看到,通过使用选项rsync-path,可以指定要在远程计算机上运行哪个程序来启动rsync。特别是,程序可以是一个包装脚本,它在中间调用实际的rsync命令,但在rsync调用之前和/或之后执行一些操作。一个可能有趣的用途是获取/释放锁(例如,一个群),以便远程端的rsync的操作可以与远端的另一个进程协调,该进程争用对其的写访问权。文件。可能有多个rsync进程同时持有共享锁(我知道有可能出现饥饿但现在并不关心它)。我正在处理的'writer'进程只会改变一些硬链接,因此它不会阻止rsync进程的任何重要时间。
我已经研究过其他协调方法,例如,在客户端和服务器之间实现自定义远程锁定协议,但它们都涉及更多的开发工作和/或由于其他原因而不能令人满意,这就是我感兴趣的原因。包装/(f)锁定方法。
我的问题是:
1)这是解决rsync'读者'与另一个“作者”进程协调访问同一目录的问题的合理方法吗?
2)在使用inetd(或xinetd)守护进程运行rsync时,还可以在rsync周围放置一个包装器,方法是在/etc/inetd.conf中添加如下所示的行(根据rsyncd.conf文件)页):
rsync stream tcp nowait root / usr / bin / rsync rsyncd --daemon
但是将/ usr / bin / rsync替换为rsync-lookalike包装器的路径,在这种情况下,它将是一个C / C ++代码程序,它抓住一个锁,分离rsync,等待rsync完成,然后释放锁。
谢谢, 汤姆
答案 0 :(得分:1)
包装器方法的一个潜在问题:远程进程似乎使用额外的参数调用,这些参数附加到您使用--rsync-path指定的任何命令行。因此,如果您需要传递参数,则需要以下样式。
#! /bin/sh
lock_target=$1
shift
if ! lockfile ${lock_target}.lock ; then exit 1 ; fi
trap "rm -f ${lock_target}.lock" EXIT HUP TERM INT
/usr/bin/rsync "$@"
答案 1 :(得分:0)
根据对原始帖子的评论,使用包装器方法在服务器端实现(f)rsync锁定确实是可行的。
答案 2 :(得分:0)
感谢问题和评论。有了你的想法,我使用--rsync-path解决了它(对我来说),但远程主机上没有任何包装程序,只需将所有有效负载脚本放入--rsync-path,只需几个技巧。
此特定示例使用rsync从远程主机提取数据,同时在远程主机上保留一个群,例如
,远程主机定期转储数据,同时保留一个flock,因此不能交错转储。注意事项
考虑到这一点,这里是我简化的概念 rehash(我没有运行这个特定的脚本,我的完整解决方案有额外的层,分散了主要注意力的注意力。)
拉主机上的脚本:
#!/bin/bash
function rsync_wrap() {
{
flock --exclusive --timeout ${LOCK_TIMEOUT} 100 || {
echo "Failed to lock: ${LOCK_TIMEOUT}" 1>&2
return 1
}
# call real rsync with original arguments
rsync "$@"
exit_code=$?
if [ ${exit_code} -eq 0 ]; then
# Do clean up when success
# rm -f "${LOCK_FILE}"
# rm -rf /eg/purge/data
else
# Do clean up when failed
fi
# Note, return is important, do not let it fall out
return ${exit_code}
} 100<"${LOCK_FILE}"
echo "Failed to open lock file: ${LOCK_FILE}" 1>&2
return 1
}
# Define vars
LOCK_FILE=/var/somedir/name.lock; # or /dev/shm/name.lock
LOCK_TIMEOUT=600; #in seconds
# Build remote command, define vars and functions inside the command
remote_cmd="
# this approach deals with crazy chars in variables and function code
$( declare -p LOCK_FILE )
$( declare -p LOCK_TIMEOUT )
$( declare -f rsync_wrap )
rsync_wrap "
local_cmd=(
rsync
-a
--rsync-path="${remote_cmd}"
# I want to handle network timeouts in SSH, not in rsync,
# because rsync does not know that waiting for lock is expected
-e "ssh -o BatchMode=yes -o ServerAliveCountMax=3 -o ServerAliveInterval=30 ${IDENTITY_FILE:+ -i '${IDENTITY_FILE}'}"
/remote/source/path
/local/destination/path/
)
# Do it
"${local_cmd[@]}"
如果远程端执行-rsync-path而不是bash,那么也许整个远程命令可以包含在以下内容中:
local_cmd="bash -c '${local_cmd//\'/\'\\\'\'}'"