LoginSignup
42
41

More than 5 years have passed since last update.

fabricで高速なファイル転送

Last updated at Posted at 2014-03-07

追記: http://qiita.com/NPoi/items/46364461f0ab76e986c3 のやり方の方がスマートですね!

fabricのputは遅くないですか?rsyncを使っちゃいましょう。画像やHTML、JSなど静的なファイルがたくさんあるディレクトリをまるごと転送するようなケースではfabricの実行時間が劇的に違うテクニックですのでご紹介します。(fabricをある程度使ってる人を想定させていただいております)

rootじゃないユーザでrsync

これはfabricから公式機能で提供されてるので簡単に使っちゃえます。

from fabric.contrib.project import rsync_project

@task
def hoge():
    rsync_project(
        local_dir='./mydir',
        remote_dir='/usr/local/destination/mydir',
        exclude=['.DS_Tore', '*.tmp'],
        delete=True
    )

rootユーザでrsync

rootじゃないユーザでrsyncしたあと, mvcp -rしてもいいんですが、差分だけ転送できるのが、rsyncのいいところですので、こんな関数を作ってみました。引数はrsync_projectにあわせてあります。

動作としては, /tmp/(ディレクトリ名のハッシュ値)/ に一度rsyncしてから、サーバ上でsudo rsyncしています。

fabtoolsのis_dir関数に依存してるので、pip install fabtoolsが必要です

import hashlib
from fabric.api import local, run, sudo
from fabric.contrib.project import rsync_project
from fabtools.files import is_dir

def root_rsync(local_dir, remote_dir, exclude=[], delete=False):
    def _end_with_slash(dir_path):
        if dir_path[-1] == '/':
            return dir_path
        else:
            return dir_path + '/'
    local_dir = _end_with_slash(local_dir)
    remote_dir = _end_with_slash(remote_dir)
    m = hashlib.md5()
    m.update(remote_dir)
    me = local('whoami', capture=True)
    remote_tmp_dir = '/tmp/%s/%s/' % (me, m.hexdigest())
    run('mkdir -p %s' % remote_tmp_dir)
    if is_dir(remote_dir):
        run('rsync -a %s %s' % (remote_dir, remote_tmp_dir))  # already exists
    rsync_project(
        remote_dir=remote_tmp_dir,
        local_dir=local_dir,
        exclude=exclude,
        delete=delete
    )
    sudo('rsync -a %s %s' % (remote_tmp_dir, remote_dir))
42
41
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
41