我已經複製了數 TB 的文件,rsync
但我忘記使用它--archive
來保留文件的特殊屬性。
rsync
這次我再次嘗試執行--archive
,但速度比我預期的要慢得多。有沒有簡單的方法可以透過遞歸複製元資料來更快地完成此操作?
答案1
好的,您可以使用參數將擁有者、群組、權限和時間戳複製--reference
到chown
, chmod
, touch
。這是一個執行此操作的腳本
#!/bin/bash
# Filename: cp-metadata
myecho=echo
src_path="$1"
dst_path="$2"
find "$src_path" |
while read src_file; do
dst_file="$dst_path${src_file#$src_path}"
$myecho chmod --reference="$src_file" "$dst_file"
$myecho chown --reference="$src_file" "$dst_file"
$myecho touch --reference="$src_file" "$dst_file"
done
您應該使用sudo
(以允許 chown)和兩個參數來運行它:來源目錄和目標目錄。該腳本僅回顯它將執行的操作。如果滿意,請更改myecho=echo
線路myecho=
。
答案2
將問題視為「rsync 只需要複製元數據,那麼為什麼它這麼慢,以及如何使其更快?」:
rsync
通常使用相等的 mtime 作為啟發式來偵測並跳過未變更的檔案。如果沒有--archive
(特別是沒有--times
),目標檔案的 mtime 仍設定為您對它們進行 rsync 的時間,而原始檔案的 mtime 則保持不變(忽略您的手動欺騙)。如果沒有來自您的外部保證來源檔案的內容沒有更改,rsync 必須假設它們可能已經更改,因此必須對它們進行校驗和和/或再次將它們複製到目標。這一點,再加--whole-file
上本地->本地同步隱含的事實,使得rsync
沒有--times
大致相當於cp
本地同步。
如果更新目標檔案的內容是可以接受的,或者如果原始檔案自原始副本以來沒有受到任何影響,您應該會發現rsync --archive --size-only
比簡單的 rsync 更快。
如果您對rsync
複製的內容有疑問,需要花費這麼長時間,rsync --archive --dry-run --itemize-changes ...
我們會以詳盡而簡潔的方式告訴您。
答案3
警告:如果沒有特殊的解決方法,GNUcp --attributes-only
將截斷目標文件,至少在 Precise 中是如此。請參閱下面的編輯。
原來的:
在這種情況下,您可能需要 GNU cp 的--attributes-only
選項以及 ,--archive
因為它是經過嘗試和測試的程式碼,執行所有與檔案系統無關的屬性並且不遵循符號連結(遵循它們可能會很糟糕!):
cp --archive --attributes-only /source/of/failed/backup/. /destination/
與檔案一樣,cp
它與擴充屬性相加:如果來源和目標都具有擴充屬性,則它添加來源的擴充屬性到目標(而不是先刪除目標的所有 xattrs)。雖然這反映了cp
將文件複製到現有樹中時的行為方式,但它可能不是您所期望的。
另請注意,如果您第一次沒有保留硬鏈接,rsync
但現在想保留它們,那麼cp
慣於為你解決這個問題;您可能最好rsync
使用正確的選項重新運行(請參閱我的其他答案)並保持耐心。
如果您在尋找時發現這個問題故意地分離並重新組合元資料/文件內容,那麼您可能想看看元儲存它位於 Ubuntu 儲存庫中。
編輯新增:
cp
GNU coreutils
>= 8.17 及以上版本將按描述工作,但 coreutils <= 8.16 將在恢復元資料時截斷檔案。如有疑問,請勿cp
在這種情況下使用;rsync
與使用正確的選擇和/或要有耐心。
除非你完全理解你在做什麼,否則我不會建議這樣做,但是早期的 GNUcp
可以使用以下命令來阻止截斷檔案:LD_PRELOAD技巧:
/*
* File: no_trunc.c
* Author: D.J. Capelis with minor changes by Zak Wilcox
*
* Compile:
* gcc -fPIC -c -o no_trunc.o no_trunc.c
* gcc -shared -o no_trunc.so no_trunc.o -ldl
*
* Use:
* LD_PRELOAD="./no_trunc.so" cp --archive --attributes-only <src...> <dest>
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <bits/fcntl.h>
extern int errorno;
int (*_open)(const char *pathname, int flags, ...);
int (*_open64)(const char *pathname, int flags, ...);
int open(const char *pathname, int flags, mode_t mode) {
_open = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open");
flags &= ~(O_TRUNC);
return _open(pathname, flags, mode);
}
int open64(const char *pathname, int flags, mode_t mode) {
_open64 = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64");
flags &= ~(O_TRUNC);
return _open64(pathname, flags, mode);
}
答案4
在本機傳輸中,當來源和目標位於本機安裝的檔案系統上時,rsync
將始終複製整個檔案內容。為了避免這種情況,你可以使用
rsync -a --no-whole-file source dest