web-dev-qa-db-ja.com

まだ書き込まれているファイルでのrsyncの動作?

Apacheが大きなファイルを書き込んでいる最中にrsync cronジョブがそのファイルで実行されている場合、rsyncはファイルをコピーしようとしますか?

  • Apache-1:大きなファイルが/var/wwwに書き込まれています。
  • Apache-2:Apache-1のクローン。 5分ごとにcronがrsyncを実行して/var/wwwを同期させます。
13
Louis Waweru

Apacheが1か所にある種類のファイルを書き込んでいて、その書き込みを完了していない場合、次にrsync 起動します、rsyncはそこにあるものをすべてコピーします。

つまり、Apacheが5MBのファイルを処理している場合、2MBのみが書き込まれ、rsyncが起動し、部分的な2MBファイルがコピーされます。そのため、そのファイルは宛先サーバーで「破損」しているように見えます。

使用しているファイルのサイズに応じて、rsync--inplaceオプションを使用して以下を実行できます。

このオプションは、ファイルのデータを更新する必要があるときにrsyncがファイルを転送する方法を変更します。ファイルの新しいコピーを作成し、完了時にファイルを所定の場所に移動するデフォルトの方法ではなく、rsyncが更新されたデータを宛先に直接書き込みますファイル。

これの利点は、5MBのファイルが最初の実行で2MBしかコピーされない場合、次の実行は2MBで取得され、完全な5MBが配置されるまでファイルをコピーし続けます。

否定的な点は、ファイルのコピー中に誰かがWebサーバーにアクセスして、部分的なファイルが表示されるという状況が発生する可能性があることです。私の意見では、rsyncは、「非表示」ファイルをキャッシュしてすぐに所定の場所に移動するというデフォルトの動作で最適に機能します。ただし、--inplaceは、サイズの大きなファイルや帯域幅の制約により、サイズの大きなファイルを正方形のファイルから簡単にコピーできない場合に適しています。

それはあなたがこれを述べていると言った;強調は私のものです:

5分ごとにcronがrsyncを実行しています…

それで、このcronジョブを管理するためのbashスクリプトがあると思いますか?そうですね、rsyncは、コピーする必要のあるファイルのみをコピーするのに十分スマートです。そして、5分ごとに実行されるスクリプトがある場合、それが速くなる場合は、互いにrsyncステップを実行しないようにしようとしているようです。つまり、毎分実行した場合、ファイルサイズまたはネットワーク速度が原因で、1つ以上のrsyncプロセスがまだ実行されており、次のプロセスがそれと競合しているというリスクがあります。レース状態。

これを回避する1つの方法は、ファイルロックをチェックするbashスクリプトでrsyncコマンド全体をラップすることです。以下は、このような場合に使用する定型bashスクリプトフレームワークです。

一部の人々はflockの使用を推奨しますが、flockは私が使用する一部のシステムにインストールされていないため、Ubuntu(ある)とMac OS X(ない)の間でジャンプします。ロット—私はこの単純なフレームワークを実際の問題なしに使用しています:

LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'

if mkdir ${LOCK_DIR} 2>/dev/null; then
  # If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
  echo $$ > ${PID_FILE}

  echo "Hello world!"

  rm -rf ${LOCK_DIR}
  exit
else
  if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
    # Confirm that the process file exists & a process
    # with that PID is truly running.
    echo "Running [PID "$(cat ${PID_FILE})"]" >&2
    exit
  else
    # If the process is not running, yet there is a PID file--like in the case
    # of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
    rm -rf ${LOCK_DIR}
    exit
  fi
fi

アイデアは、_echo "Hello world!"のある一般的なコアがスクリプトの中心であるということです。残りは基本的にmkdirに基づくロックメカニズム/ロジックです。コンセプトの良い説明 この回答にあります

mkdirは、ディレクトリがまだ存在しない場合は作成し、存在する場合は終了コードを設定します。さらに重要なことは、このすべてを1つのアトミックアクションで実行することで、このシナリオに最適です。

したがって、rsyncプロセスの場合は、echoコマンドをrsyncコマンドに変更するだけでこのスクリプトを使用することをお勧めします。また、LOCK_NAMERSYNC_PROCESSのように変更すれば、問題ありません。

rsyncをこのスクリプトにラップすると、2つ以上のrsyncプロセスが同じことを実行するために競合する競合状態のリスクなしに、毎分実行するようにcronジョブを設定できます。これにより、速度の向上やrsyncの更新が可能になり、部分的なファイルの転送の問題が解消されませんが、プロセス全体の速度が向上し、ファイル全体を適切にコピーできるようになります。

21
JakeGould

はい。ファイルへの書き込みと同時にrsyncがファイルを読み取っていると、ファイルが破損する可能性があります。

あなたはこれを試すことができます: https://unix.stackexchange.com/a/2558

Lsofを使用してスクリプトを作成することもできます。

lsof /path/to file

終了コード0はファイルが使用中であることを意味し、終了コード1はそのファイルにアクティビティがないことを意味します。

3
rebelshrug