コンテキストマネージャー

コンテキストマネージャーは with とともに使用します。

ノート

Python 2.5の利用時、 with ステートメントを利用するためにはfabfileを from __future__ import with_statement から始める必要があります(Python 2.6以上では通常の非 non __future__ 機能です)。

ノート

ダイレクトにネストされている複数の with ステートメントを使用する場合、1つのwithステートメント内に複数のコンテキスト表現を用いたほうが便利なことがあります。次のように書く代わりに:

with cd('/path/to/app'):
    with prefix('workon myvenv'):
        run('./manage.py syncdb')
        run('./manage.py loaddata myfixture')

次のように書くことができます:

with cd('/path/to/app'), prefix('workon myvenv'):
    run('./manage.py syncdb')
    run('./manage.py loaddata myfixture')

このようにするにはPython 2.7以上が必要です。Python 2.5もしくは2.6では次のようにします:

from contextlib import nested

with nested(cd('/path/to/app'), prefix('workon myvenv')):
    ...

最後に settingsnested 自身を実装していることに留意してください。詳しくはこのAPIドキュメントをご覧ください。

fabric.context_managers.cd(path)

コンテキストマネージャーはリモート操作を呼び出すときにはディレクトリの状態を維持します。

これでラップされたブロック内の runsudogetput へのどんな呼び出しも、実際に状態が維持されているという意味を持たせるために "cd <path> && " がプリフィックスされたのと似た文字列を暗に含みます。

ノート

cdリモート のパスでのみ作用します。 ローカル パスを変更するには lcd を使います。

cd の利用はこうしたすべての実行に影響を与えるので、contrib セクションの多くなど、うした操作を行うコードもまた cd の利用に影響を受けます。

実際のシェルビルトインの cd のように、 cd は相対パスで呼び出すことができ(最初のディレクトリのデフォルトはリモートユーザーの $HOME であることに気をつけてください)、ネストすることも可能です。

下の例はシェルの cd を使った “ノーマルな” 試みで、 run もしくは sudo の実行と実行の間の状態が維持 されない というシェルなしSSH接続の実装のため動作しません。

run('cd /var/www')
run('ls')

上の例は /var/www ではなく、リモートユーザーの $HOME のコンテンツの一覧を表示します。cd とともに使うと期待通りに動作します:

with cd('/var/www'):
    run('ls') # Turns into "cd /var/www && ls"

最後に、ネストの例(インラインのコメントをご覧ください)をお見せします:

with cd('/var/www'):
    run('ls') # cd /var/www && ls
    with cd('website1'):
        run('ls') # cd /var/www/website1 && ls

ノート

このコンテキストマネージャーは環境変数のカレントの値、 env.cwd に追加することによって実装されています(そして、いつものようにその後もとの状態にもどします)。とは言え、この実装は将来的には変更されるかもしれませんので、手動で env.cwd に変更することはおすすめしません。後方互換性を保証するのは cd挙動 のみです。

ノート

空白文字を含むディレクトリ名を扱うため、空白文字は自動的にエスケープされます。

バージョン 1.0 で変更: コマンドでの操作に加え、 getput にも適用されます。

参考

lcd

fabric.context_managers.char_buffered(*args, **kwds)

ローカルターミナルの パイプ を行ごとではなく文字ごとに強制的にバッファします。

ユニックスベースのシステムのみの適用されます。Windowsでは操作できません。

fabric.context_managers.hide(*args, **kwds)

与えられた出力 groups をFalseにセットするためにコンテキストマネージャー。

groupsoutput で定義された出力グループを命名している1つ以上の文字列でなければなりません。与えられたグループは、囲まれたブロックでの継続性のためFalseにセットされ、その後は前の状態に戻ります。

例えば、 “[hostname] run:” のステータスラインを隠し、同じように標準出力と標準エラー出力を表示させないようにするには、次のように hide を利用することができます:

def my_task():
    with hide('running', 'stdout', 'stderr'):
        run('ls /var/www')
fabric.context_managers.lcd(path)

ローカルのカレントワーキングディレクトリを更新するためのコンテキストマネージャー。

このコンテキストマネージャーは cd と同じですが、別の環境変数(cwd ではなく lcwd)を変更するので、 local の実行と get/put へのローカルの引数のみに影響を与えます。

相対パスの引数はローカルユーザーのカレントのワーキングディレクトリに対する相対になり、Fabric(もしくはFabricを使うコード)がどこで実行されるかによって違ってきます。これは os.getcwd で確認できます。fabfileが利用されている場所からの相対に固定すると便利かもしれません。それは env.real_fabfile で確認できます。

バージョン 1.0 で追加.

fabric.context_managers.path(path, behavior='append')

ラップされたコマンド実行するために使われるパスに与えられた path を追加します。

