読者です 読者をやめる 読者になる 読者になる

Fabricを使ってリモートサーバーでコマンドを実行する

Python

Python版のCapistranoと言われて久しいFabricだけど、ドキュメント通りにやっても全く動かなかった経験があるのでずっとスルーしてきた。

PyPIに上がっている0.9というバージョンは、まずまず動くので検討する価値がある。インストールはいつも通り、

$ pip install Fabric

基本的なこと

Fabricをインストールするとfabというスクリプトがインストールされるので、

$ fab -H localhost -f fabfile.py <command>

のようにして実行する。fabfile.pyは設定ファイルの名前だが、fabfile.pyという名前で設定ファイルを保存しておけば省略できる。-Hオプションはホスト名の指定。

オプションの詳細は--helpで確認。

$ fab --help

チュートリアルをざっと眺めれば使い方とできることをだいたい把握できるはず。

チュートリアルの次は、

がよい。

ローカルサーバーでコマンドを実行する

from fabric.api import local

def local_date():
    local('/bin/date')

のようなfabfile.pyをつくり、

$ fab local_date

でコマンドを実行。

リモートサーバーでコマンドを実行

from fabric.api import run, env

env.hosts = ['example.com', 'example.org']

def remote_date():
    run('/bin/date')

のようなfabfile.pyをつくり、

$ fab remote_date

で実行。上の例ではenv.hostsを使ってfabfile.py内でホストを指定しているが、コマンドラインからホストを指定することもできる。その場合は前述の通り、

$ fab -H host1.example.com,host2.example.com remote_date

のように-Hオプションで指定。

リモートサーバーでsudoを行う

from fabric.api import sudo

def yum_update():
    sudo('yum update', pty=True)

ptyオプションに注意。

rootではなく別ユーザーで実行したい場合は、

from fabric.api import sudo

def mogilefsd_start():
    sudo('/usr/sbin/mogilefsd', user='mogile', pty=True)

のようにuserオプションにユーザ名を指定する。

ファイルをアップロード/ダウンロード

putでローカルサーバーからリモートサーバーへファイルをアップロード。getでリモートサーバーからファイルをダウンロード。

from fabric.api import local, put, get

def put_and_get():
    local('date > /tmp/local.txt')
    put('/tmp/local.txt', '/tmp/remote.txt')
    get('/tmp/remote.txt', '/tmp/remote2.txt')

確認を求める

fabric.contrib.consoleでユーザーに確認を求めることができる。

from fabric.contrib import console

def say_no():
    answer = console.confirm("Do you PHP?", default=False)
    print "Your answer", answer

で、say_noコマンドを実行すると、

$ fab -H localhost say_no
Do you PHP? [y/N]
Your answer False

Done.

Yes/Noではなく、直接文字列の入力を求めたい場合は、promptを使う。

from fabric.api import prompt

def say_ni():
    answer = prompt("Ni!")
    print "You say,", answer

プロジェクトディレクトリをrsyncする

fabric.contrib.project.rsync_projectを使うと便利。

from fabric.contrib import project

def rsync_test():
    remote_dir = '/path/to/directory'
    project.rsync_project(remote_dir, exclude=['*.pyc', '*~'])

上の例では、fabfile.pyを置いているディレクトリを、/path/to/directoryという名前でリモートサーバーへrsyncする。