いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.246 / 読者数:2438名

こんばんは、うすだです。

毎年毎年毎年、暑い夏が飽きもせずやってきて、 われわれ人間を苦しめているようですが、今年は、 その苦しさが柔らかいような感じがします。

以下、超個人的な理由を、3点ほど述べさせていただきます。

まず、寝苦しくて眠れない、という日が、 いまのところ数日程度しかないように思います。最高気温35度とかでも、 夜は布団がないと寒かったり。

それから、びっくりするほど、蚊にさされていません。
7月前半に何度か夜襲を仕掛けられたことがあったものの、ここ半月ほどの間は、 蚊にさされることも、夜中に耳元で囁かれることもなく、快適に過ごせています。

そしてなんといっても、とち狂ったセミとの遭遇が、 今のところほぼ皆無に近いことが、 今年の夏の評価を上げている大きな要因だと言えます。

夜の駐車場などで、ほぼ必ず天井に貼り付いていて、 そばを通りかかるとランダムに絶叫しながら飛び回る、アレ、です。

節足動物門汎甲殻類六脚亜門昆虫綱(Wikipedia の昆虫より) の大半を苦手とする私としましては、 秋になると飛行能力を発揮する黒い"アレ"に匹敵するくらいダメなのですが、 今年は、玄関や駐車場で待ち伏せされることがほとんどありません。

セミの歌声は、例年同様、あちこちから聞こえるのですが。
セミも、こんなことずっとやっていたってしょうがない… とか思うようになってくれたのかもしれませんね。

とにかく、このままの勢いを維持したまま、栗の季節へと遷移してほしいぞと、 切に願う今日この頃です。

己の経年劣化が主原因では? …という疑惑(真実?)には耳を傾けないようにして、 今回もはりきってまいりましょう。

今回のお題 - Fabric でもう少し気軽に遠隔管理する

前回、前々回およびその前の3回に渡って、Puppet というシステム管理のツールを、 延々と紹介させていただきました。

Vol.243 - Puppet でシステムを集中管理する
http://www.usupi.org/sysad/243.html
Vol.244 - Puppet でシステムを集中管理する 帝国の逆襲
http://www.usupi.org/sysad/244.html
Vol.245 - Puppet でシステムを集中管理する ジェダイの復讐
http://www.usupi.org/sysad/245.html

Puppetを使うと、司令塔であるサーバから、 クライアントである管理対象の各マシンに対して、 システムやサービスなどの集中管理ができます。
また、ほどよく抽象化されているため、 OSなどが違っていても共通の記述で設定や操作ができます。

ですが、サーバ・クライアントの双方に Puppet が必要であったり、 実際に行いたい操作とマニフェストの記述内容との間に距離があるなど、 敷居を感じることが少なからずあるように思われます。

Puppet ほどガッツリじゃなくていいので、もう少し簡単に試せて、 もうちょっとストレートに処理内容を記述できたらなあ…という貴兄のため、 今回は、Fabric というツールをご紹介したいと思います。

Fabric とは?

Fabric とは、 アプリケーションのデプロイやシステム管理を行うためのツールとライブラリです。

http://fabfile.org/

Fabricを使うと、リモートにある複数のマシンに対して、 同じ処理を一気に行うことができます。

Python で記述されているため、行いたい操作も Python で記述する必要があります。 ただ、実行したいコマンドなどがわかっていれば、Pythonがあまりわからなくても、 (おそらく)なんとかなります。

また、SSH を使って操作するため、Fabric で操りたいマシンには、 sshdさえあれば(動いていれば)よいです。
(指示を出すマシンに Fabric がインストールされていれば OK です。)

今どきのディストリビューションにはパッケージがありますので、 いつものように同名のパッケージをインストールします。

  $ sudo apt-get install fabric   (Debian系の場合)
  # yum install fabric            (RedHat系の場合)

もしなければ、easy_install と pip を使ってインストールします。

  # easy_install pip
  # pip install fabric

ただ、上記を CentOS で試そうとしたら、 python-pip というパッケージを使おうとしたのがいけなかったのか、 fab コマンドの実行時にエラーが発生してしまいました。

  # yum install python-pip
  # python-pip install fabric
  # fab --version
  ...エラー...

きっぱりと一から入れるか、 パッケージのあるディストリビューションを使うという選択肢が、 鉄板のように思われます。

まずは動かしてみましょう

Fabric で管理や操作を行うには、fab というコマンドを使います。
まずは、下記のように実行して、 エラーなくバージョンが出力されることを確認しましょう。

  $ fab --version
  Fabric 1.4.3
  ssh (library) 1.7.7.1 (George)

Fabricで処理を行うには、「fabfile.py」というファイルを用意します。
差し当たって、以下のような超簡単なモノを用意してみました。
(ちなみに、Fabric のサイトにも、ほぼ同じ内容のものがあります。)

