18
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

fabric2のインストール手順と簡単な使い方

Last updated at Posted at 2019-01-15

概要

fabric2のインストール手順と簡単な使い方です。
fabric1と2は別物だと考えた方がよいです。fabric2は、Pythonのinvokeライブラリのラッパーなので、invokeのドキュメントも参考になります。

Version

  • Python 3.7.1
  • fabric 2.4.0

fabric2のインストール

以下のコマンドでインストール。

$ pip install fabric

以下でもインストール可能だが、fab2コマンドになったり、import fabric2としなくてはいけなくなるので面倒。

$ pip install fabric2

基本的な使い方

fabfile.pyを作成。
以下は接続先でhostnameコマンドを実行するサンプルスクリプト。

fabfile.py
#-*- coding:utf-8 -*-
import getpass
from fabric import Connection, Config
from invoke import task

@task
def sample(c):
    Config.user = 'username'
    hostname = 'example.com'

    sudo_pass = getpass.getpass("What's your sudo password?")
    config = Config(overrides={'sudo': {'password': sudo_pass}})
    c = Connection(hostname, config=config)
    c.run('hostname')

以下のコマンドで実行可能task一覧を確認できる。

$ fab -l
Available tasks:

  sample

sample taskを実行。

$ fab sample
What's your sudo password?
example.com

fabコマンドではなくpythonコマンドで実行する方法

以下で実行できる。

sample.py
from fabric import Connection, Config

Config.user = 'username'
hostname = 'yourhostname'
c = Connection(hostname)
c.run('hostname')
$ python sample.py

sudoコマンドにパスワードを渡す方法

結論から言うと、以下の「方法3」がベスト。

方法1

sudoでsudo: no tty present and no askpass program specifiedと怒られる場合、runでpty=Trueを付ける。
ただし、この方法だとsudoコマンドがある度にパスワードの入力が必要になる。

#-*- coding:utf-8 -*-
from fabric import Connection, Config
from invoke import task

@task
def sample(c):
    Config.user = 'username'
    hostname = 'example.com'

    c = Connection(hostname)
    c.run('hostname')
    c.run('whoami')
    c.run('sudo whoami', pty=True)

実行

$ fab sample
example.com
username
[sudo] password for username:
root

方法2

c.sudoを使い、引数でpasswordを渡す。
この方法なら毎度sudoパスワードを入力しなくて済む。
環境変数でpasswordを渡すことで、ソース内にパスワードを記述することを回避できる。

@task
def sample(c):
    c.sudo('whoami', password=os.environ.get('SUDO_PASSWORD'))

方法3

--prompt-for-sudo-passwordoptionを使う。
このオプションを使うことで、最初にパスワードをpromptで入力させることができる。しかも、最初に1度だけ入力させればよい。c.sudo()へのパスワードの渡し方は、方法2と同じ。

$ fab --prompt-for-sudo-password sample
Desired 'sudo.password' config value:

c.config.sudo.passwordで入力した文字列を取得できます。

@task
def sample(c):
    print(c.config.sudo.password)
    c.sudo('whoami', hide='both', echo=True, password=c.config.sudo.password)

ちなみに、以下のドキュメントを読んだが、入力したパスワードを取得する方法がよくわからなかったので
http://docs.pyinvoke.org/en/1.2/invoke.html

以下のinvokeのソースを追ったら分かった。
https://github.com/pyinvoke/invoke/blob/0de7020aa908d4a1afc5a7287e29196a657c292a/tests/_support/sudo_prompt.py

fabfileを分割する

fabfileをtaskごとに分割します。
production, developmentで環境ごとに異なる設定を読み込み、接続先でwhoamiを実行するサンプルを作ってみます。

以下のディレクトリ構成でファイルを作成します。

.
└── fabfile
    ├── hosts.py # 環境ごとの設定を読むモジュール
    ├── __init__.py # モジュールをimportするファイル
    └── sample.py # mainのtask(whoamiを実行する)

__init__.pyで、hosts, sampleをimportします。

__init__.py
#-*- coding:utf-8 -*-
from fabfile.hosts import *
from fabfile.sample import *

production, developmentそれぞれの設定を定義します。

hosts.py
#-*- coding:utf-8 -*-
from fabric import Connection, Config
from invoke import task

@task
def production(c):
    Config.environment = 'production'
    Config.hostname = 'prod.example.com'
    Config.user = 'username'

@task
def development(c):
    Config.environment = 'development'
    Config.hostname = 'dev.example.com'
    Config.user = 'username'

whoamiを実行するtaskを作成。

sample.py
#-*- coding:utf-8 -*-
from fabric import Connection, Config
from invoke import task
import os

@task(default=True)
def check(c):
    print(Config.environment)
    print(Config.hostname)

    with Connection(Config.hostname) as c:

        '''
        結果を変数にセットすることも可能
        hide=Trueでrunコマンドの標準出力を抑制する
        '''
        result = c.run('whoami', hide=True)
        print(result.stdout.strip())

        '''
        echo=Trueで実行コマンドも出力する
        ただし、hide=Trueだと出力されなくなるので、hide='both'とする
        '''
        result = c.run('whoami', hide='both', echo=True)
        print(result.stdout.strip())

        '''
        sudoで実行
        '''
        result = c.sudo('whoami', hide='both', password=os.environ.get('SUDO_PASSWORD'))
        print(result.stdout.strip())

        '''
        warn=Trueで、コマンドでエラーが発生しても中断しないようにできる
        以下のように自分でエラー処理を定義できる
        '''
        result = c.run('abcdef', hide=True, warn=True)
        if result.ok:
            print(result.stdout.strip())
        else:
            print("ERROR: {}".format(result.stderr.strip()))

実行可能コマンド一覧を確認。

$ export SUDO_PASSWORD=mypassword
$ fab --list
Available tasks:

  check
  production
  development

Default task: check

実行

$ fab development check
development
dev.example.com
username
whoami
username
root
ERROR: bash: abcdef: command not found

fabコマンドに任意のoptionを付与する方法

fooというoptionを付与する場合

fabfile/__init__.py
#-*- coding:utf-8 -*-
from fabfile.sample import *
fabfile/sample.py
#-*- coding:utf-8 -*-
from fabric import Connection, Config
from invoke import task

@task(optional=['foo'])
def foobar(c, foo=''):
    print(foo)

実行

$ fab foobar --foo=bar
bar

コマンドを連続で実行する場合

cd /tmp && pwdのようなことする場合。

以下のやり方では、それぞれ独立して動いてしまうため、pwdしても/tmpとはならない。

@task
def sample(c):
    with Connection('hostname') as c:
        c.run('cd /tmp'):
        c.run('pwd')

方法1: cd()を使って事前にディレクトリを移動する方法

@task
def sample(c):
    with Connection('hostname') as c:
        with c.cd('cd /tmp'):
            c.run('pwd')

方法2: prefix()で事前にコマンドを実行する方法

こちらであれば、cd以外のコマンドを実行したい場合でも使える。

@task
def sample(c):
    with Connection('hostname') as c:
        with c.prefix('cd /tmp'):
            c.run('pwd')

ssh秘密鍵のパスを指定する方法

#-*- coding:utf-8 -*-
from fabric import Connection, Config
from invoke import task

@task
def sample(c):
    c = Connection(
        host='example.com',
        user='username',
        connect_kwargs={
            "key_filename": "/home/username/.ssh/private.key",
        },
    )
    c.run('hostname')
    c.run('whoami')
    c.run('sudo whoami', pty=True)

参考

18
25
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
18
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?