これで囲まれたブロック内の run もしくは sudo に対するどんな呼び出しも、与えられたコマンドの前に "PATH=$PATH:<path> " に似た文字列を暗黙のうちに追加されます。

次のように、オプションの behavior キーワード引数を指定することによって path の挙動をカスタマイズできます:

  • 'append': カレントの $PATH に与えられたパスを追加します。例えば PATH=$PATH:<path> です。これはデフォルトの挙動になります。

  • 'prepend': カレントの $PATH に与えられたパスを前に追加します。例えば PATH=<path>:$PATH です。

  • 'replace': $PATH の前の値を完全に無視します。例えば PATH=<path> となります。

ノート

このコンテキストマネージャーは、環境変数 env.pathenv.path_behavior のカレントの値を変更する(そしていつものようにその後に元に戻す)ように今は実装されています。しかし、この実装は将来的には変更されるかもしれないので直接手動で変更することはおすすめしません。

バージョン 1.0 で追加.

fabric.context_managers.prefix(command)

囲まれたすべての run/sudo コマンドの前に、与えられたコマンドと && を追加します。

これは cd とほとんど同一ですが、1つの文字列を変更する代わりにコマンド文字列のリストに、ネストされた呼び出しが追加されます。

たいていの場合、シェル環境変数をエクスポートしたり変更するような、シェルの状態を変えるシェルスクリプトと一緒に使うといいでしょう。

例えば、このツールのもっとも一般的な利用方法の1つは virtualenvwrapper からの workon コマンドと使うものです:

with prefix('workon myvenv'):
    run('./manage.py syncdb')

上記の例では、実際のシェルコマンドの実行はこのようになります:

$ workon myvenv && ./manage.py syncdb

このコンテキストマネージャーは cd と互換性があるので、もし自分の virtualenv がその postactivate スクリプトで cd できないときは次ようにもできます:

with cd('/path/to/app'):
    with prefix('workon myvenv'):
        run('./manage.py syncdb')
        run('./manage.py loaddata myfixture')

これは、実行時には次のような結果になります:

$ cd /path/to/app && workon myvenv && ./manage.py syncdb
$ cd /path/to/app && workon myvenv && ./manage.py loaddata myfixture

最後に、冒頭近くで示唆したように、prefix はお好みのようにネストできます。例えば:

with prefix('workon myenv'):
    run('ls')
    with prefix('source /some/script'):
        run('touch a_file')

結果:

$ workon myenv && ls
$ workon myenv && source /some/script && touch a_file

不自然かもしれませんが、説明的だと思います。

fabric.context_managers.quiet()

settings(hide('everything'), warn_only=True) へのエイリアス。

時折失敗が予期されるかつ/もしくは何も表示させたくない疑問形のリモートコマンドをラップするときに便利です。

例:

with quiet():
    have_build_dir = run("test -e /tmp/build").succeeded

タスク内で使用されると、上記スニペットは run: test -e /tmp/build の行を生成せず、また、標準出力/標準エラー出力のまったく表示させず、コマンドの失敗は無視されます。

参考

env.warn_onlysettingshide

バージョン 1.5 で追加.

fabric.context_managers.remote_tunnel(*args, **kwds)

ローカルの開いているポートからリモートのターゲットにトンネルフォワーディングを作成します。

例えば、クライアントホストにインストールしてあるデータベースへリモートからアクセスさせます:

# Map localhost:6379 on the server to localhost:6379 on the client,
# so that the remote 'redis-cli' program ends up speaking to the local
# redis-server.
with remote_tunnel(6379):
    run("redis-cli -i")

データベースは、クライアントホストからのみ接続可能なクライアント上にインストールされているとします(クライアント自身の 上に あるのとは対照的に):

# Map localhost:6379 on the server to redis.internal:6379 on the client
with remote_tunnel(6379, local_host="redis.internal")
    run("redis-cli -i")

remote_tunnel は4個までの引き数を取ります:

  • remote_port (必須)リッスンするリモートホストのポート。

  • local_port (オプション) は接続するローカルのポートです。デフォルトはリモートのポートと同じポートです。

  • local_host (オプション) は接続するローカルで到達可能なコンピュータ(DNS名かIPアドレス)です。デフォルトは localhost です(これはつまり、Fabricが動いているのと同じコンピュータのことです)。

  • remote_bind_address (オプション) は、カレントターゲット上のリッスンするためにバインドするためのリモートのIPアドレスです。これはターゲット上のインターフェースに割り当てられたIPである必要があります(もしくはそうしたIPをリゾルブするDNS名)。すべてのインターフェースにバインドするには “0.0.0.0” を使います。

ノート

