追記: 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したあと, mv
やcp -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))