Fabric の run() メソッドと sudo() メソッド


この記事では、Fabricの主要メソッドである run() と sudo() について解説します。

サンプルコードは https://github.com/shiumachi/fabric-sample にあります。

run() と sudo() の基本


読みやすくするため、以後は必要がない限り run() メソッドのみを取り上げます。run() で出来ることはほぼ全て sudo() でも出来ます。断りが無い限り、run() は sudo() と読み替えることができます。

  • from fabric.api import run でインポート可能
  • run([コマンド文字列]) で、任意のコマンド文字列を実行可能
  • sudo([コマンド文字列]) とすれば、任意のコマンド文字列を sudo できる

エラーハンドリング


run() で実行したコマンドが失敗した場合、fab コマンド自体がその場で中断(abort)されます。

もしそのまま処理を続行したい場合は warn_only=True という引数を追加します。

def run_error_warn_only():
    run("hoge", warn_only=True)


warn_only=True だけだと、処理は続行できますがエラー出力はそのまま行われます。
エラー出力も抑制したい場合は quiet=True を追加します。

def run_error_warn_only_with_quiet():
    run("hoge", warn_only=True, quiet=True)

出力内容やリターンコードを使う


run() コマンドの返り値には、出力内容とリターンコードなどの情報が含まれています。

この返り値、公式ドキュメントでさえ使い方がきちんと整理されて書かれていないので、ここにまとめておきます。

res = run() としたとき、

  • print res
    • 実行したコマンドの出力内容を出力する
  • res.return_code
    • リターンコードを返す
  • res.succeeded
    • コマンドが成功していたら True、失敗していたら False を返す
  • res.failed
    • コマンドが失敗していたら True、成功していたら False を返す。succeeded の逆。


となります。

def succeeded_sample():
    res = run("hostname", warn_only=True)
    if res.succeeded is True:
        puts("succeeded!")
        return

sudo() で、リモートサーバ上で別のユーザとしてコマンドを実行


リモートサーバで、現在実行しているユーザとは別のユーザでコマンドを実行したいときがあります。

例えば、Hadoop HDFS の管理コマンドは hdfs ユーザしか扱えません。

そういうときは、user='ユーザ名' を使います。

def sudo_user_sample():
    print sudo("id", user='sho')


ユーザ名は、既に存在する別のユーザがあればそのユーザと置き換えてください。

zsh による Fabric コマンドのタブ補完


Fabricは便利ですが、コマンドが多くなると管理が大変になり、いちいちコピペするのが面倒になります。

zsh を使えば、Fabric のタブ補完をすることが可能です。
ここでは、oh-my-zsh を使ったタブ補完の設定方法を紹介します。

oh-my-zsh のインストール


id:mollifier さんがインストール方法についてまとめてくれていますので、こちらを参考にしてインストールしてみてください。

http://mollifier.hatenablog.com/entry/20101009/p1

Fabric 用タブ補完プラグインの導入


残念ながら、Fabric 用タブ補完プラグインは oh-my-zsh のアップストリームにマージされていません。

santiycr 氏が補完プラグインを書いていますのでそれを使ってください。


~/.oh-my-zsh/plugins/fabric というディレクトリを作成し、以下のファイルを置いてください。


https://github.com/santiycr/oh-my-zsh/blob/master/plugins/fabric/fabric.plugin.zsh


やり方が分かる人は、santiycr 氏のリポジトリを fetch して必要なパッチのみを cherry-pick するといいでしょう。

一応こんな感じにすればうまくいくはずです。
細かい説明は省略します。

使い方


fabfile.py のあるディレクトリで fab と入力した後、タブを押すだけです。

コマンドを補完するか、補完対象のコマンド一覧を表示してくれます。

今日からすぐに使えるデプロイ・システム管理ツール Fabric 入門

Fabric は、Python 製のデプロイ・システム管理ツールです。

最近、構築や運用を自動化するための様々なツールが出てきています。
構成管理ツールの Puppet や Chef が有名ですが、使うまでに覚えることが多いのが欠点です。
しかし、Fabric は非常にシンプルなツールで、今からすぐに使うことができます。
Fabric はデプロイ・システム管理ツールで、類似のツールとして Ruby 製の Capistrano があります。


Fabric の最大の特長は、シェルスクリプトを書き慣れた人がいきなり利用できるところです。
シェルスクリプトとしてまとめていたコマンドをそのまま run() メソッドや sudo() メソッドで囲むだけで、使うことができます。