from fabric.api import run

def uname():
    run("uname -a")

1行目は、「fabric.api」にある「run」という関数を使わせてください、 というお願い的な文言です。
3行目は、uname という関数の定義です。
4行目がその内容で、run という関数を使って、 遠隔のマシンで uname -a を実行してね、という処理内容を書いています。

これを動かすには、実行したい関数名を引数に指定して、fab コマンドを実行します。

  $ fab uname
  No hosts found. Please specify (single) host string for connection:

実行するホスト名を聞かれていますので、入力すると、 さらにパスワードも聞かれます。それに答えると、 指定したホストで uname を実行して、その結果を出力してくれます。

  $ fab uname
  No hosts found. Please specify (single) host string for connection: \
  192.168.1.2  (←ホスト名やIPアドレスを入力)
  [192.168.1.2] Login password for 'usu': (パスワードを入力)
  [192.168.1.2] out: Linux hoge 2.6.25 #1 SMP Thu Sep 22 12:34:56 \
  MSD 2011 i686 i686 i386 GNU/Linux

  Done.
  Disconnecting from 192.168.1.2... done.

ホスト名を「ユーザ名@ホスト名:ポート番号」の形式で指定すれば、 SSH のポート番号やユーザ名も指定できます。

もうちょっと自動化してみましょう

ただ、きっと、実行したいホストはほぼ毎回決まっていますよね。
それをイチイチ指定するのは面倒ですので、 「env」という辞書を使ってホストを登録してしまいましょう。

from fabric.api import run, env

env.hosts = ['user@192.168.1.3']

def uname():
    run("uname -a")

1行目の最後に env が追加されています。ご注意ください。
で、実行すると、パスワードだけ聞かれるようになりました。

  $ fab uname
  [user@192.168.1.3] Executing task 'uname'
  [user@192.168.1.3] run: uname -a
  [user@192.168.1.3] Login password for 'user': (パスワードを入力)
  [user@192.168.1.3] out: Linux hoge 2.6.25 #1 SMP Thu Sep 22 \
  ...後略...

env.hosts には複数のホストを指定できます。
また、env.password にパスワードを指定しておけば、 パスワードを入力しなくて済みます。

from fabric.api import run, env

env.hosts = ['192.168.1.2', '192.168.1.3']
env.password = 'パスワードはヒ・ミ・ツ!'

def uname():
    run("uname -a")

 

…ただ、生のパスワードを書いておくのは、かなり気が引けますよね。
そんなときは、パスワードなしでログインできるよう、 双方にSSHの鍵を登録しておきましょう。

認証用の鍵は、ssh-keygen コマンドで作成できます。

  $ ssh-keygen -f ~/.ssh/id_rsa.remote
  Generating public/private rsa key pair.
  Enter passphrase (empty for no passphrase): (リターン)
  Enter same passphrase again: (リターン)
  Your identification has been saved in /home/usu/.ssh/id_rsa.remote.
  Your public key has been saved in /home/usu/.ssh/id_rsa.remote.pub.
  ...後略...

途中、パスワードを求められますので、どちらも空っぽを指定します。
すると、~/.ssh/id_rsa と ~/.ssh/id_rsa.pub というファイルが、 無事作成されます。前者が秘密鍵、後者が公開鍵です。
そうしましたら、公開鍵を、ログインしたいマシンに持っていって、 以下のように ~/.ssh/authorized_keys へ追加します。

  remote$ cat id_rsa.remote.pub >> ~/.ssh/authorized_keys
  remote$ chmod go-rwx ~/.ssh/authorized_keys

2行目では、自分しかアクセスできないようにパーミッションを設定しています。 すでに authorized_keys があればおそらく実行は不要です。

念のため、パスワードなしでログインできるか試してみましょう。
-i オプションで秘密鍵を指定して実行します。

  $ ssh -i ~/.ssh/id_rsa.remote remote ls

問題なければ、env.key_filename に秘密鍵を指定します。

from fabric.api import run, env

env.hosts = ['192.168.1.2']
env.key_filename = '~/.ssh/id_rsa.remote'

def uname():
    run("uname -a")

これで、何も入力することなく、 リモートの各ホストに対して処理を実行することができるようになりました。

run 以外の主な関数

run 以外の関数を、いくつかご紹介します。

まず、「put」は、遠隔のマシンへファイルをコピーする関数です。
コピー元のファイルのパスと、コピー先のファイルのパスを、 引数に指定して呼び出します。

from fabric.api import env, put

env.hosts = ['192.168.1.2']
env.key_filename = '~/.ssh/id_rsa.remote'

def copy_file():
    put("/etc/issue", "/tmp/issue.test")

