web-dev-qa-db-ja.com

すべての変更がアトミックに表示されるようにrsyncディレクトリ

ローカルネットワークで頻繁に使用されるリポジトリのミラーリングを毎晩、毎週行っています。予期されるファイルがまだすべて存在しないため、rsyncの実行中に誰かが更新を試みて失敗したことがまれにあります。

all変更されたファイルが完了時に正しい名前でのみ表示されるようにrsyncを実行することは可能ですか? rsyncが各転送の進行中に一時的な.hiddenファイルを使用することを知っていますが、何らかの方法で完了するまで名前の変更を延期できますか?

または、--backupオプションを使用してすべての変更を1つのディレクトリに移動し、その後にそれらをアトミックに移動できるようですが、この機能を現在の機能とは逆に機能させたいと思います。

私はLinuxを利用しています。

7
mikebabcock

--link-dest=オプション。基本的には、新しいフォルダーを作成します。すべてのファイルは新しいフォルダーにハードリンクされます。すべてが完了したら、フォルダ名を入れ替えて古いものを削除できます。

カーネル/ VFSのサポートがないため、Linuxでこれを100%アトミックに実行することは不可能です。ただし、名前の交換は実際には2回のシステムコールで行われるため、完了までに1秒もかかりません。 Darwin(MAC/OSX)でのみ可能であり、HFSファイルシステムでexchangedataシステムコールを使用します。

4

rsyncバックアップ[ディスクへ]でも同様のことを行っていますが、バックアップの実行中にファイルを更新するデーモンが原因で同じ問題が発生しました。

多くのプログラムとは異なり、rsyncにはmanyさまざまなエラーコードがあります[manページ下部を参照]。興味深いのは2つです。

23-エラーによる部分的な転送
24-ソースファイルの消失による部分的な転送

Rsyncが転送を行っているときにこれらの状況の1つに遭遇した場合、それはただちに停止するわけではありません。それはスキップして、ファイルを続行しますcan転送します。最後に、戻りコードが表示されます。

したがって、エラー23/24が発生した場合は、rsyncを再実行してください。後続の実行ははるかに速く進みます。通常は、前の実行から欠落しているファイルを転送するだけです。最終的には、クリーンランが得られます(または得られるはずです)。

アトミックであることについては、転送中に「tmp」ディレクトリを使用します。次に、rsyncの実行がクリーンになったときに、名前を[原子的に] <date>に変更します

私は--link-destオプションも使用していますが、それを使用して差分バックアップを保持しています(例:--link-dest=yesterday for daily)

私自身は使用していませんが、--partial-dir=DIRを使用すると、隠しファイルによってバックアップディレクトリが乱雑になるのを防ぐことができます。名前変更がアトミックになるように、DIRがバックアップディレクトリと同じファイルシステム上にあることを確認してください

私はこれをPerlで行いますが、私はあなたの特定の状況についてもう少し詳細/正確に私が言っていることを要約するスクリプトを書きました。これはtcshに似た構文であり、[テストされていない、少し荒い]ですが、選択して独自のbashPerlpythonスクリプトを書き込むための擬似コードとして扱います。再試行回数に制限はありませんが、希望に応じて簡単に追加できます。

#!/bin/tcsh -f
# repo_backup -- backup repos even if they change
#
# use_tmp -- use temporary destination directory
# use_partial -- use partial directory
# use_delta -- make delta backup

# set remote server name ...
set remote_server="..."

# directory on server for backups
set backup_top="/path_to_backup_top"
set backup_backups="$backup_top/backups"

# set your rsync options ...
set rsync_opts=(...)

# keep partial files from cluttering backup
set server_partial=${remote_server}:$backup_top/partial
if ($use_partial) then
    set rsync_opts=($rsync_opts --partial-dir=$server_partial)
endif

# do delta backups
if ($use_delta) then
    set latest=(`ssh ${remote_server} ls $backup_backups | tail -1`)

    # get latest
    set delta_dir="$backup_backups/$latest"

    if ($#latest > 0) then
        set rsync_opts=($rsync_opts --link-dest=${remote_server}:$delta_dir)
    endif
endif

while (1)
    # get list of everything to backup
    # set this to whatever you need
    cd /local_top_directory
    set transfer_list=(.)

    # use whatever format you'd like
    set date=`date +%Y%m%d_%H%M%S`

    set server_tmp=${remote_server}:$backup_top/tmp
    set server_final=${remote_server}:$backup_backups/$date

    if ($use_tmp) then
        set server_transfer=$server_tmp
    else
        set server_transfer=$server_final
    endif

    # do the transfer
    rsync $rsync_opts $transfer_list $server_transfer
    set code=$status

    # run was clean
    if ($code == 0) then
        # atomically install backup
        if ($use_tmp) then
            ssh ${remote_server} mv $backup_top/tmp $backup_backups/$date
        endif
        break
    endif

    # partial -- some error
    if ($code == 23) then
        continue
    endif

    # partial -- some files disappeared
    if ($code == 24) then
        continue
    endif

    echo "fatal error ..."
    exit(1)
end
4
Craig Estey

ミラー同期は自動ですか(cronタスクなど)?もしそうなら、おそらくあなたはこれのために専用のOSユーザーを使用しています、そうですか?したがって、解決策は単にコピーするのではなく、

  1. rsyncのみがアクセスできるように、宛先ディレクトリの権限を設定します。
  2. 同期を続行します。
  3. ターゲットの権限を(無条件に)変更して、他のユーザーが再びアクセスできるようにします。

欠点は、同期プロセス中(所要時間は不明)、ターゲットディレクトリにアクセスできないことです。ここで問題ないかどうかを自分で決める必要があります。

1
sam_pan_mariusz

これが役立つかどうかはわかりませんが...

毎回データセット全体をコピーしてもかまわない場合andシンボリックリンクを使用してターゲットディレクトリを参照できる場合は、すべてを一時ディレクトリにrsyncしてからスワップ(rename())新旧のシンボリックリンクをアトミックに次のように記述します。

_% mkdir old_data new_data
% ln -s old_data current
% ln -s new_data new
% strace mv -T new current
_

走る

rename("new", "current") = 0

そして与える

_current -> new_data
_

これが機能する場合でも、この設定から読み取ろうとするすべてのクライアントは、読み取りを試みる前に、シンボリックリンクによって参照されるディレクトリにcdする必要があります。そうしないと、古いコピーから一部のコード/データと新しいもの。

1
Karol Nowak