シェルスクリプトを使っていていると、いくつもの問題に遭遇します。

  • 名前空間の管理
  • 変数の扱い
  • 複雑なデータ構造がない(せいぜい配列ぐらい)
  • 例外処理


これらの問題に頭を悩ませたことがある人は多いでしょう。
Fabric は Python で記述しますので、上記の問題は全て解決します。

「Fabric = シェルスクリプト + Python + 便利メソッド」

というイメージです。


SIerに勤めていてSE等をされている方は、運用チームのための運用手順書を書いたことがある人も多いでしょう。
その運用手順書の多くは、何らかのコマンドラインを実行する、という記述が書かれているはずです。
Fabric を使えば、その運用手順書を「ほぼそのまま」Fabric のスクリプトに移行できます。

Fabric のインストール

$ easy_install fabric


たったこれだけです。「easy_install って何?」という人は ymotongpoo先生の素晴らしい記事 を参考にしてください。約5分で読み終わり、さらに約5分で easy_install を使えるようになるでしょう。

試してみる(1): yum コマンドを Fabric から実行


例えば、yum コマンドで git をインストールする、という作業があったとします。

シェルを使えば以下のように書けるでしょう。

$ sudo yum -y install git


おそらく、普通の運用手順書では、「サーバAにログインし、以下のコマンドを実行する」という形で書いてあるはずです。
Fabric を使えば、そのような手順書は不要になります。


まず、リモートマシンを1台用意してください。
VM でも構いませんが、Amazon EC2 を使う方が便利です。EC2 を使ったことがないという方は、この記事の末尾で使い方などが記載されている資料のリンクを紹介します。


ここでは、以下のようなサーバ設定を例にとります。
ec2-user は Amazon Linux のデフォルト管理者ユーザで、sudo 権限を持っています。
EC2 上で RHEL を使う場合は ec2-user ではなく root を使ってください。

  • サーバ名: ec2-XXX.ap-northeast-1.compute.amazonaws.com
  • ユーザ名: ec2-user
  • SSH秘密鍵のパス: ~/.ssh/id_rsa


Fabric を使う場合、まず適当なディレクトリを作成し、fabfile.py というファイルを作成してください。
次に、以下の内容を書き込みます。

from fabric.api import sudo

def install_git():
  sudo("yum -y install git")


「え?」と思ったでしょうが、本当にこれでおしまいです。
あとは、fabfile.py の置いてあるディレクトリで、以下のコマンドを実行します。

$ fab -u [ユーザ名] -i [sshの秘密鍵] -H [ホスト名] install_git


先程のサーバ例の場合は、以下のようになります。

$ fab -u ec2-user -i ~/.ssh/id_rsa -H ec2-XXX.ap-northeast-1.compute.amazonaws.com install_git


たったこれだけで、リモートサーバで yum install git を実行することができます。
非常に簡単です!


今回紹介したサンプルスクリプトは、github に公開しています。
こちらも参考にしてみてください。

https://github.com/shiumachi/fabric-sample

試してみる(2): Fabric の価値を体感する


「ただ置き換えるだけならシェルスクリプトのままでいいじゃん」

と思う人のために、Fabric の強力な機能のうちのいくつかをを紹介します。

複数ホストに対して同時に実行


'-H' でホスト名を指定する際にカンマ区切りで複数のサーバを指定することができます。

例えば先程の例で、serverA と serverB に対し同時に install_git を実行したい場合は、以下のように書きます。

$ fab -u ec2-user -i ~/.ssh/id_rsa -H serverA,serverB install_git

複数コマンドを順番に実行


例えば、ユーザ 'hoge' を作成するコマンドを作りたいとします。
シェルスクリプトで書く場合は以下のようになります。

# adduser hoge

これを Fabric で書くと、以下のようになります。

def adduser_hoge():
  sudo("adduser hoge")

シェルスクリプトの場合、先程の git のインストールコマンドと一緒に管理するには、別々のファイルとして保存するか、一緒のファイルにしてしまってバッチ実行するしかありませんでした。

Fabric の場合は、作成したメソッド全てを独立したコマンドとして扱えます。
fabric.py のあるディレクトリで、以下のコマンドを入力してみてください。

$ fab --list

そうすると、現在実行可能なコマンドの一覧が表示されます。

Available commands:

adduser_hoge
install_git

Fabric の面白いところは、一回のコマンドでこれらを任意の順番で実行できるところです。
以下の例のように、スペースを空けて一つづつコマンドを記述していくことで、Fabric はそのコマンドを左から順番に実行していきます。

