Fabric †
- 類似ツール
- Puppet(ruby製) マニフェストを定義。状態を定義する。
- Chef(ruby製)レシピを定義。
~/.ssh/configで多段sshの設定と、use_ssh_configを組み合わせると切断されない †
/.ssh/configで多段sshの設定と、use_ssh_configを組み合わせると処理が終わっても切断されない。
バグっぽい
/.ssh/config
Host gateway.example.com
ProxyCommand none
User gateway-user01
IdentityFile ~/.ssh/gateway.pem
Host target01.example.com
User user01
ProxyCommand ssh gateway.example.com nc %h %p 2> /dev/null
IdentityFile ~/.ssh/id_rsa
- fabric側 v1.8.0
# -*- coding: utf-8 -*-
from fabric.api import *
from fabric.contrib.console import *
from pprint import pprint
@task
def multistage_ssh_test():
env.use_ssh_config = True
run('whoami')
- 実行
# localは大丈夫
fab multistage_ssh_test
# 多段sshは処理が終了しない
fab -u user01 -H target01.example.com multistage_ssh_test
fabricからスクリプトが起動しない場合 †
fabricからシェルスクリプト等を実行する時、起動しないものがある
fabtools †
実行時に処理が進まない場合 †
- gateway側で操作ログをファイルに記録するために"script"コマンドを使っている場合に処理が進まなかった
- 対処: ptyをデフォルトでは使わないようにする。(gateway側で@ptyが無い場合は記録しないように変更する必要あり)
env.always_use_pty=False
gateway: 多段SSH †
env.roledefs/@roles : 環境別設定 †
- fabricのバージョンによって仕様が変わったのか、blog等の情報は実行してもエラーが出たりと錯綜している
- -R rolename オプションは、env.roledefs = {}を定義していないとエラーになる
- 複数のサーバに特定の処理を実行(fabric 1.8.0)
- fabfile.py
# -*- coding: utf-8 -*-
from fabric.api import *
env.roledefs = {
'web' : ['web01.example.com','web02.example.com'],
'db' : ['db01.example.com','db02.example.com'],
}
@task
def deploy():
pass
- webとdbにdeploy()を実行
$ fab -R web,db deploy
[web01.example.com] Executing task 'deploy'
[web02.example.com] Executing task 'deploy'
[db01.example.com] Executing task 'deploy'
[db02.example.com] Executing task 'deploy'
Done.
- webにだけdeploy()を実行
fab -R web deploy
[web01.example.com] Executing task 'deploy'
[web02.example.com] Executing task 'deploy'
Done.
- 関数毎に環境を指定する(fabric 1.8.0)
- fabfile.py
...
@task
@roles('web')
def deploy():
pass
- roleを指定しないで実行するとwebホストにだけ実行される
fab deploy
[web01.example.com] Executing task 'deploy'
[web02.example.com] Executing task 'deploy'
Done.
- -R dbを指定しても、webホストに実行される
fab -R db deploy
[web01.example.com] Executing task 'deploy'
[web02.example.com] Executing task 'deploy'
Done.
@runs_onceデコレータ †
quiet() : エラーが発生した場合でも表示しない †
- 通常、local(), run(), sudo()を実行するとコンソールに表示され、エラーが発生すると中断するが、quiet()を使うと画面に何も表示されなくなる
@task
def test_quiet():
with quiet():
print local("test -e /tmp/build").succeeded # False
print local("test -e /tmp/build").failed # True
return_codeの取得 †
- local(), run(), sudo() で使える
@task
def test_return():
print local('test -d /tmp', quiet=True, warn_only=True).succeeded # True
print local('test -d /tmp', quiet=True, warn_only=True).return_code # 0
環境変数の設定 †
with構文 †
- python 2.5以上
- with構文に対応しているcd(), lcd(), shell_env()等は、環境を引き継いで次のコマンドを実行できる
@task
def test_cd():
with cd('/tmp'):
run('pwd') # /tmp
文字列をbool型に変換 †
- fabricのコマンドライン引数は文字列(str)になるため、ifの分岐等で思った通りにいかない場合がある。
import distutils
print distutils.util.strtobool("true") # 1: y, yes, t, true, on
print distutils.util.strtobool("false") # 0: n, no, f, false, off
var1 = distutils.util.strtobool(var1) if isinstance(var1, str) else var1
公開鍵認証での接続 †
def test():
env.use_ssh_config = True # ~/.ssh/configを参照する場合
env.user = "hoge"
env.key_filename = "/home/hoge/.ssh/id_rsa"
run("hostname -s")
Exception : エラーと例外 †
logging : ログの出力 †
- コンソール(簡易)とファイル(詳細)に両方出力
# -*- coding: utf8 -*-
from fabric.api import *
import logging
# ~/.fabricrc に log_filename=/tmp/fab.log 等を追加
def set_logging(filename=env.log_filename, level=logging.INFO):
try:
logger = logging.getLogger()
if logger.handlers:
for handler in logger.handlers:
logger.removeHandler(handler)
if filename != "":
logging.basicConfig(
filename=filename
, level=level
, format="%(asctime)s\t%(levelname)s\t%(message)s\t%(module)s\t%(funcName)s\t%(lineno)d\t%(pathname)s")
console = logging.StreamHandler()
console.setLevel(level)
formatter = logging.Formatter("%(asctime)s\t%(levelname)s\t%(message)s")
console.setFormatter(formatter)
logging.getLogger().addHandler(console)
except Exception, e:
sys.stderr.write(e.message)
@task
def test():
set_logging()
logging.debug('message') # level=logging.INFO なので出力されない
logging.info('message')
logging.warning('message')
logging.error('message')
logging.critical('message')
env.hosts : ホストの指定 †
- 例
- 設定
vim ~/.fabricrc
----
servers=host1,host2
----
- タスク
# -*- coding: utf8 -*-
from fabric.api import *
@task
def test():
run("hostname -s")
@task
def test2():
""" パスワード指定 """
env.use_ssh_config = True
env.host_string="ssh.example.com"
env.user="foo"
env.password="bar"
run("hostname -s")
- fab -H host1,host2 # env.hostsに値が入る
fab test -H host1,host2
- Using execute with dynamically-set host lists env.hosts = [var1,var2]と同等の事がしたい場合
def _test(arg1, arg2):
run("hostname -s")
@task
def test():
host_list=env.servers.split(",")
execute(_test, arg1="arg1", arg2="arg2", hosts=host_list)
fabricrc : 設定ファイル †
env : 環境変数 †
env.varname に対して、読み書き可能。省略時のデフォルトとして使われる。
env.newvar="value" のように新しい値も作成できる。
envは辞書型
- '#'で注釈を入れた。環境:CentOS6.3 x86_64, fablic 1.8.0
vim fabfile.py
----
# -*- coding: utf8 -*-
from fabric.api import *
from pprint import pprint
@task
def show_env(key = ""):
if key == "":
pprint(env)
else:
print(env[key])
----
fab show_env
{'': True,
'abort_exception': None,
'abort_on_prompts': False,
'again_prompt': 'Sorry, try again.',
'all_hosts': [],
'always_use_pty': True,
'colorize_errors': False,
'combine_stderr': True,
'command': 'show_env',
'command_prefixes': [],
'command_timeout': None,
'connection_attempts': 1,
'cwd': '',
'dedupe_hosts': True,
'default_port': '22',
'disable_known_hosts': False,
'eagerly_disconnect': False,
'echo_stdin': True,
'exclude_hosts': [],
'fabfile': 'fabfile',
'forward_agent': False,
'gateway': None,
'hide': None,
'host': None, # hostname
'host_string': None, # 1台だけホストを指定
'hosts': [], # ["host1", "host2"] のように複数ホストを指定。コマンドの-H host1,host2 で指定可能。変数はなぜか代入しても機能しない
'keepalive': 0,
'key_filename': None,
'lcwd': '',
'linewise': False,
'local_user': 'hoge',
'new_style_tasks': True,
'no_agent': False,
'no_keys': False,
'ok_ret_codes': [0],
'output_prefix': True,
'parallel': False,
'password': None,
'passwords': {},
'path': '',
'path_behavior': 'append',
'pool_size': 0,
'port': '22',
'rcfile': '/home/hoge/.fabricrc',
'real_fabfile': '/home/hoge/fabric/fabfile.py',
'reject_unknown_hosts': False,
'remote_interrupt': None,
'roledefs': {},
'roles': [],
'shell': '/bin/bash -l -c', # run(), local() で実行される場合のshell
'shell_env': {},
'show': None,
'skip_bad_hosts': False,
'ssh_config_path': '~/.ssh/config',
'sudo_prefix': "sudo -S -p '%(sudo_prompt)s' ",
'sudo_prompt': 'sudo password:',
'sudo_user': None,
'system_known_hosts': None,
'tasks': ['show_env'],
'timeout': 10,
'use_exceptions_for': {'network': False},
'use_shell': True,
'use_ssh_config': False, # True : ~/.ssh/config を使用する
'user': 'hoge', # ssh接続する時に使うユーザ名
'version': '1.8.0',
'warn_only': False} # タスク実行中に異常が起きた場合、中断する
Done.
AssertionError †
- assert len(specs) == 1 and specs[0][0] == '=='
pip list
...
Exception:
Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/basecommand.py", line 134, in main
status = self.run(options, args)
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/commands/list.py", line 80, in run
self.run_listing(options)
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/commands/list.py", line 127, in run_listing
self.output_package_listing(installed_packages)
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/commands/list.py", line 136, in output_package_listing
if dist_is_editable(dist):
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/util.py", line 347, in dist_is_editable
req = FrozenRequirement.from_dist(dist, [])
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/__init__.py", line 194, in from_dist
assert len(specs) == 1 and specs[0][0] == '=='
AssertionError
confirm: Yes/No確認 †
prompt: ユーザ入力待ち †
rootユーザで実行 †
- 事前に接続するユーザがsudoできるようにしておく必要がある
- sudo("command") : リモートでsudoしてcommandを実行
- from fabric.api import sudo が必要
- 別ユーザ/グループで実行するには sudo("command", user='apache',group='apache')
関数と引数 †
- 実行時に関数と引数を指定: fab command:arg1=val1,arg2=val2,...
- python
- print("message %s %s" % (arg1, arg2)) : メッセージを表示
- Core API > Operations
- local("command") : ローカルで実行
- run("command") : リモートで実行
- put("local path", "remote path") : ローカルファイルをリモートへコピー。SFTP使用
- get("remote path", "local paht") : リモートファイルをローカルへコピー。SFTP使用
- var1=prompt("message") : ユーザ入力待ち
- sudo("command") : root または別ユーザで実行
- Core API > Utils
- abort(message)
- error(message)
- puts(message) : printのエイリアス
- warn(message)
- Core API > Context Managers
- quiet() エラーが発生した場合でも表示しない
- shell_env(**kw) :環境変数を設定する。shell_env(HOGE="hoge")
- cd(path) :ローカルカレントディレクトリの変更。 with cd(path): 構文
- lcd(path) :リモートカレントディレクトリの変更。 with lcd(path): 構文
clouddns:Python API binding to Rackspace Cloud DNS †
boto:A Python interface to Amazon Web Services †
- インストール
sudo pip install boto
@taskデコレータ †
git/svn無視ファイル †
再インストール/アップグレード †
インストール †
Raspbian 7.x †
cat /etc/debian_version
7.1
python -V
Python 2.7.3
sudo aptitude update
sudo aptitude install python-pip python-dev gcc
sudo pip-2.7 install fabric fabtools fexpect
sudo pip-2.7 install -U distribute
CentOS 6.x †
- CentOS 6.4 x86_64
yum install python python-devel python-setuptools --enablerepo=epel
easy_install pip
pip install fabric fabtools fexpect
pip list | grep -i fabric
Fabric (1.6.1)
# pip list で以下のエラーが出たが、fabricは動いている。
pip list
Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/basecommand.py", line 134, in main
status = self.run(options, args)
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/commands/list.py", line 80, in run
self.run_listing(options)
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/commands/list.py", line 127, in run_listing
self.output_package_listing(installed_packages)
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/commands/list.py", line 136, in output_package_listing
if dist_is_editable(dist):
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/util.py", line 347, in dist_is_editable
req = FrozenRequirement.from_dist(dist, [])
File "/usr/lib/python2.6/site-packages/pip-1.4-py2.6.egg/pip/__init__.py", line 194, in from_dist
assert len(specs) == 1 and specs[0][0] == '=='
AssertionError
# 解決するには
sudo pip install -U distribute
- テスト
- localhostにsshでログインしてuname -sを実行
- デフォルトファイルは fabfile.py
- -f PATH: 別のpyファイルを指定する場合。
- -H HOSTS : ホスト指定。カンマ区切りで複数ホストを指定。指定しなければプロンプトが出る
- -u USER : 接続ユーザ指定。指定しなければプロンプトが出る
- -p PASSWORD : 接続パスワード
- -i PATH : SSH private key file
vim fabfile.py
----
# -*- coding: utf-8 -*-
from fabric.api import *
@task
def host_type() :
""" usage """
run('uname -s');
# vim: ts=4 sw=4 expandtab
----
fab -H localhost host_type
out: Linux
fab list
Available commands:
host_type usage
CentOS 5.x †
|
|