うまくいけば、以下のように出力されます。

  $ fab copy_file
  [192.168.1.2] Executing task 'copy_file'
  [192.168.1.2] put: /etc/issue -> /tmp/issue.test

  Done.
  Disconnecting from 192.168.1.2... done.

SFTP を使ってコピーするため、sshd が許可していないと、 下記のような出力が得られて失敗します。

  $ fab copy_file
  [192.168.1.2] Executing task 'copy_file'
  Traceback (most recent call last):
  ...中略...
    File "/home/usu/some/where/fabfile.py", line 13, in copy_file
      put("/etc/issue", "/tmp/issue.test")
  ...中略...
    File "/usr/lib/python2.7/dist-packages/paramiko/sftp_client.py", \
  line 105, in from_transport
      chan.invoke_subsystem('sftp')
  ...中略...
  paramiko.SSHException: Channel closed.
  Disconnecting from 192.168.1.2... done.

また、「get」という、遠隔のマシンからこっちへ持ってくるための関数もあります。

 

そして、「local」は、fab を実行するマシンでのみ処理を実行するための関数です。

from fabric.api import env, local, run

env.hosts = ['192.168.1.2']
env.key_filename = '~/.ssh/id_rsa.remote'

def printenv():
    local("printenv")
    run("printenv")

実行すると、こうなります。

  $ fab printenv
  [192.168.1.2] Executing task 'printenv'
  [localhost] local: printenv
  HISTFILESIZE=2048
  LESSOPEN=| /usr/bin/lesspipe %s
  ...中略...
  PWD=/home/usuda/some/where
  [192.168.1.2] run: printenv
  [192.168.1.2] out: HOSTNAME=centos6
  ...中略...
  [192.168.1.2] out: _=/usr/bin/printenv

  Done.
  Disconnecting from 192.168.1.2... done.

他に、「sudo」や「reboot」といった、 ちょっとドキドキする関数も用意されています。

最後に、実用的ぽい例を…

最後に、やや実用的な例を、ひとつ示したいと思います。

以下では、sshd_config をホストごとに用意しておき、それをコピーして適用する、 というのをやっています。

from fabric.api import env, put, sudo

env.hosts = ['192.168.1.2']
env.key_filename = '~/.ssh/id_rsa.remote'

def update_sshd():
    put("sshd_config." + env.host, "/etc/ssh/sshd_config",
        use_sudo=True, mode=0600)
    sudo("chown root.root /etc/ssh/sshd_config")
    sudo("service sshd reload")

env.host によって、遠隔のホスト名を知ることができます。
それから、put にはいくつか引数があります。
use_sudo に True を指定すると sudo 経由で実行してくれます。
また、mode で、ファイルのモードを指定できます。
ただ、ファイルの所有者が root でないため、 次のsudoで所有者を root にしています。そして最後に、sshdをreloadしています。

それから、以下のように、sshd_config.ホスト を用意しておきます。

  $ ls
  fabfile.py   sshd_config.192.168.1.1   sshd_config.192.168.1.pub
  fabfile.pyc  sshd_config.192.168.1.2

そして fab を実行すれば、sshd_config をコピーして、sshd を reload します。 するはずです。

  $ fab update_sshd
  [192.168.1.2] Executing task 'update_sshd'
  [192.168.1.2] put: sshd_config.192.168.1.2 -> /etc/ssh/sshd_config
  [192.168.1.2] out: sudo password: (自分のパスワードを入力)
  [192.168.1.2] sudo: chown root.root /etc/ssh/sshd_config
  [192.168.1.2] out: sudo password:
  [192.168.1.2] sudo: service sshd reload
  [192.168.1.2] out: sudo password:
  [192.168.1.2] out: sshd を再読み込み中:                  [  OK  ]

  Done.
  Disconnecting from 192.168.1.2... done.

もとのファイル名を、ホスト名ではなく引数で指定することもできます。

from fabric.api import env, put, sudo

env.hosts = ['192.168.1.2']
env.key_filename = '~/.ssh/id_rsa.remote'

def update_sshd(suffix=None):
    if suffix is None:
        suffix = env.host
    put("sshd_config." + suffix, "/etc/ssh/sshd_config",
        use_sudo=True, mode=0600)
    sudo("chown root.root /etc/ssh/sshd_config")
    sudo("service sshd reload")

引数を指定して実行するには、関数名の後に「:引数の値」をつけます。

  $ fab update_sshd:pub
  [192.168.1.2] Executing task 'update_sshd'
  [192.168.1.2] put: sshd_config.192.168.1.pub -> /etc/ssh/sshd_config
  ...後略...

引数は、「引数名=値」での指定や、「,」で区切って複数指定することも可能です。

  $ fab rescue_mates:first=Mikasa,second=Armin