$ fab -u ec2-user -i ~/.ssh/id_rsa -H ec2-XXX.ap-northeast-1.compute.amazonaws.com install_git adduser_hoge

たったこれだけのコマンドで、「git をインストールする」「ユーザ hoge を作成する」の2つの作業を実行できるのです!

次のステップ


もしこの記事を読んで、「よし、ちょっと Fabric を試してみよう」と思った方に、次にステップのための記事を紹介します。

drillbits 氏の紹介スライド


https://speakerdeck.com/drillbits/fabric-python-developers-festa-2013-dot-03-number-pyfes

Fabric の基本的な使い方についてまとめています。Fabric 入門者は必読です。

Python製デプロイツール Fabricを初めて使う際に役立つTips


http://dekokun.github.io/posts/2013-04-07.html

dekokun 氏による Tips 集です。

最初に読んでもいいですが、ある程度使ってから「こういう書き方したいんだけど、どうすればいいんだろう?」と思ったときに開いてみるのもオススメです。

Fabric デプロイツールのPythonicな書き方


http://www.ianlewis.org/jp/fabric-pythonic

やや古い記事ですが、ianlewis 氏による Fabric の書き方入門。

with cd() の書き方は Fabric での典型的なイディオムなのでオススメです。

公式ドキュメント


最後に、公式ドキュメントを紹介します。

http://docs.fabfile.org/en/1.6/

英語ですが、API のリファレンスとしては必須です。以下の3つのモジュールの API リファレンスは何度も読むことになるでしょう。

  • Operations
    • run, sudo, get, put などの基本メソッドのドキュメントがあります。
  • Utils
    • error, warn などのロギング周りのメソッドについて書かれています。
  • Files and Directory Management
    • append(ファイルに追記)、comment(ファイルの特定の項目をコメントアウト)などのファイル操作周りの便利APIがあります。

付録: Amazon EC2 の使い方

EC2 を使ったことのない人のために、いくつかドキュメントを紹介します。

これらを読めば、EC2 上でインスタンスを立ち上げることができると思います。

これらを読んでもどうしても分からない人はAWSの有償サポートを買ってください
多分人件費分は元が取れると思います。

更新履歴

2013/04/14 17:33 指摘に従い、タイトル及び冒頭の説明を修正

8つの質問で、Hadoop業界の現状を知る


Webサービス系の隆盛があったのかどうかはよく知らないが、Hadoopのリリースが騒がれたのが7年前ぐらいだろうか。Hadoop業界の人材動向が、今どうなってるかって?

大方の予想より凄惨ですよ。

それが分かる方法がある。Hadoop技術者に技術力を問う8つの質問によってだ。Hadoop業界のエンジニアの平均レベルを知りたくって、いろんな会社さんのHadoop開発者(経験者)向けに以下のような8つの質問をしてみたいと思ってるけど、やったことはない。 対象者としては、Hadoop経験3から4年の現役バリバリのはずのHadoopエンジニアだ。

その8つの質問というのはこんな問題だ。

Hadoop技術者に技術力を問う8の質問

  1. 投機的実行のメリットを一言で表して下さい。(筆記解答)
  2. ネームノードのRPCアドレスを取得するコマンドは何ですか?(筆記解答)
  3. 標準jarファイルでベンチマークを取る方法を説明してください。(筆記解答)
  4. 複数の出力を生成するためのクラスはどれですか?(選択解答。複数回答可)
    1. MultipleOutputs
    2. MultipleOutputFormat
    3. MultiOutputFormat
    4. MOutputs
  5. MapReduceを書いているのに、思ったほど実行時間が短くなってくれません。CPUコア数は足りているようです。原因として何が考えられますか?(筆記解答)
  6. MapReduceでMap処理だけを使用するのはNGですか?そうであればその理由を説明してください。(筆記解答)
  7. Yarnでノード一覧を取得するためのコマンドは何ですか?(筆記解答)
  8. APIでカウンタをカウンター名の指定により取得するメソッドは何ですか?(筆記解答)


過去に実施した平均点
この8問について、僕が出会ったエンジニアに解答してもらった平均正解数は、なんと8点満点中8点(予想)である。





この辺まで書いて力尽きた。

おまけ

Go Conference 2013 springというイベントが開催されます。凄惨なGo業界の現状を打破したいそうなので手伝いましょう。直前でキャンセルが出るはずなので、とりあえず並んでみて下さい。

Go Conference 2013 spring - connpass

