我正在尝试在执行rsync
命令之前,将我的rsync
命令视为源文件的文件更改为未知的uid&gid&gid。
我的rsync
命令包含排除文件。
在我的问题here中解释了我需要这样做的原因。
我试过这个find
命令:
find /cygdrive/f -uid 4294967295 -exec chown 544. '{}' + -o -gid 4294967295 -exec chown .197121 '{}' +
但是,它不处理排除文件。我的意思是,上面的find
搜索所有f驱动器以查找与未知uid / gid匹配的文件,然后查找chowns
个文件。我的rsync
查看驱动器f并复制除排除文件中的文件以外的所有内容。我不想chown
任何rsync
不复制的Win7端文件。
例如,Win7保护其隐藏/ sys文件的方法之一是将其uid和gid设置为4294967295(例如c:\ pagefil.sys和c:\ hiberfil.sys)。我已在rsync
排除文件中排除了这两个文件,我想单独保留其Win7端的uid / gid。 find
命令会chown
他们。
我还尝试解析ls
列表,这可能有用,但速度非常慢。由于我只处理Win7文件,我认为ls
适合解析。
在ls
脚本之前使用find
列表(或解析chowning
输出)之前,有没有更好的方法来解决我的问题?
另一种更精确的方法,但速度慢,需要更困难的脚本,就是解析一个rsync --dry-run ...
列表,找出哪些项目需要chowning
。
编辑2015-12-13:不幸的是rsync --dry-run ...
没有生成关于在干运行期间无法设置UID / GID的警告,因此方法已经结束。
但是,我找到了rsync
的源代码,它在我看来修改它很容易,以便UID / GID可以设置为UID和GID如果在会话期间发现错误的UID / GID,则运行rsync
命令的进程。
任何人都可以总结一下我在Win7计算机上编译rsync
源代码所需的工具吗?
这是来自源代码的rsync.c(搜索'无法设置'):
int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
const char *fnamecmp, int flags)
{
int updated = 0;
stat_x sx2;
int change_uid, change_gid;
mode_t new_mode = file->mode;
int inherit;
if (!sxp) {
if (dry_run)
return 1;
if (link_stat(fname, &sx2.st, 0) < 0) {
rsyserr(FERROR_XFER, errno, "stat %s failed",
full_fname(fname));
return 0;
}
init_stat_x(&sx2);
sxp = &sx2;
inherit = !preserve_perms;
} else
inherit = !preserve_perms && file->flags & FLAG_DIR_CREATED;
if (inherit && S_ISDIR(new_mode) && sxp->st.st_mode & S_ISGID) {
/* We just created this directory and its setgid
* bit is on, so make sure it stays on. */
new_mode |= S_ISGID;
}
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
get_acl(fname, sxp);
#endif
change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
&& sxp->st.st_gid != (gid_t)F_GROUP(file);
#ifndef CAN_CHOWN_SYMLINK
if (S_ISLNK(sxp->st.st_mode)) {
;
} else
#endif
if (change_uid || change_gid) {
if (DEBUG_GTE(OWN, 1)) {
if (change_uid) {
rprintf(FINFO,
"set uid of %s from %u to %u\n",
fname, (unsigned)sxp->st.st_uid, F_OWNER(file));
}
if (change_gid) {
rprintf(FINFO,
"set gid of %s from %u to %u\n",
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
}
}
if (am_root >= 0) {
uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
if (do_lchown(fname, uid, gid) != 0) {
/* We shouldn't have attempted to change uid
* or gid unless have the privilege. */
rsyserr(FERROR_XFER, errno, "%s %s failed",
change_uid ? "chown" : "chgrp",
full_fname(fname));
goto cleanup;
}
if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
rprintf(FERROR_XFER, "uid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
if (gid == (gid_t)-1 && sxp->st.st_gid != (gid_t)-1)
rprintf(FERROR_XFER, "gid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
/* A lchown had been done, so we need to re-stat if
* the destination had the setuid or setgid bits set
* (due to the side effect of the chown call). */
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
link_stat(fname, &sxp->st,
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
}
}
updated = 1;
}
#ifdef SUPPORT_XATTRS
if (am_root < 0)
set_stat_xattr(fname, file, new_mode);
if (preserve_xattrs && fnamecmp)
set_xattr(fname, file, fnamecmp, sxp);
#endif
if (!preserve_times
|| (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
|| (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
flags |= ATTRS_SKIP_MTIME;
if (!(flags & ATTRS_SKIP_MTIME)
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);
if (ret < 0) {
rsyserr(FERROR_XFER, errno, "failed to set times on %s",
full_fname(fname));
goto cleanup;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
else
file->flags |= FLAG_TIME_FAILED;
}
#ifdef SUPPORT_ACLS
/* It's OK to call set_acl() now, even for a dir, as the generator
* will enable owner-writability using chmod, if necessary.
*
* If set_acl() changes permission bits in the process of setting
* an access ACL, it changes sxp->st.st_mode so we know whether we
* need to chmod(). */
if (preserve_acls && !S_ISLNK(new_mode)) {
if (set_acl(fname, file, sxp, new_mode) > 0)
updated = 1;
}
#endif
#ifdef HAVE_CHMOD
if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
if (ret < 0) {
rsyserr(FERROR_XFER, errno,
"failed to set permissions on %s",
full_fname(fname));
goto cleanup;
}
if (ret == 0) /* ret == 1 if symlink could not be set */
updated = 1;
}
#endif
if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
if (updated)
rprintf(FCLIENT, "%s\n", fname);
else
rprintf(FCLIENT, "%s is uptodate\n", fname);
}
cleanup:
if (sxp == &sx2)
free_stat_x(&sx2);
return updated;
}
答案 0 :(得分:1)
我找到了两个解决基本问题的实用解决方案:
如果源和目标环境都使用rsync 3.1.0或更高版本,则可以使用新选项。在这种情况下,我可以将这些选项添加到我的rsync命令中:
- usermap = 4294967295:544 --groupmap = 4294967295:197121
谢谢你,Wayne Davison指导我这些新选项!
如果您在目的地上遇到较旧的rsync(因为我使用的是WD MyCloud),您可以使用cygwin修改rsync源代码,如下所示。
确保您的cygwin已安装gcc
gcc-core
perl
make
和quilt
rsync
源tar文件
我将其解压缩到我的〜目录中的文件夹。
我已下载Eclipse
以用作IDE,但您只需使用NotePad++
修改文件,如下所示:
在main.c文件中,我添加了一条信息行,您每次运行rsync时都会看到该信息行,因此您知道自己正在使用个人rsync版本。我确信还有一种适当的方法可以将版本号设置为我自己的版本号,但我会让某人评论如何做到这一点。 (我的所有行以/ * dalek * /结尾):
starttime = time(NULL);
our_uid = MY_UID();
our_gid = MY_GID();
rprintf(FINFO,"rsync 3.1.1 with edits started by uid: %u gid: %u\n", our_uid, our_gid ); /* dalek */
然后,在flist.c中,添加我的/ * dalek * /行,如下所示:
if (!preserve_uid || ((uid_t)F_OWNER(file) == uid && *lastname))
xflags |= XMIT_SAME_UID;
else {
uid = F_OWNER(file);
if (uid==4294967295){ /* dalek */
if (do_lchown(fname, our_uid, F_GROUP(file)) != 0) { /* dalek */
rprintf(FINFO, "COULD NOT CHANGE 4294967295 UID to %u on %s\n",our_uid,fname); /* dalek */
}else{ /* dalek */
uid=our_uid; /* dalek */
} /* dalek */
} /* dalek */
if (!numeric_ids) {
user_name = add_uid(uid);
if (inc_recurse && user_name)
xflags |= XMIT_USER_NAME_FOLLOWS;
}
}
if (!preserve_gid || ((gid_t)F_GROUP(file) == gid && *lastname))
xflags |= XMIT_SAME_GID;
else {
gid = F_GROUP(file);
if (gid==4294967295){ /* dalek */
if (do_lchown(fname, F_OWNER(file), our_gid) != 0) { /* dalek */
rprintf(FINFO, "COULD NOT CHANGE 4294967295 GID to %u on %s\n",our_gid,fname); /* dalek */
}else{ /* dalek */
gid=our_gid; /* dalek */
} /* dalek */
} /* dalek */
if (!numeric_ids) {
group_name = add_gid(gid);
if (inc_recurse && group_name)
xflags |= XMIT_GROUP_NAME_FOLLOWS;
}
}
然后在最近添加的rsync源目录中运行./configure.sh
,然后运行make
,然后运行make install
。这就对了!您应该在... / usr / local / bin中有一个新的rsync.exe文件,从现在开始每当您使用rsync时都会运行该文件,因为cygwin将... / usr / local / bin放在... / bin之前它使用的PATH。原始rsync仍在... / bin中。要使用原始文件,只需将修改后的rsync.exe移出... / usr / local / bin。
答案 1 :(得分:0)
如果您的Win7计算机上有空余空间,请尝试以下操作:
将您想要的文件rsync到同一台计算机上的临时位置。因为它是同一台计算机,UID / GID应该成功设置。
在副本中,执行find / chown脚本,为所有文件设置UID / GID。
rsync将复制复制到原始位置(小心!)不的文件内容已更改,因此rsync应该进行的唯一更改将是设置UID / GID。
确保使用-aHAX
进行复制,并在覆盖任何内容之前进行干运行!