既にテラバイトのファイルをrsync
でコピーしましたが、--archive
を使用してファイルの特別な属性を保存するのを忘れていました。
今回は--archive
でrsync
を再度実行しようとしましたが、予想よりもずっと遅くなりました。メタデータを再帰的にコピーするだけで、これを簡単に行う方法はありますか?
わかりました。--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を許可するため)および2つのパラメーター:sourceおよびdestinationディレクトリで実行する必要があります。スクリプトは、実行内容をエコーするだけです。満足したら、行myecho=echo
をmyecho=
に変更します。
質問を「rsyncはコピーするメタデータのみを持っているので、なぜそんなに遅いのですか、どうすれば速くできますか?」:
rsync
は、通常、未変更のファイルを検出してスキップするためのヒューリスティックとして等しいmtimesを使用します。 --archive
がない場合(具体的には--times
がない場合)、宛先ファイルのmtimesはrsync-edした時刻に設定されたままで、ソースファイルのmtimesはそのままです(手動によるトリックは無視されます)。ソースファイルのコンテンツが変更されていないことを外部から保証しない場合、rsyncはファイルが存在する可能性があると想定するため、それらをチェックサムしたり、コピー先にコピーしたりする必要があります。これに加えて、ローカル同期で--whole-file
が暗示されるという事実により、--times
なしのrsync
は、ローカル同期のcp
とほぼ同等になります。
宛先ファイルのコンテンツの更新が許容される場合、またはソースファイルが元のコピー以降に変更されていない場合は、単純なrsyncよりもrsync --archive --size-only
をすばやく見つける必要があります。
rsync
のコピーに時間がかかっていることが疑わしい場合、rsync --archive --dry-run --itemize-changes ...
は、簡潔な場合でも、詳細を網羅的に示します。
警告:特別な回避策がなければ、GNU cp --attributes-only
は少なくとも正確に宛先ファイルを切り捨てます。以下の編集を参照してください。
オリジナル:
この状況では、おそらくGNU cpの--attributes-only
オプションと--archive
が必要です。コードが試行およびテストされているため、ファイルシステムに依存しない属性をすべて実行し、シンボリックリンクをたどりません(以下を参照)それらは悪い場合があります!):
cp --archive --attributes-only /source/of/failed/backup/. /destination/
ファイルの場合と同様に、cp
は拡張属性を使用して追加できます。ソースと宛先の両方に拡張属性がある場合、addsソースの拡張属性を宛先に追加します(最初に宛先のすべてのxattrsを削除するのではなく)。これは、既存のツリーにファイルをコピーした場合のcp
の動作をミラーリングしますが、期待どおりではない場合があります。
また、最初にrsync
でハードリンクを保存しなかったが、今すぐそれらを保存したい場合は、cp
はそれを修正しませんあなたのために;おそらく、rsync
を適切なオプション(私の その他の回答 を参照)で再実行し、忍耐強い方がよいでしょう。
意図的に分離してメタデータ/ファイルのコンテンツを再結合しているときにこの質問を見つけた場合は、Ubuntuにある metastore を見てみたいかもしれませんリポジトリ。
ソース: GNU coreutils manual
追加するために編集:
cp
from GNU coreutils
> = 8.17以降は説明どおりに機能しますが、coreutils <= 8.16はメタデータの復元時にファイルを切り捨てます。疑わしい場合は、この状況でcp
を使用しないでください。 rsync
を 正しいオプション とともに使用する、および/または我慢してください。
あなたが何をしているかを完全に理解していない限り、これはお勧めしませんが、以前のGNU cp
は 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);
}
ローカル転送では、ソースと宛先がローカルにマウントされたファイルシステムにある場合、rsync
は常にファイルの内容全体をコピーします。これを回避するには、次を使用できます
rsync -a --no-whole-file source dest
これを別のコンピューターにリモートで実行する必要があったため、-referenceを使用できませんでした
これを使ってスクリプトを作成しました...
find -printf "touch -d \"%Tc\" \"%P\"\n" >/tmp/touch.sh
ただし、最初に「」が含まれるファイル名がないことを確認してください...
find | grep '"'
次に、touch.shをリモートコンピューターにコピーして、実行します...
cd <DestinationFolder>; sh /tmp/touch.sh
Find -printfには、ユーザー、グループ名をコピーする場合にそれらを印刷するオプションもあります。