2015-12-10 27 views
0

我想改變未知的uid和gid的文件,我的rsync命令會考慮作爲源文件,然後執行我的rsync命令。我的rsync命令包含排除文件。更好的方式'chowning`未知的uid/gid的文件`rsync`(包括--exclude-from文件)將被視爲源文件

我需要這樣做的原因在我的問題here中有解釋。

我已經試過這find命令:

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

,但它不處理排除文件。我的意思是,上面的find搜索f驅動器的所有文件匹配未知的uid/gid,然後chowns他們。我的rsync查看驅動器f並複製除排除文件中的文件以外的所有文件。我不想chown任何不復制的Win7副文件。例如,Win7保護一些隱藏/ sys文件的方法之一是將其uid和gid設置爲4294967295(例如c:\ pagefil.sys和c:\ hiberfil.sys)。我排除了rsync排除文件中的這兩個文件,並且我想單獨離開它們的Win7端uid/gid。它們的find命令將會是chown

我也試圖解析一個ls列表,這可能工作,但非常緩慢。由於我只處理Win7文件,我認爲ls將適合解析。

chowning腳本之前使用ls列表(或解析find輸出)之前有沒有更好的方法來解決我的問題?

另一種更精確的方式,但速度較慢,需要一個更難的腳本,我會解析一個rsync --dry-run ...列表來找出哪些項目需要chowning

編輯2015-12-13:不幸的是,rsync --dry-run ...不會產生關於在空運行期間無法設置UID/GID的警告,因此該方法不適用。

但是,我發現了rsync的源代碼,它在我看來很容易修改它,以便UID/GID可以設置爲運行rsync的進程的UID和GID命令,如果在會話期間找到錯誤的UID/GID。

任何人都可以給我一個總結,我需要什麼工具來編譯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

你是什麼意思「它不處理排除文件」。 –

+0

查找如所示對所有找到的文件進行操作,但rsync將作用於相同的文件集減去該文件集中與排除文件中的任何規則匹配的任何文件 – KiloOne

+0

對不起,如果這是令人困惑的答案。上面的查找搜索f驅動器的所有文件,查找匹配未知uid/gid的文件,然後放入它們。 rsync查看驅動器f並複製除了排除文件中的文件以外的所有文件。我不想顯示rsync不傳輸的任何文件。 – KiloOne

回答

1

我發現,解決基礎問題上有兩個實用的解決方案:

  1. 如果源和目標環境使用rsync 3.1.0或更新的版本,有新的可用選項。在這種情況下,我可以添加這些選項到我的rsync命令:

    --usermap = 4294967295:544 --groupmap = 4294967295:197121

    感謝信韋恩·戴維森指導我對這些新的選擇!

  2. 如果你在目的地(如我使用我的WD MyCloud)時遇到舊的rsync,可以使用cygwin修改rsync源代碼,如下所示。

    確保您的cygwin的安裝與gccgcc-coreperlmakequilt

    下載最新rsync源tar文件在rsync site

    我解壓,要在我的〜目錄下的文件夾。

    我下載Eclipse作爲一個IDE使用,但你可以只修改這些文件與NotePad++如下:

    在我還說,你看每次運行rsync的,所以你知道時間信息線main.c文件您正在使用您的個人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,加我的/ * *戴立克/線路如下:

    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文件,因爲cygwin將.../usr/local/bin放在.../bin的前面它使用的PATH。原始的rsync仍然在.../bin中。要使用原始文件,只需將修改後的rsync.exe移出.../usr/local/bin。

0

如果您的電腦的Win7的重要空間,試試這個:

  1. 將您想要的文件rsync同步到同一臺計算機上的臨時位置。因爲它是UID/GID應該成功設置的同一臺計算機。

  2. 在副本做查找/ CHOWN腳本來設置UID/GID爲所有文件。

  3. rsync的副本到原來的位置(小心!)文件的內容應已經改變,所以唯一變化的rsync應該會設置UID/GID。

請確保您使用-aHAX來完成副本,並在覆蓋任何內容之前進行幹運行!

+0

這是一個非常好的建議,但它很麻煩,而且不像改變源代碼和重新編譯rsync這樣我現在已經完成和正在測試的實用程序,我很快就會發布該答案。每次運行時,修改後的rsync都會檢查並清空剛出現的未知文件(如果需要的話)。 – KiloOne

+0

開源FTW! – ams