Disclaimer

煽ったのは id:ymotongpoo です。私は乗せられて書いただけです。

PyFes 2013.3 参加メモ #pyfes

午前: Riak ハンズオン

Riak ハンズオンに参加したと思っていたらいつの間にか Riak ハンズオンを手伝う側に回っていたでござる

教訓

  • インターネットがまともに使えない、かつ全員がMac という特殊な環境だと AirDrop を使って必要なファイルをばらまくという技が使える。かなり限定的な条件ではあるが、便利
  • ハンズオンで構築からやらせるのはリスク高過ぎと再確認

ハンズオンについては別途ブログを書くかもしれない

Go ( @ymotongpoo )

http://www.slideshare.net/ymotongpoo/20130316-go

  • Go 言語の紹介
  • 内容はいつも説明を聞いているのでほぼ知っていた。初めて説明聞いた人には面白い内容のはず
  • プレゼンうまくなっててびっくり

Mock と patch ( @torufurukawa )

http://www.slideshare.net/torufurukawa/mock-and-patch

テストが難しいメソッド

例: urlopen の結果は不確定なのに、その結果に依存するメソッド

  • 戻り値が不確定
    • 乱数
    • 時刻
  • セットアップがだるい

だから、テスト対象の外側を入出力として扱う

mock モジュール
  • 3.2 以前は PyPI
  • 3.3 標準ライブラリ unittest.mock
mock の 使い方
  • 依存先オブジェクトを入れ替える
    • 例: urlopen を mock に入れ替える
    • with patch で入れ替える

with patch('urllib.request.urlopen') as m:
...
... from urllib.request.urlopen ...
これが m になる

  • @patch で入れ替える
    • with はインデントが深くなるのであまり好きじゃない

@patch('urllib.request.urlopen')

  • call_count で呼び出し回数を確認

assert m.call_count == 1

  • call_args で引数を確認
  • 依存先の挙動を定義する
    • m.return_value = 999
      • 返り値が 999 になる。
    • m.return_value.meth.return_value = 1
      • m().meth()
    • 複雑な戻り値は side_effect

def f(x, y): ...
m.side_effect = f

例外も side_effect に指定可能



MS Surface でゲームを作った話 ( @tokoroten )

巷で話題の Surface ではない本物の Surface
静電容量式はオワコン

APIC# なので pygame からアクセスする場合はソケット通信で入力メソッド部分を置き換えれば既存のゲームを移植可能

Introduction of Leap Motion (@hagino3000 )

http://www.slideshare.net/hagino_3000/introduction-of-leap-motion

手の認識に特化した小型モーションキャプチャデバイス

机の上にちょこんと置いて手をかざして使うことを想定している

  • センサー: 赤外線センサー
  • 接続: USBインタフェース
  • 高分解能(0.01mm), 速い(> 60 FPS), 安い
  • Pre Order
    • < $90
    • 5/13 以降順次発送
  • 開発者登録
    • 一個無料で送ってくれる
    • 製品版と一部異なる
    • 起動に開発者IDとパスワードが必要
    • 作ったアプリの勝手配布はNG

Arduino + Python 勉強会の紹介 ( @nonNoise )

といっても基本技術は既に固まっているのであとはこれをどう遊ぶかという話

Tinkerer ( @r_rudi )

Sphinx を利用したブログ作成ツール
tinker コマンドを使う
更新のたびに全ファイル生成し直し

  • drone.io
    • travis ci のような自動テストツール
    • bitbucket 対応
  • S3
    • 転送量課金される
  • Dropbox
    • アクセス量で金額は増えないが、独自ドメインが使えない

webpay ( @keikubo )

1時間で使えるクレカ決済

USでは決済市場が白熱している

日本の決済システムは問題がいっぱい
だから日本で開発者向けの決済システムを作った。それが webpay


ライブマインドマッピング ( @sawonya )

@3_and_planet による身の上話をマインドマップ
2人目の人は名前がわからなかった cobit の話
@wozozo による身の上話をマインドマップ

WebMachine ( @voluntas )

https://gist.github.com/voluntas/f99838001efced196fc0

  • Webmachine
    • Basho 製 REST ツールキット
    • Erlang 専用?
      • 「考え方」なのでどんな言語でもOK

Blender ( @lab1092 )

  • オープンソース 3DCG ソフトウェア
  • Open Movie Project
    • Blender の開発をしながら映画を作るプロジェクト
  • Python 3.3 が使える
  • Rapid Release
  • Git 対応

