更好的方式`chowning`未知的uid / gid的文件`rsync`(包括一个–exclude-from文件)将被视为源文件

我正在尝试更改我的rsync命令在执行我的rsync命令之前将其视为源文件的未知uid和gid。

我的rsync命令包含一个排除文件。

我需要这样做的原因在我的问题中解释。

我试过这个find命令:

 find /cygdrive/f -uid 4294967295 -exec chown 544. '{}' + -o -gid 4294967295 -exec chown .197121 '{}' + 

但是,它不处理排除文件。 通过我的意思是,上面的findsearch所有的f驱动器匹配未知的uid / gid的文件,然后chowns它们chowns 。 我的rsync查看驱动器f并复制除了排除文件中的文件以外的所有文件。 我不想chown rsync不能复制的任何Win7端文件。

例如,Win7保护一些隐藏/ sys文件的方法之一是将其uid和gid设置为4294967295(例如c:\ pagefil.sys和c:\ hiberfil.sys)。 我已经在rsync排除文件中排除了这两个文件,而且我想单独离开他们的Win7 side uid / gid。 find命令会让他们chown

我也试图parsing一个ls列表,这可能工作,但非常缓慢。 由于我只处理Win7文件,我认为一个ls会适合parsing。

有没有更好的方法来解决我的问题之前,我在处理ls列表(或parsingfind输出) chowning脚本之前?

另一种更精确的方式,但速度慢,需要一个更困难的脚本,我将parsingrsync --dry-run ...列表来找出哪些项目需要chowning

编辑rsync --dry-run ... :不幸的是, rsync --dry-run ...不会产生无法设置UID / GID的干运行,所以这种方法是警告。

但是,我已经find了rsync的源代码,它在我看来,这将是很容易修改它,使UID / GID的可以设置为运行rsync命令的进程的UID和GID,如果坏在会话中findUID / GID。

任何人都可以给我一个什么工具,我需要在Win7的电脑上编译rsync源代码的总结?

这是源代码中的rsync.c(search“无法设置”):

  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; } 

我找到了两个解决基本问题的实用解决方案:

  1. 如果源和目标环境都使用rsync 3.1.0或更高版本,则有新的选项可用。 在这种情况下,我可以将这些选项添加到我的rsync命令:

    –usermap = 4294967295:544 –groupmap = 4294967295:197121

    感谢您Wayne Davison指导我去这些新的选择!

  2. 如果您的目标位置上存在较旧的rsync(如我正在使用我的WD MyCloud),则可以使用cygwin修改rsync源代码,如下所示。

    确保你的cygwin安装了gcc gcc-core perl makequilt

    在rsync站点下载最新的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之前它使用的路径。 原始的rsync仍然在… / bin中。 要使用原始文件,只需将已修改的rsync.exe移出… / usr / local / bin。

如果您的Win7计算机上有足够的空间,请尝试以下操作:

  1. rsync将您想要的文件放到同一台计算机上的临时位置。 因为它是UID / GID应该设置成功的同一台计算机。

  2. 在副本中做你的find / chown脚本来设置所有文件的UID / GID。

  3. rsync的拷贝原来的位置(小心!)文件的内容应该改变,所以rsync应该做的唯一的改变就是设置UID / GID。

确保你使用-aHAX做拷贝,并在覆盖任何东西之前做一个干运行!