おわりに

以上、Fabric の使い方を、さらっとご紹介しました。

Python をご存じの方であれば、いろんな方法が思いつくのではないかと思います。 いろいろ試してみてください。

また、Puppet や Fabric 以外にも、Chef とか Capistrano とか、 星の数ほどではありませんが、管理ツールが世の中にはいろいろあるようです。 時間と気力のある貴兄は、興味のあるモノを試してみてくださいませ。

宿題の答え

前回の宿題は、

  Puppetの設定ファイルを、SCMで管理してみましょう。

でした。

わたしは、主に Ubuntu で試しているのですが、etckeeper という、 /etc 以下を SCM(Source Code Management) で管理するツールを使っていますので、 すでに SCM で管理をしてしまっています。

という状況ではありますが、/etc/puppet 以下を Mercurial で管理してみました。 まずは土台を作ります。

  # cd /etc/puppet/
  # hg init
  # hg add *
  files/sshd_config を追加登録中
  manifests/site.pp を追加登録中
  manifests/test.pp を追加登録中
  templates/hoge を追加登録中
  templates/main.cf.rh を追加登録中
  # hg commit -m "initial version of puppet"
  auth.conf
  files/sshd_config
  ...後略...

そして、たとえば sshd_config を更新する必要が生じた場合、 変更して commit したら、puppetrunなどで展開します。

  # hg commit -m 'update sshd_config' 
  files/sshd_config
  ...中略...
  # puppetrun --host=クライアント
  Triggering tamacent
  Getting status
  status is success
  クライアント finished with exit code 0
  Finished

で、やっぱり前の状態に戻したい、というときには、 戻して再度展開するということも、さらっとできます。

  # hg revert -r0 files/sshd_config
  # puppetrun --host=クライアント
  ...後略...

問題なければ、commit してしまえばよいですよね。

  # hg commit -m 'revert sshd_config'

他にも、複数のサーバの設定をSCMで集約して管理したりなど、 メリットはいろいろありそうです。

今回の宿題

今回の宿題は、

  Fabric で、ホスト毎に違うSSHの鍵を指定して、実行するものを書いて
  みましょう。

です。

まあ、普通は、SSHの鍵を何個も作ってそれぞれ指定する…のではなく、 1つの鍵で全部まかなったりするのではないかと思います。

ですが、歴史的経緯などで、ホスト毎に異なる鍵を使う必要があったり、 とあるホストへの接続には、みんなで共通の鍵を使わないといけないなどといった、 しがらみがあるかもしれません。

というわけで、ホスト毎に違うSSHの鍵を使って、パスワードを入力することなく、 実行できるものを作ってみてくださいませ。

あとがき

静的解析ツールを開発している Coverity 社では、 OSSのソースコードをスキャンして問題を検出する Coverity Scan サービス なるものを行っておられます。

Coverity Scan
https://scan.coverity.com/

そのレポートが公開されていましたので、さらっと目を通してみました。
上記ページから、Download the report というボタンをクリックすると、 氏名や会社などの情報を入力する必要がありますが、 レポート自体は無料で入手できます。ありがたいことに、日本語版もあります。

個人的にもっとも知りたかったのが、検出されたバグの種類です。
レポートには、修正済と未修正に分けて書かれていますが、 いずれも上位に挙がっていた項目は、「制御フロー問題」「NULLポインタの間接参照」 「リソースリーク」と「エラー処理の問題」でした。

変数の初期化忘れや、メモリの不正なアクセスなど、 ケアレス?なものが多いだろうと思っていたのですが、 プログラムの制御構造そのものにバグがあるというケースも、多くあるようです。

他にも、プロジェクトの規模や商用コードとの比較、 プロジェクトごとのレポートやインタビューなどもあり、興味深そうです。

とりあえずピンポイントで目を通しただけですので、 後でじっくり読んでみようと思います。

 

で、システム管理の世界にも、こういうチェックするツールがあるといいのになあ、 と思いました。
(あ、ひょっとするとあるのかも…ご存じでしたら教えてください。)

汎用的なものは難しいと思いますが、パケットフィルターの設定に矛盾がないかなど、 ピンポイントなチェックであれば、できそうな気がします。

 

…ええ、できそうな気がするだけで、具体的にどうすればいいのかというのは、 わたくしの脳みそではゼンゼンわからないのですが…。

いつの日か、何かが閃いたら、ここで披露させていただこうと思います。
え、ええ、もし閃いたら、です…。(どなたか、閃いてくださいませ。)

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、8月18日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- 次回発行時には、秋限定の栗モノが出回っていそうですね。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)
http://twitter.com/kuriking/ (栗つぶやき)
http://facebook.com/kuriking3 (栗顔本)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本