フォルダAをフォルダBに同期したいのですが、次の制限があります。
フォルダAには、何百ものフォルダに何千ものファイルと数百ギガバイトのファイルが含まれています。
フォルダBには、フォルダA(および必要なすべてのフォルダ)に最新の10 GB(または他の)ファイルが含まれており、フォルダAにある最新のファイルのファイルと構造を複製します。
同期が実行されるたびに、フォルダBはフォルダAの最新の10GBファイルに制限され、古いファイルは削除されます。
空のディレクトリはクリーンアップする必要がありますが、必要に応じて直接クリーンアップできます。
bashやOS X上で動作するより良いツールがある場合は、rsyncを介してこれを行う必要はありませんが、ログインセッションなしでスタンドアロンで実行できる必要があります。
答え1
#非推奨の場合は、コメントで理由を書き留めてください。本当に悪い!
私の意見で解決策を見つけました。
完全なコマンドラインは次のとおりです。 $ find . -type f -printf "%T@ %p %s\n"| sort -n -r | awk '{ i+=$3; if (i<=200000) {print $2}}' | tar -cvf toto.tar -T -&& ssh -n prd "rm -rf dir/*" && scp toto.tar prd:tmp/ && ssh -n prd "tar xvf tmp/toto.tar"
このコマンドはfindで始まり、現在のディレクトリ(サーバーAのディレクトリパスに合わせて調整する必要があります)からすべてのファイルを見つけ、3つのフィールドを印刷します。
- %T @ Unixタイムスタンプ印刷
find
%pは起動時にファイルパスを印刷します。- %s印刷ファイルサイズ(バイト)
- \nもちろん新しい行です。
次に、出力がソートされ、最初のフィールドがfind
数値のsort -n -r
逆順に並べ替えられ、Unixタイムスタンプが最新のエントリから最も古いエントリの順にソートされます。
サイズ制限を処理するには、サイズの合計が制限を下回るまでawk
出力の2番目のフィールドを印刷すると、少し役立ちます。sort
処理する各行について、3番目のフィールド(サイズ)の値をローカル変数として合計i
し、ソートされた出力の2番目のフィールドを印刷します(i
制限より小さい場合)。
tar -cvf toto.tar -T -
awk
出力で提供されるファイルのリストから、toto.tarというアーカイブが作成されます。
成功したら、まずサーバーBのバックアップを削除してからファイルをリモートscp toto.tar host:dir
サーバー(サーバーB)に転送ssh -n "tar xvf dir/toto.tar
し、ディレクトリ構造を維持しながら転送されたアーカイブの圧縮をリモートフォルダに解凍します。
以前のscpベースのソリューションはディレクトリ構造を維持していなかったため、この回答を編集しました。
これは、最大サイズが200kbの私のhomedirで実行された結果です。
$ rm toto.tar; find . -type f -printf "%T@ %p %s\n"| sort -n -r | awk '{ i+=$3; if (i<=200000) {print $2}}' | tar -cvf toto.tar -T -&& scp toto.tar prd:tmp/ && ssh -n prd "tar xvf tmp/toto.tar"
./.lesshst
./.viminfo
./scpplus
./.config/xfce4/desktop/icons.screen0-1350x650.rc
./.xsession-errors
./.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml
./.config/pulse/7f14833c645d4a6abb0beba68b79e0c0-default-source
./.config/pulse/7f14833c645d4a6abb0beba68b79e0c0-default-sink
./.cache/imsettings/log
./.cache/gpg-agent-info
./.ICEauthority
./.vboxclient-draganddrop.pid
./.vboxclient-seamless.pid
./.vboxclient-display.pid
./.vboxclient-clipboard.pid
./.dbus/session-bus/7f14833c645d4a6abb0beba68b79e0c0-0
./.cache/xscreensaver/xscreensaver-getimage.cache
./.config/xfce4/desktop/icons.screen0-1264x950.rc
./work/fpart-0.9.2/src/fpart
toto.tar 100% 170KB 170.0KB/s 00:00
./.lesshst
./.viminfo
./scpplus
./.config/xfce4/desktop/icons.screen0-1350x650.rc
./.xsession-errors
./.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml
./.config/pulse/7f14833c645d4a6abb0beba68b79e0c0-default-source
./.config/pulse/7f14833c645d4a6abb0beba68b79e0c0-default-sink
./.cache/imsettings/log
./.cache/gpg-agent-info
./.ICEauthority
./.vboxclient-draganddrop.pid
./.vboxclient-seamless.pid
./.vboxclient-display.pid
./.vboxclient-clipboard.pid
./.dbus/session-bus/7f14833c645d4a6abb0beba68b79e0c0-0
./.cache/xscreensaver/xscreensaver-getimage.cache
./.config/xfce4/desktop/icons.screen0-1264x950.rc
./work/fpart-0.9.2/src/fpart
最大の問題は、このソリューションがメインサーバーから最新の10gigデータを転送する前にバックアップフォルダを削除することです。最新のデータセットとバックアップデータセットに共通のファイル/ディレクトリが多い場合、効率はそれほど高くありません。しかし、これは実際のデータの最新の10gig(または何でも)を実際に追跡する非常に簡単な方法です(高速で汚れています)。
update2:退屈ですが、2番目の解決策を説明します。
最後に2番目の解決策を見つけました。それではこれについて説明します。コーディングにはあまり効率的ではありません。シェルスクリプトでフォーマットでき、エラーが発生したり、奇妙な形式のファイル名がある場合は、基本的なチェックを実行する大規模なオンラインプログラムです。
最初のソリューションの最大の問題は、常に最新のファイルの最後の10 GBをバックアップしようとしていることです。バックアップされた内容です。つまり、新しい起動時に新しいファイルが1億個しかない場合は、フルバックアップを消去して10Gデータを再送信します(最新の100M、新しい9.9G未満)。
これは一行です。
ssh -n prd 'cd /var/tmp/test/ && find . -type f -printf "%T@ %p %s\n" ' |awk '{ print int($1)" "$2" "$3 }'|sort -n -r >/tmp/remote ; find . -type f -printf "%T@ %p %s\n" |awk '{ print int($1)" "$2" "$3 }'|sort -n -r | awk '{ i+=$3; if (i<=200000) {print $1" "$2" "$3}}'>/tmp/locale; grep -F -x -v -f /tmp/remote /tmp/locale |cut -d" " -f2 >/tmp/newfile;grep -F -x -v -f /tmp/locale /tmp/remote |cut -d" " -f2 >/tmp/toremove; cat /tmp/toremove |while read i; do echo "removing $i on remote server"; ssh -n prd "rm /var/tmp/test/$i"; done ; cat /tmp/newfile | tar -cvf toto.tar -T -&& scp toto.tar prd:/var/tmp/test/ && ssh -n prd "cd /var/tmp/test; tar xvf /var/tmp/test/toto.tar; rm /var/tmp/test/toto.tar"; rm /tmp/remote /tmp/locale /tmp/toremove /tmp/newfile toto.tar
もちろん、prd
すべてのディレクトリパス(一時ファイル生成を除く)は、ローカル/リモートサーバーだけでなくサーバーBでも変更されます。ファイル名内にスペースや特殊文字を含むファイル名を処理しないように注意してください。
説明する:
主なアイデアは、バックアップされていないバックアップサーバーの最新のファイルが何であるかを把握することです。バックアップサーバーから古いファイルを消去し、サイズ制限を念頭に置いて、存在しない最新のファイルのみをバックアップサーバーに転送してください。
- まず、バックアップサーバーに接続してバックアップファイルのリストを取得します。 ;小数部を常にに設定する
ssh -n prd 'cd /var/tmp/test/ && find . -type f -printf "%T@ %p %s\n" ' |awk '{ print int($1)" "$2" "$3 }'|sort -n -r >/tmp/remote ;
問題のため、時々小数部を削除する必要があります。これは、バックアップサーバーとソースサーバーの日付が小数点以下であることを意味します。ソートは、最初のフィールドの最大値から最も低い値で構成されます。つまり、最新のファイルから最も古いファイルの順にソートされます。結果をファイルとして保存します。以前のバックアップでは常に10G未満で転送されたため、全体のサイズを確認する必要はありません。tar
0
/tmp/remote
- 次に、全体のサイズが制限より小さい最新のファイルのリストを取得するために、ローカルで同じことを行います。
find . -type f -printf "%T@ %p %s\n" |awk '{ print int($1)" "$2" "$3 }'|sort -n -r | awk '{ i+=$3; if (i<=200000) {print $1" "$2" "$3}}'>/tmp/locale;
結果を次の場所に保存します。/tmp/locale
したがって、実際に/tmp/locale
存在または存在しないすべてのファイルは、同期する/tmp/remote
バックアップサーバーの最新のファイルです。その内外のすべてのファイルは、
削除するバックアップサーバーのファイルです(古いファイル)。/tmp/remote
/tmp/locale
これらのサブセットを区別するには、次のものを使用しますgrep
。
grep -F -x -v -f /tmp/remote /tmp/locale |cut -d" " -f2>/tmp/newfile;
保存した埋め込み/tmp/locale
ファイルと含まれていないファイルの両方が表示されます。/tmp/remote
/tmp/newfile
grep -F -x -v -f /tmp/locale /tmp/remote |cut -d" " -f2 >/tmp/toremove;
/tmp/remote
含まれているファイルと含まれていないすべてのファイルが表示されます/tmp/locale
。/tmp/toremove
ディレクトリ構造を維持しながら、リモートで削除するファイルのリストとバックアップサーバーに転送するファイルのリストが作成されました。
tar
ビルドロケールアーカイブを使用してバックアップを送信し、古いファイルをリモートで削除し、アーカイブを転送し、解凍します。
そして私たちはほぼ終わりました。/tmp
クリーンアップのために一時ファイルを削除します。
詳細は次のとおりです。
cat /tmp/toremove |while read i; do echo "removing $i on remote server"; ssh -n prd "rm /var/tmp/test/$i"; done ;
このループはiファイルのリストを入力として読み込み、削除したファイルを知らせる小さなメッセージを表示し、次からcat
リモートを起動します。rm
ssh
cat /tmp/newfile | tar -cvf toto.tar -T -&& scp toto.tar prd:/var/tmp/test/ && ssh -n prd "cd /var/tmp/test; tar xvf /var/tmp/test/toto.tar; rm /var/tmp/test/toto.tar";
にリストされているすべてのファイルを含むロケールtoto.tar
アーカイブが作成されます/tmp/newfile
。成功したら、リモートサーバーに送信し、リモートで解凍し、次のブートを妨げssh
ないようにバックアップサーバーのアーカイブも削除します。
rm /tmp/remote /tmp/locale /tmp/toremove /tmp/newfile toto.tar
この起動時に使用されたファイルのローカルクリーンアップ。
このオンラインプログラムは一時ファイルの使用を排除し、出力をgrep
ループwhile
とtar
コマンドに直接パイプすることで短縮できます。
scp
また、すべてのコマンドの戻り状態(アーカイブを構築するのに十分な場所ではないか、ssh
エラー...)と奇妙なファイル名(パラメータ拡張の混乱を避けるためにスペースや特殊文字を含む)を処理するように改善することもできます。
答え2
最近同様の問題が発生しました。私が終わったのはfind + rsyncでした。
#!/usr/bin/env bash
# first prepare the file list I want to sync
find /path -mtime 7 -other-conditions-you-want > /tmp/file.list.$$
rsync --file-from=/tmp/file.list.$$ /source /dest
もちろん、ファイルがリモートサーバーにある場合は、リモートで検索を実行し、 --file-from=:/tmp/file.list.$$ を使用して、次のようにリモートからファイルのリストを取得する必要があります。
ssh "$_SOURCE_HOST" "cd '$_SOURCE_PATH'; find . $MMIN_FLAG -type f > /tmp/$_NAME-$TOKEN"
rsync "--files-from=:/tmp/$_NAME-$TOKEN" "$_SOURCE" "$_DEST"
ssh "$_SOURCE_HOST" "rm -f /tmp/$_NAME-$TOKEN"
bashのようにrm
コマンドを設定して、trap
ファイルを最後に削除することができます。