インターネットの経済学 ( @JHarrison )

Webサービスってどれほどの価値があるのか?

Fabric ( @drillbits )

https://speakerdeck.com/drillbits/fabric-python-developers-festa-2013-dot-03-number-pyfes

  • 環境はたくさん作らなきゃいけない
    • 開発、本番、ステージング、ステージング2、ステージング3、...
  • pip install fab
  • オプションでユーザ名、ホスト、SSH鍵などを指定可能
  • env にオプションを指定することも可能

Opsworks & Chef ( @tk0miya )

http://www.slideshare.net/TakeshiKomiya/ops-works-chef

  • why chef
    • 冪等性
      • 手続き型ツール(Capistrano, Fabric)は順序が重要(差分更新)
    • community cookbooks
      • 大抵のツール向けの設定が集約
      • 再利用の精神
      • 理想はほとんど書かない
  • chef の種類
    • chef-server
      • 大規模用、クライアントサーバ型
    • chef-solo
      • 小規模運用、手動実行
      • 20台くらいまでなら chef-solo で十分
    • ホスティング
      • 有料プラン
chef-solo
  • vagrant
  • librarian
    • cookbook 管理ツール
    • yum や apt みたいなもん
    • 依存関係解決 Java 入れたりとか
    • Chef 使うなら最初に覚えたい
    • 類似ツール: Berkshelf
      • どっち使ってもいい
  • attributes を書く
    • json 形式で書いていく
  • 実行する
    • コマンド一発
tips

capistrano 経由で実行すると便利

  • chef 情報が少ない
    • id:naoya による書籍
    • Ryuzee さん、セカコミさんによるブログ
  • チームへの布教が大変
  • コミュニティクックブック
    • Ubuntu が多く、CentOS に対応していないものも多い
    • attributes 化されていない設定項目がある
    • 似たような cookbook がたくさんある
    • パッチを投げても無反応
OpsWorks
  • AWS のアプリ管理ツール
    • 環境構築
    • アプリのデプロイ
    • インスタンスの起動/終了の管理
      • スケーリング
      • スケジューリング
  • まだバグが残ってる
    • This is oops works

団長 (団長)

メモはとったけど公開しない

moriyoshi さん

AnyPack Builder
素晴らしい

最も無価値なものを探す

駅を降り、夜道を歩いて帰る途中、ふと思いつき「今目に映るもののうち、最も無価値なものはなんだろう」と考えてみました。
こんな視点で周囲を見渡すと、普段は全く価値を感じない様々なものが、意外にも価値があることに気づきます。
マンホールや排水口は、雨が降ったときの水はけに不可欠ですし、工事現場の金網は侵入防止の機能だけでなく不意にぶつかってしまったときの衝撃吸収に役立ちます。
「最も価値あるものを探す」という視点よりも、「最も無価値なものを探す」という視点の方がかえって多くの価値に気づくことができます。


これはよく考えれば自明の話です。
人間は自分本位な生き物なので、「最も価値ある」というのは無意識のうちに「(自分にとって)最も価値ある」という言葉に置き換えられます。

一方、最も無価値なものを探す場合、世の中の大半のものは自分にとって無価値なので、自分本位の価値判断だと比較ができません。
例えば、マンホールに大きな価値を見いだしている人は相当少ないはずです。
「より」無価値なものを探そうとすると、必然的に自分以外の価値基準で比較しなければならなくなります。

私にとっては無価値でも、ご近所さんに必要なものはたくさんあります。
住民にとって無価値でも、工事現場の作業員にとって重要なものもたくさんあります。
そんな視点でものを見渡すと、無価値なものって意外と見つからないものです。


案外、自分自身が今目に映る何よりも一番無価値なものなのかもしれません。

hadoopプロジェクトの規模(2013/01/25版)

@ に手伝ってもらいながら、hadoop プロジェクトのコードの行数をカウントしました。

サブプロジェクト 行数
common 198,303
hdfs 234,070
mapreduce 221,630
yarn 158,067
hadoop-tools 59,713
maven-plugins 522
合計 872,305

というわけで合計87万行でした。4つのサブプロジェクト(common, hdfs, mapreduce, yarn) に分かれているとはいえ、それにしても大きいです。

おまけ: 他のプロジェクトの行数

プロジェクト名 行数
HBase 633,922
Hive 410,005

Hive は id:oza_x86 さんにカウントしてもらいました。thx!

さらにおまけ: コードの行数計算 via cocoatomo


リンク: https://gist.github.com/4623120