デフォルトでは、たいていのSSHサーバはリモートトンネルにローカルホストのインターフェース(127.0.0.1)をリッスンすることしか許可していません。こうしたケースでは remote_bind_address はサーバーによって無視され、トンネルは127.0.0.1だけをリッスンします。

fabric.context_managers.settings(*args, **kwargs)

コンテキストマネージャーをネストおよび/もしくは env 変数を上書きします。

settings には2つの目的があります:

  • もっとも便利なのが、 env を与えられるどんなキーワード引き数、例えば with settings(user='foo'): などで一時的に上書き更新できることです。元の値は、もしあればですが、with ブロックが閉じられると戻されます。

    • キーワード引き数 clean_revertsettings 自身にとっては特別な意味を持ち(下記参照)、実行前に取り除かれます。

  • 加えて、 contextlib.nested を使うと、与えられたどんな非キーワード引き数でもネストできます。これは他のコンテキストマネージャーである必要がありますが、例えば with settings(hide('stderr'), show('stdout')): などです。

これらの挙動は望めば同時に指定することも可能です。これがなぜ便利であるのかは例でわかりやすく説明します:

def my_task():
    with settings(
        hide('warnings', 'running', 'stdout', 'stderr'),
        warn_only=True
    ):
        if run('ls /etc/lsb-release'):
            return 'Ubuntu'
        elif run('ls /etc/redhat-release'):
            return 'RedHat'

上のタスクは run 命令文を実行しますが、もし ls が失敗した場合に中断するのではなく警告を出し、その警告自身を含めたすべての出力はユーザーには表示されません。その結果としてこのシナリオでは、通常であれば発生するたくさんの出力を発生させずに、リモートホストがどのシステムのタイプなのかを呼び出しが判別することができる完全に静かなタスクとなります。

したがって settings は、特定のレベルの出力を隠す(もしくは表示する)のとともに、もしくはコンテキストマネージャーとして実装された他のFabricの機能のひとつとともに、環境変数とのどんな組み合わせでもセットするために利用可能です。

clean_revertTrue にセットされると、settings はネストされたブロック内で変更されたキーは 元には戻しません 。その代わり、与えられたときと同じ値を持つキーだけを元に戻します。さらに例をご覧になるとより理解できるでしょう。以下は settings の通常の動作です:

# Before the block, env.parallel defaults to False, host_string to None
with settings(parallel=True, host_string='myhost'):
    # env.parallel is True
    # env.host_string is 'myhost'
    env.host_string = 'otherhost'
    # env.host_string is now 'otherhost'
# Outside the block:
# * env.parallel is False again
# * env.host_string is None again

env.host_string の内部での変更は取り消されていますが、これが常に希望の状態であるとは限りません。ここで clean_revert の登場です:

# Before the block, env.parallel defaults to False, host_string to None
with settings(parallel=True, host_string='myhost', clean_revert=True):
    # env.parallel is True
    # env.host_string is 'myhost'
    env.host_string = 'otherhost'
    # env.host_string is now 'otherhost'
# Outside the block:
# * env.parallel is False again
# * env.host_string remains 'otherhost'

clean_revert 有効時には settings の利用前に env に存在しなかった新しいキーも保存されます。False の時はこうしたキーはブロック終了時に取り除かれます。

バージョン 1.4.1 で追加: clean_revert キーワード引数。

fabric.context_managers.shell_env(**kw)

ラップされたコマンドのためのシェル環境変数をセットします。

例えば、以下はPythonのZMQライブラリをインストールするときに関連する環境変数をどのようにセットするのかをお見せしています:

with shell_env(ZMQ_DIR='/home/user/local'):
    run('pip install pyzmq')

prefix と同様に、これは実質的に run コマンドを以下に変更します:

$ export ZMQ_DIR='/home/user/local' && pip install pyzmq

複数のキーバリューペアを同時に与えることができます。

ノート

Windowsのローカルホストから実行したときに local の挙動に営業が出る場合、この機能の実装には SET コマンドが使われます。

fabric.context_managers.show(*args, **kwds)

与えられた出力 groups をTrueにセットするためにコンテキストマネージャー。

groupsoutput で定義された出力グループを命名している1つ以上の文字列でなければなりません。与えられたグループは、囲まれたブロックでの継続性のためTrueにセットされ、その後は前の状態に戻ります。

例えば、デバッグ出力を有効にします(デフォルトではたいていオフになっています):

def my_task():
    with show('debug'):
        run('ls /var/www')

ほぼすべての出力グループがデフォルトでは表示されますが、通常は非表示になっている debug グループをオンにしたり、ご自分のコードを呼び出すコードが hide で出力を隠そうとしていることを知っていたり疑っていたりする場合に show はとても有用です。

fabric.context_managers.warn_only()

settings(warn_only=True) のエイリアスです。