言語非依存でバイナリデータをやりとりするには
はじめに
色々なシステム間でバイナリデータのやり取りをする方法に興味を持っています.調べている中でUniversal Binary Format(UBF)という規格を知ったので,その元になっている資料をまとめてみました.これは,Getting Erlang to talk to the outside worldという名前で,プログラミングErlangの著者でもあるJoe Armstrong氏が書いています.この資料を章ごとにまとめてみました.
ここから
ABSTRACT
Erlangを使ってErlang以外の世界とデータをやりとりするにはどうすればいいでしょう.これは,Erlangを構成要素として使う分散アプリケーションを構築する際には重要な課題です.一般的な解決策は,XML,XML-schemas,SOAP,WSDLと言ったXML標準を使うことですが,非効率,かつ,複雑すぎます.そこで我々はUniversal Binaru Format(UBF)という簡単なバイナリスキーマを提案します.UBFスキーマはXML標準と同じ程度の記述能力を持ちますが,非常に簡単です.
INTRODUCTION
この資料で扱うのは,構成要素が非同期に通信する信頼性のある分散システムです.各構成要素は別々の言語で作られ,別々のOS上で動作し,ネットワーク上のどこかで動いています.このシステムでの課題は,これらの構成要素をどのように連携させればよいのか,ということと,システムを容易に構築可能な,使いやすい言語非依存なtransport layerをどのように作るか,の2点です.XMLを使うのは解決策のひとつですが,複雑すぎで冗長です.
XMLが大変だと言ってる
次の"PROBLEMS WITH XML"の章では,XMLの大変さについて書いてます.
OUR ARCHITECTURE
この資料では,下図のようなアーキテクチャのシステムを提案します.この図でBは"Black box"で,Cは"Contract Checker"を意味します.
+-+ +-+ |B|--C--|B| +-+ +-+ | C | +-+ +-+ +-+ |B|--C--|B|--C--|B| +-+ +-+ +-+
Black boxはシステムの構成要素で,それぞれが必要に応じてクライアントやサーバとして動作します.構成要素間にはcontract checkerがあります.contract checkerは構成要素間でのメッセージが正当かどうかをチェックします.
X X --> --> +------+ +------+ |Client|----C----|Server| +------+ +------+ <-- <-- (M,S1) (M,S1)
contract checkerの初期状態がSだとします.クライアントがサーバに向けてXというメッセージを送ると,contract checkerはXが型に従っているかどうか,状態Sで受けてよい型かどうかをチェックします.チェックして問題なければサーバに送信します.サーバがメッセージと状態から構成される組み合わせ{M,S1}を返すと,contract checkerはこのメッセージが現在の状態で受けてよいレスポンスかどうかをチェックします.{M,S1}が問題なければクライアントに送信すると供にcontract checkerの状態をS1にします.contract checkerはクライアントサーバ間で許容されるメッセージの順番や型に関するcontractによってパターン化できます.contractは簡単なnon-deterministic finite state machineと簡単なtype languageを使って定義できるので,以下のようなモデル化できます.
{}
これは,サーバがという状態で,という型のメッセージを受け取ると,という型のメッセージを返し,状態がになるということを現しています.
UBF - A UNIVERSAL BINARY FORMAT
contractはUBFという言語で記述します.UBFには
- UBF(A): data transport format
- UBF(B): UBF(A)で定義された型を記述するプログラミング言語
があります.
UBF(A) - A BINARY TRANSPORT FORMAT
この章の内容は間違いがあるようなので,quick summaryを見ながらまとめました.
表記 | 概要 |
---|---|
'...' | constantをスタックに積む |
"..." | stringをスタックに積む |
Int ~...~ | 長さIntのバイナリをスタックに積む |
`xxx` | スタックにxxx型というタグを付ける |
%...% | コメント |
[-][0-9]+ | Integer 資料上だと+でなく*になってるけど,おそらく間違い |
\s\n\r\t | (white spaceとして)無視する |
# | スタックにnilを積む |
& | スタックから2個エントリを取り出して(cons X Y)と置き換える |
{ | 構造体の開始 |
} | 構造体の終了 |
$ | スタックからエントリを返す |
Control | '"~%-0123456789{}#&$> の21個 |
>C | スタックから取り出してregister[C]にstoreする |
C | register[C]をスタックに積む |
となります.実際の例だと
'person'>p # {p,"Joe",123} & {p, 'fred', ~abc~} & $
というUBF(A)は
[{person, "Joe", 123}, {person, fred, <>}].
というerlangで記述したUBF(B)になります.4種類の基本型の後に`...`というsemantic tagを付けることができます.このタグはUBF(A)の世界では意味を持ちませんが,UBF(B)の世界で意味を持ちます.例えば
12456 ~...~ `jpg`
はsemangtic tag "jpg"がついた12456バイトのバイナリデータを現すことになります.複雑な構造を作るにはStructとListを使います.Structは,
{ Obj1 Obj2 ... Objn }
と表記します.Obj1..Objnは任意のUBF(A) objectで要素数は固定です.例えばC言語なら構造体に該当します.Listsは,
# ObjN & ObjN-1 & ... & Obj2 & Obj1 &
と表記します.Obj1..ObjNはある特定の型で要素数は任意です.最初の要素がObj1でObj2と続くので注意が必要です.
PROGRAMMING BY CONTRACT
UBFの特徴はcontractにあります.contractはUBF(B)で記述します.
+------+ +----------+ +--------+ +----------+ +------+ | |-->| |-->|Contract|-->| |-->| | |Client| |UBF Driver| |checker | |UBF Driver| |Server| | |<--| |<--| |<--| |<--| | +------+ +----------+ +--------+ +----------+ +------+ Java / / / / / Erlang Java UBF(A) UBF(B) UBF(A) Erlang objects objects Contract objects terms
UBF(B)の実態はtype systemとprotocol description languageです.
type systemは
表記 | 概要 |
---|---|
int() | UBF(A) integer |
sting() | UBF(A) string |
constant() | UBF(A) constant |
bin() | UBF(A) binary data |
X() | Object type X |
となります.複合型は再帰的に定義します.
表記 | 概要 |
---|---|
{T1, T2, ..., Tn} | T1~Tnが型を現す要素数が固定された組み合わせ |
[T] | 要素がT型である要素数が任意の組み合わせ |
T1 | T2 | T1型かT2型の型であることを意味します |
さらに,UBF(B)では,新しい型を以下のように表現します.
+TYPE X() = Type
例えば
+TYPE persion() = {person, firstname(), lastname(), sex(), age()}. +TYPE firstname() = string(). +TYPE lastname() = string(). +TYPE age() = int(). +TYPE sex() = male | female. +TYPE people() = [person()].
と定義すると,
'person' >p
# {p "jim" "smith" male 10} &
# {p "susan" "jones" female 14} & $
はpeople()型になります.
さて,ここからはfile_serverというcontractについて考えてみます.
+NAME("file_server"). +VSN("ubf1.0"). +TYPES info() = info; description() = description; services() = services; contract() = contract; file() = string(); ls() = ls; files() = {files, [file()]}; getFile() = {get, file()}; noSuchFile() = noSuchFile. +STATE start ls() => files() & start; getFile() => binary() & start | noSuchFile() & stop. +ANYSTATE info() => string(); description() => string(); contract() => term().
+TYPESは型定義が複数あることを意味します.STATEは状態についての記述で,start状態にあるときにls()というメッセージを受け取ったら,files()というレスポンスを返し,start状態に戻ります.同じように,getFile()を受け取ったらbinary()型のレスポンスを返しstart状態に戻るか,noSuchFile()型のレスポンスを返しstop状態に移行することを意味します.NAME,VSN,ANYSTATEに関しては資料に説明がなくてよくわからないですが,ANYSTATEはstatelessな状況を記述するために使っているようです.
省略
この後"IMPLEMENTATION DETAILS"と"PERFORMANCE"という章はerlangで作った場合の話がでます.さらに,"FUTURE WORK"の章ではさらに高度な状態記述を書く話がでています.
RUNNING THE SYSTEM
前章で定義したcontractで動いているサーバにtelnetできたとすると,以下のような応答になります.表記の都合上$が入力,|がサーバ出力としました.
$ 'info'$ | {"I am a mini file server",'start'}$ $'ls'$ | {{'files', | # | "ubf.erl"& | "client.erl"& | "Makefile"& ...} | 'start'}$
さらに,'contract'$と入力すると,システムのcontractを出力するようですが,資料中にはその機能説明がありません.
$ 'contract'$ | {'contract', | {{'name',"file_server"}, | {'info',"I am a mini file server"}, | {'description'," | | Commands: | 'ls'$ List files | {'get' File} => Length ~ ... ~ | | noSuchFile | "}, | {'services',#}, | {'states', | #{'start', | #{'input',{'tuple',#{'prim','file'}& | {'constant','get'}&}, | #{'output',{'constant','noSuchFile'},'stop'}& | {'output',{'prim','binary'},'start'}&}& | {'input',{'constant','ls'}, | #{'output', | {'tuple', | #{'list',{'prim','string'}}& | {'constant','files'}&},'start'}&}&}&}, | {'types', | #{'file',{'prim','string'}}&}}}$
もういちど省略
この後の"A LARGER CONTRACT","EXPERIENCE","ACKNOWLEDGEMENTS"という章は省略します.
おわりに
概略はなんとなくわかってきたのですが,実際にシステム間でどんなデータをやりとりするのかはこの資料からはよくわかりません.githubから落としたプログラムがなんとか動き始めたので,それを使って確かめてみます.
UBFを動かす
はじめに
昨日erlangをrpm化しましたが,これはUniversal Binary Format(UBF)を試してみたかったからです.UBFについてはまた日を改めて書きますが,XMLのようなテキストベースでの情報流通形式の代わりにバイナリベースでの情報流通を実現します.マッキンダーの「東欧を支配するものはハートランドを制し,ハートランドを支配するものは世界島を制し,世界島を支配するものは世界を制す」とかにならって言うと,
バイナリフォーマットを支配するものはWebSocketを制し,WebSocketを支配するものはクラウドを制し,クラウドを支配するものは世界を制す
とか考えてるからです.
make
gitから落として来てsrcディレクトリ配下でmakeすれば簡単に動くと思ったんですが,はまったのでそのまとめ.priv/make/erl_make.mkというmakeするための補助ツールを書き直す必要がありました.
diff --git a/priv/make/erl_make.mk b/priv/make/erl_make.mk index ce9b680..b502065 100644 --- a/priv/make/erl_make.mk +++ b/priv/make/erl_make.mk @@ -58,7 +58,9 @@ endif export DIALYZER_PLT export DIALYZER -ERLDIRNAME1 := $(shell which $(ERL)) +ERLDIRNAME0 := $(shell which $(ERL)) +export ERLDIRNAME0 +ERLDIRNAME1 := $(shell readlink -e $(ERLDIRNAME0)) ERLDIRNAME2 := $(patsubst %/bin/erl,%,$(ERLDIRNAME1)) ERLDIRNAME3 := $(notdir $(ERLDIRNAME2)) @@ -76,11 +78,11 @@ endif endif ## well-known ERT applications -EDOCDIRNAME := $(wildcard $(ERLDIRNAME2)/lib/erlang/lib/edoc-*) -EIDIRNAME := $(wildcard $(ERLDIRNAME2)/lib/erlang/lib/erl_interface-*) -ERTSDIRNAME ?= $(wildcard $(ERLDIRNAME2)/lib/erlang/erts-*) -XMERLDIRNAME := $(wildcard $(ERLDIRNAME2)/lib/erlang/lib/xmerl-*) -EUNITDIRNAME := $(wildcard $(ERLDIRNAME2)/lib/erlang/lib/eunit-*) +EDOCDIRNAME := $(wildcard $(ERLDIRNAME2)/lib/edoc-*) +EIDIRNAME := $(wildcard $(ERLDIRNAME2)/lib/erl_interface-*) +ERTSDIRNAME ?= $(wildcard $(ERLDIRNAME2)/lib/erts-*) +XMERLDIRNAME := $(wildcard $(ERLDIRNAME2)/lib/xmerl-*) +EUNITDIRNAME := $(wildcard $(ERLDIRNAME2)/lib/eunit-*) EBIN = ../ebin DOC_DIR = ../doc.$(shell cat ../.otpversion)
作者の環境と大分違ってたみたいです.これでmake checkも通りました.make checkを実行した際にできあがるcheck.logの最後はこのような出力がでてきました.
=INFO REPORT==== 1-Jul-2010::05:09:59 === application: stateful_plugin exited: stopped type: temporary All 64 tests passed.
これでやっと次に進めます.
erlang rpmを作ってみる
はじめに
ubfとかebfとかっていうバイナリフォーマットに興味があってerlangをインストールしようとしました.CentOS5.5で,yumを使ってさくっとインストールしてみたんですが,肝心のプログラムがmakeできません.識者に聞いてみた所,バージョン古すぎとご神託を授かりました.そこで最新のバージョンをインストールとあいなったのですが,せっかくなのでrpm化しようとしてはまってしまいました.今回はrpm化するまでの苦闘の道のりです.
環境づくり
vmware上のcentosでrpmを作ってみました.しばらくほっといたvmなので,まずはupdateから実行して開発環境をインストールします.
$ sudo yum update $ sudo yum groupinstall "Development Tools" $ sudo yum install rpmdevtools $ mkdir -p ~/rpm/{BUILD,RPMS,SOURCES,SPECS,SRPMS} $ echo "%_topdir /home/daiba/rpm" > ~/.rpmmacros
これで基本的な環境はできあがったので,希望するerlangソースをダウンロードページから落とします
$ cd rpm/SOURCES $ wget http://www.erlang.org/download/otp_src_R13B04.tar.gz
後はspecファイルを作ればOK.が,これが大変なわけです.
spec file
ぐぐってみたら,FC用のerlang spec fileを見つけました.これをベースに作ってみたspec fileは次のようになります.
Name: my-erlang Version: R13B Release: 13.4%{?dist} Summary: General-purpose programming language and runtime environment Group: Development/Languages License: Erlang Public License URL: http://www.erlang.org Source: otp_src_R13B04.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRequires: ncurses-devel %description Erlang is a general-purpose programming language and runtime environment. Erlang has built-in support for concurrency, distribution and fault tolerance. Erlang is used in several large telecommunication systems from Ericsson. %prep [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT; %setup -n otp_src_R13B04 %build %configure make %install rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc AUTHORS EPLICENCE README.md %{_bindir}/* %{_libdir}/erlang %post %define erlangdir %{_libdir}/erlang %{erlangdir}/Install -minimal %{erlangdir} >/dev/null 2>/dev/null
ここまで作るのに涙なくしては語れないあれやこれやはありましたが,それはまた別の機会に.まねして作成したspec fileなのでよくわからないんですが,postセクションでInstallというコマンドを実行してるので,postunセクションで何か作業をしないといけない気がするんですが,よくわかりませんでした.とりあえず,インストールしても問題なかったので,しばらく使ってみようと思っています.
rpmを作る
spec file をerlang.specという名前にしてSPECSディレクトリに置いてbuildrpmを実行します.
$ cd ~/rpm $ cd SPECS $ vi erlang.spec $ rpmbuild -bb erlang.spec
そうすると延々またされたあげくにRPMS配下にmy-erlang-debuginfo-R13B-13.4.x86_64.rpmとmy-erlang-R13B-13.4.x86_64.rpmというrpmファイルができます.これでできあがり,
$ sudo rpm -ivh my-erlang-R13B-13.4.x86_64.rpm
とやればインストールできます.インストールできたか試すと
$ erl Erlang R13B04 (erts-5.7.5) [source] [64-bit] [rq:1] [async-threads:0] [kernel-poll:false] Eshell V5.7.5 (abort with ^G) 1> 123456789 * 9 . 1111111101
となりました.多分問題ないんでしょう.さて,最初にやろうとしたmakeは通るかなー
大規模ソーシャルサーチエンジンの構造
はじめに
Googleのように,どのドキュメントが適切なのかを選ぶのではなく,質問を誰にするのが適切かを選ぶ検索エンジンをAardvarkという会社が作り,その構造を論文で公開しました.この会社はもともとGoogleの社員だった人達が作った物で,最近Googleが買い上げました.今日はその論文の要旨をまとめてみました.
タイトルと著者
タイトルはGoogle創始者のLarry PageさんとSergey Brinさんが1988年に発表した"Anatomy of a Large-Scale Hypertextual Search Engine"と韻を踏んでいます.論文を発表したのは,Aardvark社のDamon HorowitzさんとStanford Univ.のSepandar D. Kamvarさんです.以下小見出しが章,少々見出しが節という形式で進めます.
ABSTRACT
Aardvarkは会社名であると供に,この会社が作ったSocial Search Engineの名前でもあります.ユーザはIM,email,web入力,text messageや音声で質問をします.Aardvarkは,質問をした人のextended social network中で,その質問に最も適切に答えられると考えた人にその質問を廻します.
INTRODUCTION
The Library and the Village
従来,情報を取得するためにはどうlibraryを使いこなせばいいか,という事が検索の理論的枠組みの基礎となっていました.Google自体"Stanford Digital Library project"から生まれました.一方で人々は,Aardvarkがvillage paradigmと呼んでいる情報取得方法を古くから使ってきました.情報は,村の中では薄く,かつ,人から人へ伝わりながら存在します.質問の答えを見つけるためには,正しい文章を見つけるのではなく,情報を持っている人を見つけなければなりません.
Aardvark
Aardvarkはvillage paradigmに基づいたsocial search engineです.
OVERVIEW
Main Components
- Crawler and Indexer:情報源を見つけてラベル付けします.ここでいう情報源とは,文章ではなくて人のことです.
- Query Analyzer:ユーザが必要としている情報を理解します.
- Ranking Function:適切な情報源を選択します.
- UI:人々に受け入れやすい,対話的な情報提供方法です
The Initiation of a User
ユーザが初めてAardvarkにアクセスすると,Aardvarkはどんな質問をそのユーザに廻すのが適切かを判断するindexing stepsを実施します.どんな質問を廻すかはそのユーザのextended social networkに依存するので,Aardvarkはユーザの友人をindexesすることと,ユーザとその友人との関係を調べます.その狙いは単にsocial networkを作る事にあるのではありません.ユーザから彼らのextended social networksを利用させてもらうことにあります.Aardvarkでは,ユーザは実社会における人間関係を反映したいくつかのgroupsで結びつきます.これらのgroupsはsocial networksから自動的に取り込むこともありますし,ユーザが編集することもできます.
さらにAardvarkは,ユーザのtopicにおける知識や経験がどのレベルにあるのかを複数の観点から判定しForward Indexにindexesします.Forward IndexにはuserIdに対するtopicごとのレベルのリスト,そのユーザが解答した質問内容と解答の質が格納されています.AardvarkはForward IndexからInverted Indexを作成し,そこでは任意のtopicIdに対して専門性があると判断したユーザのリストとそれらのユーザごとのレベル,回答の質と回答に要した時間を格納しています.
The Life of a Query
Aardvarkはユーザの質問をMessage data structureに正規化しConversation Managerに送ります.Conversation Managerがそのmessageを質問だと判断すると,その質問がどんなtopicsに属しているのかを調べる為Question Analyzerに問合せます.Conversation Managerは,Question Analyzerから得たtopics種別がユーザの考えと一致しているかどうかをユーザに確認し,違っていれば訂正してもらいます.それと同時にConversation ManagerはRouting Engineに対してRouting Suggestion Requestを発行します.Routing EngineはInverted IndexとSocial Graphを使って回答してくれそうな候補者リストを作成し,候補者の回答の質と質問者の希望にどれくらい合致するかを基にランク付けします.Routing Engineはランク付けしたRouting SuggestionsをConversation Mangerに返却します.Conversation ManagerはRouting Policyに従い,回答候補者に質問に返事できるかを問い合わせ続けます.最終的にConversation Managerは回答を質問者に返し,質問者と回答者が追加情報のやりとりを必要とする際には情報を中継します.
ANATOMY
The Model
Aardvarkのcoreは潜在的な回答者へ質問をroutingするための統計モデルにあります.このモデルは,aspect modelと呼ばれている物をネットワーク用にしたものを使っています.このモデルには2つの特徴があります.
-
- ユーザがtopic t()に属する質問qに答える確率
- どのような質問であるかに係らずユーザがユーザの質問に答える確率
これらふたつの確率を掛け合わせた物がscoring function です.
ranking problemとしての目標は,ユーザから質問qを与えられた時,を最大にするユーザのリストを作成することにあります.
Social Crawling
Aardvarkにとっての情報源は人なので,active userを維持し増やして行くことが必要です.そのためには使ってよかったという体験をユーザに与える必要があります.
Indexing People
Aardvarkはユーザについて以下の2点知る必要があります.
-
- ユーザがで答える事ができるtopic t
- ユーザとユーザとのconnections
まずはtopicについて.
の値は,過去そのユーザが行った発言から推測します.特定のtopicに関してある確率で回答するコンテンツジェネレータとしてユーザを見るわけです.すべてのtopicに対してスコアを作成しユーザプロファイルに登録します.加えて,
- ユーザが無視したtopic
- 機会があったのに回答を拒否したtopic
- 回答に対して別のユーザから否定的なコメントがついたtopic
を調べ,ユーザに対して送るべきではないtopicを学習します.
さらに,定期的にtopic strengthening algorithmを実行します.このアルゴリズムの基本的な考え方は,あるユーザが特定のtopicの専門家で,そのユーザのほとんどの友人がやはりそのtopicの専門家であれば,そのユーザが自分の友達グループの中でただ一人の専門家である場合よりも高い信頼を置く,というものです.
あるユーザを,そのユーザの友達グループをU,特定のtopicをtとしたとき
if then
となります.ここでは小さな定数です.
加えて,ふたつのsmoothing algorithmsを実行します.これは明示的に回答していないtopicに対して確率を割り当てる手段で,ひとつは,basic collaborating filtering techniquesで,似たようなtopicに対しては似たような値にします.もうひとつはsemantic similarityです.
これらの作業を経て,あるユーザに対するすべてのtopicに対するスコアを得ることができるので,となるように正規化しておきます.Bayesの定理から,あるtopicとユーザに対して
が得られます.ここで,は一様分布,はtopicを観測した割合です.Aardvarkは算出したをtopicをキーにした転地インデックスに格納し,質問が来た時に備えます.
次にConnectionsについて.
Aardvarkは任意のユーザ間のconnectionをさまざまな方法で算出します.ソーシャルネットワーク上での距離も重要ですが,demographics(人口統計学)や振る舞いの類似性も重要です.考慮している項目には以下のようなものがあります
- Social connection (common friends and affiliations)
- Demographic similarity
- Profile similarity (e.g. common favorite movies)
- Vocabulary match (e.g. IM shortcuts)
- Chattiness match (freequency of follow-up messages)
- Verbosity match (the average length of messages)
- Politeness match (e.g. the use of "Thanks")
- Speed match (responsiveness to other users)
ユーザ間のconnectionの強さはweighted cosine similarityを使って計算し,となるよう正規化します.
topicとconnectionは常時更新します.
Analyzing Questions
質問を解析する目的は質問qからtopicに対するスコアのリストを導きだすことにあります.まず,以下のClassifierを適用し,回答すべき質問を選別します.
- NonQuwestionClassifier: 質問かどうか
- InappropriateQuestionClassifier: Q&Aとして適切な文章かどうか
- TrivialQuestionClassifier: 人に聞かないと答えられない質問かどうか
- LocationSensitiveClassifier: 特定の地域に関する知識が必要かどうか
次に以下のTopicMapper algorithmsで得られた結果を統合して,質問に対するtopicのリストを得る事ができます.
- A KeywordMatchTopicMapper: user profileのtopicに記載された文字列と一致するか
- A TaxonomyTopicMapper: SVMを用いて約3,000種類に分類
- A SalientTermTopicMapper: 質問からの特徴語の抽出
- A UserTagTopicMapper: 質問者によって付けられたタグ
The Aardvark Ranking Algorithm
ランキングはRoutingEngineが行い,質問者と,Question Analyzerから受け取った情報を元に,よい回答をしてくれそうな人の順序リストを作成します.ユーザのランキングを決定するために必要な要素は,Topic Expertise ,Connectedness,Availabilityです.
- Topic Expertise: まず,Routing Engineは質問とsemantic matchesするユーザ群を探します.location-sensitiveな質問に関しては,ユーザプロフィールがその場所と一致するユーザのみ考慮します.
- Connectedness: 次にRouting Engineは回答者のtopicに関する専門性とは無関係に,質問者とどれぐらいの親和性があるかを見極めます.
- Availability: 3つ目にRouting Engineは質問に今回答してくれそうな人の優先度付けををします.これはIMでオンラインになっているかどうかなどを参考にします.
回答してくれそうな人のリストができるとAardvarkはガイドラインに基づいてコンタクトしてはならない人を除外します.残ったリストをConversation Managerに渡します.Conversation Managerはリストのそれぞれの人にアクセスして,回答が得られるまで,質問に答えてくれるかどうか訪ねて廻ります.
この後の論文は…
- User Interface
- EXAMPLES
- EVALUATION
- ACKNOWLEDGMENTS
- REFERENCES
と続きます.UIは面白いと思うのですが,アーキテクチャではないと思うのでここでは取り上げません.(疲れたともいう)詳しくは元論文をごらん頂くか,The Anatomy of Large-Scale Social Search Engine: ソーシャル検索エンジンAardvark論文の輪講用資料 - シリコンの谷のゾンビに載っている資料をごらんください.
おわりに
いくつかアルゴリズムの名前が出てくるんですが,それがなんだかわかってません.勉強しないと.最近ソーシャルアプリ流行だし,答えを知ってる人を推薦してくれるアプリというのは面白いと思うんですが,いつになったら自分で作れることやら… とりあえず,睡眠不足の日々が解消できてうれしいです.
bash complete でperldoc
bash-completionがないー
bash-completionが入ってない環境でBig Sky :: perldocのbash-completionが激しく便利でうれしょん出た。のようなことができたらいいなと思って試してみました.bashは':'をファイルセパレータに使っているのでHackが必要です.bash-completionのcontribにperl用のコマンドがあって,それを見ながら作ったのがこれ.
コード
function _myperldoc () { local mod cur word prev local cur=${COMP_WORDS[COMP_CWORD]} local prev=${COMP_WORDS[COMP_CWORD-1]} export mod=${COMP_LINE/perldoc/} case $prev in -f) COMPREPLY=( $( compgen -W 'chomp chop chr crypt hex index lc \ lcfirst length oct ord pack q qq reverse rindex sprintf \ substr tr uc ucfirst y m pos quotemeta s split study qr abs \ atan2 cos exp hex int log oct rand sin sqrt srand pop push \ shift splice unshift grep join map qw reverse sort unpack \ delete each exists keys values binmode close closedir \ dbmclose dbmopen die eof fileno flock format getc print \ printf read readdir rewinddir seek seekdir select syscall \ sysread sysseek syswrite tell telldir truncate warn write \ pack read syscall sysread syswrite unpack vec -X chdir chmod \ chown chroot fcntl glob ioctl link lstat mkdir open opendir \ readlink rename rmdir stat symlink umask unlink utime caller \ continue do dump eval exit goto last next redo return \ sub wantarray caller import local my our package use defined \ formline reset scalar undef \ alarm exec fork getpgrp getppid getpriority kill pipe qx \ setpgrp setpriority sleep system times wait waitpid \ import no package require use bless dbmclose dbmopen package \ ref tie tied untie use accept bind connect getpeername \ getsockname getsockopt listen recv send setsockopt shutdown \ socket socketpair msgctl msgget msgrcv msgsnd semctl semget \ semop shmctl shmget shmread shmwrite endgrent endhostent \ endnetent endpwent getgrent getgrgid getgrnam getlogin \ getpwent getpwnam getpwuid setgrent setpwent endprotoent \ endservent gethostbyaddr gethostbyname gethostent \ getnetbyaddr getnetbyname getnetent getprotobyname \ getprotobynumber getprotoent getservbyname getservbyport \ getservent sethostent setnetent setprotoent setservent \ gmtime localtime time times' -- "$cur" ) ) return 0 ;; esac if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W '-h -V -r -i -t -u -m -n -l -F -v -T -d -o -M -w -X -q'' -- "$cur" )) else word=" `perl -MExtUtils::Installed -le \ '$n = $ENV{mod}; $n =~ s/\s+//; $i = ExtUtils::Installed->new; \ @m = $i->modules; @m = grep{/^$n/}@m; @m = map{s/^$n//; $_}@m; print join q{ }, @m'` " COMPREPLY=( $( compgen -W "${word}" ) ) fi } complete -F _myperldoc perldoc
モジュールと引数候補を出す所は作りましたが,関数一覧はcontribにあったものを使いました.一覧を作るにはどうするのがいいんでしょうね?
使い方
ちょっと時間はかかりますが,perldocと書いてからtabを3回押すと
$ perldoc Display all 451 possibilities? (y or n)
という感じで表示します.yを押すと一覧表示です.モジュールに関しては'::'まで入力してtabを2回押してください
$ perldoc IO:: All Compress::Bzip2 Handle::Util Socket::SSL Stringy Zlib Compress::Base Compress::Zlib Prompt String Tty $ perldoc IO::
となります.下位のモジュールにアクセスする時も'::'まで書いてください.クラス名の補完は残念ながらできないです.私の場合は,.profileに
. ~/.myperldoc
という行を追加してみました.少し使ってみて使えるかどうか試してみようと思ってます.あ,まだgithubとかには上げてません.まだ安定してない感じです.もうshellでのプログラミング忘れてしまいました…
jetpackでtwitter client
何度目かのjavascript熱
普段xircdを使ってtwitterをチェックしていたのですが,いじっている内に動きがおかしくなってきたこともあって,クライアントを変えることにしました.firefox用のEcofonをしばらく使ってみたのですが,自分が欲しいのはlistなんて機能とは関係なく,リアルタイムにtwitをポップアップしてくれるだけのツールだと気づいたので,作ってみる事にしました.
ポーリングにチャレンジ
最終的にはstreaming APIを使ってリアルタイムにポップアップするようにしたいのですが,まずは肩ならしとしてapi.twitter.comをポーリングするスクリプトを書いてみました.久しぶりに書いたので結構色々なことを忘れていました...jetpackを使うにはjetpack用のjavascriptファイルとそれを呼び出すhtmlファイルを書く必要があります.今回はdropboxのpublicフォルダにjsとhtmlファイルをおいて,それを呼び出すようにしてみました.それぞれの名前をtwitter-notifier.html, twitter-notifier.jsとすると,twitter-notifier.htmlはこんな感じ.
<title>Twitter notifier</title> <link rel="jetpack" href="twitter-notifier.js"> <h1>Twitter notifier</h1> <p>Displays a notification bubble whenever you have an unread tweet in Twitter.</p> <p>Version 0.2 - 12 Feb 2010</p> <p>Code is <a href="http://dl.dropbox.com/u/USERID/jetpack/TwitterNotifier/twitter-notifier.js">here</a> .</p>
実際に動くjavascriptは以下のようになります。
jetpack.future.import("storage.simple"); twitter = { update: function () { $.ajax({ type: "GET", url: "http://twitter.com/statuses/friends_timeline.json?since_id="+store.lastId, dataType: "json", success: function (tweets) { if (tweets.length == 0) return; tweets.sort(function (a, b) { return a.id - b.id; }); $.each(tweets, function () { if (this.id > store.lastId) { store.lastId = this.id; queue.push({ title: this.user.name, body: this.text, icon: this.user.profile_image_url }); } }); twitter.showNotifications(); }, error: function (req, status, error) { console.log(status + ' ' + error); } }); }, showNotifications: function () { if (queue.length > 0) { jetpack.notifications.show(queue.shift()); notifier = setTimeout(twitter.showNotifications, 6000); } else clearTimeout(notifier); }, } store = jetpack.storage.simple; if (!store.lastId) store.lastId = 1; queue = []; twitter.update(); setInterval(twitter.update, 60*1000);
このAPIはベーシック認証を使っているので,FireFoxを起動したときにアカウントとパスワードを聞いてきます.後は1分毎にサイトをチェックして,新規twitがあればそれをNotificationとして表示します.私の環境はmacでGrowlを使っているので,Growlがポップアップしてきます.
さて,
streamAPIを使うにはどのライブラリを使うと楽かなー
OpenVZを使ってみる
はじめに
共用サーバのような物を作ろうと思って,chrootとSElinuxの組み合わせをどうすればいいのか考えていたらOpenVZというものを教えてもらいました.VMWare上で環境を動かすところまでうまくいったので,そのまとめです.
ホスト環境
windowsXPにVMWare Serverを入れて,その上にCentOS 5.4 x86_64をインストールしました.サーバの名前はpotate,ネットワークはNAT構成で,512MBのメモリと8GBの仮想ディスクを設定しました.インストールに使ったのはCentOS-5.4-x86_64-netinstall.isoで,textベースのインストーラを使用し,ナビゲーションは英語で,キーボード設定はjp106,IPv4のdhcpのみ使って,http://ftp.riken.jp/Linux/centos/5.4/os/x86_64から必要なデータをダウンロードしました.Package Selectionでは何も選択していません.SELinuxはdiabledにしておきました.
OpenVZのインストール
基本的にはQuick installationを見ながらの作業になりますが,x86_64のツールにはバグがあるようなので,途中からInstall OpenVZ on a x86_64を見る必要があります.
Quick installationを見ての作業
まずはパッケージを最新の状態にしてからOpenVZ用のカーネルをインストールします.
# yum update # cd /etc/yum.repos.d # wget http://download.openvz.org/openvz.repo # rpm --import http://download.openvz.org/RPM-GPG-Key-OpenVZ # yum install ovzkernel.x86_64 ... Installed: ovzkernel.x86_64 0:2.6.18-164.10.1.el5.028stab067.4
次にkernel周りの設定を変更します.まずは/boot/grub/grub.conf
--- grub.conf.org 2010-02-09 18:09:13.000000000 +0900 +++ grub.conf 2010-02-09 18:09:29.000000000 +0900 @@ -11,7 +11,7 @@ timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu -title CentOS (2.6.18-164.10.1.el5.028stab067.4) +title OpenVZ (2.6.18-164.10.1.el5.028stab067.4) root (hd0,0) kernel /vmlinuz-2.6.18-164.10.1.el5.028stab067.4 ro root=/dev/VolGroup00/LogVol00 initrd /initrd-2.6.18-164.10.1.el5.028stab067.4.img
それから/etc/sysct.confを変更します.
--- sysctl.conf.org 2010-02-09 18:26:50.000000000 +0900 +++ sysctl.conf 2010-02-09 18:29:56.000000000 +0900 @@ -4,7 +4,10 @@ # sysctl.conf(5) for more details. # Controls IP packet forwarding -net.ipv4.ip_forward = 0 +net.ipv4.ip_forward = 1 + +# Controls proxy arp +net.ipv4.default.proxy_arp = 0 # Controls source route verification net.ipv4.conf.default.rp_filter = 1 @@ -12,8 +15,12 @@ # Do not accept source routing net.ipv4.conf.default.accept_source_route = 0 +# We do not want all our interfaces to send redirects +net.ipv4.conf.default.send_redirects = 1 +net.ipv4.conf.all.send_redirects = 0 + # Controls the System Request debugging functionality of the kernel -kernel.sysrq = 0 +kernel.sysrq = 1 # Controls whether core dumps will append the PID to the core filename # Useful for debugging multi-threaded applications
これで準備できたのでpotateをリブートします.Quick installationを見るのはここまでです.
Install OpenVZ on a x86 64 system Centos-Fedora を見ての作業
といっても,パッチをダウンロードして実行するだけです.
# cd /tmp # wget http://linux.carreira.com.pt/ovzutils/setx86_64-0.5.tar.gz # tar xvfz setx86_64-0.5.tar.gz # sh setx86_64 --------------------------------------------- Openvz to x86_64 platform (Ver. 0.5) --------------------------------------------- Your OS seems to be........ CentOS release 5.4 (Final) rpm, yum and python........ Found! setx86_64: line 90: [: too many arguments Python version... 2.4...... OK! rpm-python for x86_64...... Found! --------------------------------------------- ALL TESTS PASSED! Do you want to go on with the installation? [N/y] ... All templates installed! vzrpm python is fixed for 64 bits... Applying patches... patching file /usr/share/vzpkg/cache-os patching file /usr/share/vzpkg/functions patching file /usr/bin/vzyum patching file /usr/bin/vzrpm patching file /vz/template/centos/5/x86_64/config/install-post END INSTALL!
End INSTALL!がでれば作業終了です.ここで,コンテナ(OpenVZ用語でのゲストOS)でlocaleを変更するには/vz/template/centos/5/x86_64/config/.rpmmacrosの"%_install_langs C"と言う行を"%_install_langs C:pt_PT:pt_PT.UTF-8:en_US:en_US.UTF-8"のように変更するようですが,lang Cで構わなかったので,何も設定しませんでした.インストールできているかどうかは,x86_64系のテンプレートが存在するかどうかでチェックします.
# vzpkgls | grep x86_64 ... centos-5-x86_64-minimal centos-5-x86_64-default centos-4-x86_64-minimal centos-4-x86_64-default
このテンプレートからキャッシュテンプレートを作ります.自分でも用語がよくわからなくなってきましたが,まぁそこはきにせず.出来上がる際にcron.daily関連のエラーが出ますが,これは無視します.
# vzpkgcache -f centos-5-x86_64-minimal ... Complete! chmod: cannot access `/etc/cron.daily/slocate.cron': No such file or directory chmod: cannot access `/etc/cron.daily/makewhatis.cron': No such file or directory Packing cache file centos-5-x86_64-minimal.tar.gz ... Cache file centos-5-x86_64-minimal.tar.gz [120M] created.
これでできた/vz/template/cacheにあるキャッシュテンプレートからコンテナを作ります.
# vzctl create 101 --ostemplate centos-5-x86_64-minimal Creating container private area (centos-5-x86_64-minimal) Performing postcreate actions Container private area was created
コンテナIDとしては101以上の値を使ってください.これでコンテナができたので,起動します.
# vzctl start 101 Starting container ... Container is mounted Setting CPU units: 1000 Configure meminfo: 65536 Container start in progress...
起動できたかどうかの確認はvzlistコマンドを使います.
# vzlist -a CTID NPROC STATUS IP_ADDR HOSTNAME 101 2 running - -
動いているようなので,コンテナに入ってみます.exitすればコンテナから抜けます.
# vzctl enter 101 entered into CT 101 [root@potate /]# exit logout exited from CT 101
コンテナに入らずホストからモジュールをインストールしたりアップデートしたりできます.例えばコンテナにアップデートするには,
# vzyum 101 update exec /usr/bin/yum -c /vz/template/centos/5/x86_64/config/yum.conf --installroot /vz/root/101 update Excluding Packages in global exclude list Finished Setting up Update Process No Packages marked for Update
となりますし,dhcpクライアントをインストールするには
# vzyum 101 install dhclient
となります.コンテナ制御のコマンドはContainer creationのページにまとまっています.
ネットワーク設定
コンテナは初期状態でネットワーク設定がまったくありません.ifconfig -aを実行するとこんな感じです.venetはコンテナ用の簡易インタフェースで,簡単に設定できるのですが,あえて使いません.
# vzctl exec 101 ifconfig -a lo Link encap:Local Loopback LOOPBACK MTU:16436 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) venet0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 BROADCAST POINTOPOINT NOARP MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
いばらの道を求めてeth0をコンテナに作ります.
# vzctl set 101 --netif_add eth0 --save Configure veth devices: veth101.0 Saved parameters for CT 101 # ifconfig veth101.0 0
できあがったインタフェースをホストとコンテナの両方で確認してみると次のようになります.
# ifconfig -a eth0 Link encap:Ethernet HWaddr 00:0C:29:4F:48:12 inet addr:192.168.121.138 Bcast:192.168.121.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fe4f:4812/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:884 errors:0 dropped:0 overruns:0 frame:0 TX packets:451 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:83836 (81.8 KiB) TX bytes:63347 (61.8 KiB) Base address:0x2000 Memory:d8920000-d8940000 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:560 (560.0 b) TX bytes:560 (560.0 b) sit0 Link encap:IPv6-in-IPv4 NOARP MTU:1480 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) venet0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 UP BROADCAST POINTOPOINT RUNNING NOARP MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) veth101.0 Link encap:Ethernet HWaddr 00:18:51:54:D2:13 inet6 addr: fe80::218:51ff:fe54:d213/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:22 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) # vzctl exec 101 ifconfig -a eth0 Link encap:Ethernet HWaddr 00:18:51:53:19:C4 BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) lo Link encap:Local Loopback LOOPBACK MTU:16436 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) venet0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 BROADCAST POINTOPOINT NOARP MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
ホストとコンテナの間で通信ができるようにするため,ホストにブリッジユーティリティをインストールして,vzbr0というブリッジデバイスを作成します.
# yum install bridge-utils # brctl addbr vzbr0 # brctl show bridge name bridge id STP enabled interfaces vzbr0 8000.000000000000 no
vzbr0用にネットワーク設定を行います.
# ifconfig vzbr0 0 # ls /proc/sys/net/ipv4/conf all default eth0 lo venet0 vzbr0 # cat /proc/sys/net/ipv4/conf/vzbr0/forwarding 1 # cat /proc/sys/net/ipv4/conf/vzbr0/proxy_arp 0 # echo 1 > /proc/sys/net/ipv4/conf/vzbr0/proxy_arp
network-scripts配下のifcfg-eth0を変更して,ifcfg-vzbr0とifcfg-veth101.0を新規作成します.
# cd /etc/sysconfig/network-scripts # diff -u ifcfg-eth0.org ifcfg-eth0 --- ifcfg-eth0.org 2010-02-10 11:44:20.000000000 +0900 +++ ifcfg-eth0 2010-02-10 11:46:06.000000000 +0900 @@ -1,6 +1,5 @@ # Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) DEVICE=eth0 -BOOTPROTO=dhcp -HWADDR=00:0C:29:4F:48:12 +BOOTPROTO=none ONBOOT=yes -DHCP_HOSTNAME=potate +BRIDGE=vzbr0 # cat ifcfg-vzbr0 DEVICE=vzbr0 BOOTPROTO=dhcp ONBOOT=yes DHCP_HOSTNAME=potate TYPE=bridge # cat ifcfg-veth101.0 DEVICE=veth101.0 ONBOOT=yes BRIDGE=vzbr0
これでネットワーク周りの設定ができたのでリブートします.リブート後にインタフェースが正常に動作していることを確認します.
# ifconfig -a eth0 Link encap:Ethernet HWaddr 00:0C:29:4F:48:12 inet6 addr: fe80::20c:29ff:fe4f:4812/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1231 errors:0 dropped:0 overruns:0 frame:0 TX packets:102 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:699302 (682.9 KiB) TX bytes:18000 (17.5 KiB) Base address:0x2000 Memory:d8920000-d8940000 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:560 (560.0 b) TX bytes:560 (560.0 b) sit0 Link encap:IPv6-in-IPv4 NOARP MTU:1480 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) venet0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 UP BROADCAST POINTOPOINT RUNNING NOARP MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) veth101.0 Link encap:Ethernet HWaddr 00:18:51:54:D2:13 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:7 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) vzbr0 Link encap:Ethernet HWaddr 00:0C:29:4F:48:12 inet addr:192.168.121.138 Bcast:192.168.121.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fe4f:4812/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:100 errors:0 dropped:0 overruns:0 frame:0 TX packets:123 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:7624 (7.4 KiB) TX bytes:19997 (19.5 KiB)
vzbr0にアドレスが正しく割振られていることがわかります.ちなみにブリッジの状態は以下のようになります.
# brctl show
bridge name bridge id STP enabled interfaces
vzbr0 8000.000c294f4812 no veth101.0
eth0
ここまでできたら,後はコンテナ側の作業です./etc/sysconfig/networkと/etc/sysconfig/network-scripts/ifcfg-eth0を新設します.
# vzctl enter 101 entered into CT 101 # cd /etc/sysconfig # cat network NETWORKING="yes" NETWORKING_IPV6=no HOSTNAME=taro # cd /etc/sysconfig/network-scripts # cat ifcfg-eth0 DEVICE=eth0 BOOTPROTO=dhcp ONBOOT=yes DHCP_HOSTNAME=taro
これで準備が完了したので,コンテナから抜けてリスタートさせます.
# exit # vzctl restart 101 Restarting container Stopping container ... Container was stopped Container is unmounted Starting container ... Container is mounted Setting CPU units: 1000 Configure meminfo: 65536 Configure veth devices: veth101.0 Container start in progress... # vzlist CTID NPROC STATUS IP_ADDR HOSTNAME 101 3 running - - # vzctl exec 101 ifconfig eth0 eth0 Link encap:Ethernet HWaddr 00:18:51:53:19:C4 inet addr:192.168.121.139 Bcast:192.168.121.255 Mask:255.255.255.0 inet6 addr: fe80::218:51ff:fe53:19c4/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:11 errors:0 dropped:0 overruns:0 frame:0 TX packets:13 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1251 (1.2 KiB) TX bytes:1800 (1.7 KiB)