仙石浩明の日記

2010年4月20日

Linux サーバ同士をシリアルケーブルでつなぐには寡黙な getty が必要 hatena_b

私の自宅 LAN (GCD) の対外ルータである 2台の Linux サーバ (senriasao) は、 双方のシリアルポート (つまり DSUB9ピンの RS-232C) 同士がつながっている。 いまさら RS-232C ? と思う人が大半だと思うが、 最後の命綱としての安心感は測り知れない。

つまりサーバをリモートから (ネットワーク経由で ssh ログインして) いじっていると、 ちょっとしたミスで操作不能に陥ってしまうことがある。 例えば NIC を down してしまった、 iptables で DROP する設定にしてしまった、 sshd を殺してしまった、 等々。 あるいは、 リモートから再起動を行なう場合、 起動スクリプトのほんの些細な設定ミスで、 リモートからは操作不能になってしまう。

こんなとき、 2台のサーバのシリアルポート同士を RS-232C クロスケーブル (シリアルケーブル) で接続しておけば、 生きている方のサーバからシリアルケーブル経由でログインできて、 リモートからは操作不能に陥ったサーバのネットワーク設定を修復したり、 sshd を起動し直したり、 あるいは再起動の場合であれば、 GRUB を操作することができる (ML115 などであれば BIOS 設定までいじれる)。

職場のサーバ群は、 もちろん IPMI を利用していて大抵の操作は IPMI でできてしまうのでシリアルケーブルの出番はあまりないのだが、 それでもやはり最後の命綱がある安心感は何ものにも代えがたい。 しかも数百円のケーブル一本で済むのだから、 掛けておくべき保険だろう。

シリアルケーブル経由でサーバにログインするには、 そのサーバの /dev/ttyS0 (シリアルポート COM1 の場合) で getty を動かしておく必要がある。 例えば GCD の場合 mgetty を使っているので、 /etc/inittab に

# Dialin lines
s0:25:respawn:/usr/sbin/mgetty ttyS0

などと設定している。 シリアルケーブルでつながった 2台の Linux サーバ senri と asao において、 asao から senri へシリアルケーブル経由でアクセスすると、 senri のシリアルコンソールが表示される:

asao:/home/sengoku % cu ttyS0
Connected.

Welcome to Linux 2.6.31.13-x86_64.


senri.gcd.org!login: root
otp-md5 299 se5047 ext
Response or Password:
Last login: (null) on /dev/ttyS0

senri.gcd.org:/root # tty
/dev/ttyS0
senri.gcd.org:/root # 

たとえ senri のネットワーク機能が全滅していたとしても、 mgetty は /sbin/init から直接起動されるので影響を受けない。 シリアルコンソールから root でログインして復旧作業を行なうことができる。 逆に、 asao のネットワーク機能が全滅したときは、 senri へ ssh ログインした上で asao へシリアルケーブル経由でアクセスすればよい。 ネットワーク機能が麻痺する可能性があるような危険な作業を senri と asao の両方で同時に行なったりしないようにすれば、 何が起きてもどちらかは生きていることが保証できる。

さて、 両サーバで mgetty が動いているときは以上で問題無いのだが、 どちらかのサーバを再起動するときなど、 mgetty 以外のものが動くときは状況が変わってくる。

More...
Filed under: システム構築・運用 — hiroaki_sengoku @ 07:48
2010年4月2日

「無知の無知」への 3ステップ hatena_b

KLab(株)は、 2007年から新卒採用を行っています。
今年も例年通り、4月1日に入社式を行いました。

- o -

みなさん、入社おめでとうございます。 社長のお話が終わり、みなさんは挨拶が終わって、 緊張もほぐれてきたのではないかと思います。 ここからは各役員の挨拶なのですが、 なぜか私だけは挨拶だけでなく (長くならない範囲で ^^;) 話もしろということになったらしいので、 話を捻り出してみます。

「考えることが大事」ということは社長のお話にもありましたし、 みなさんも既によく知っていることだと思います。 ただ、 知っていることと実際に実行できることとの間には越えがたい壁があることも事実で、 分かっちゃいるけどついつい考えなくなってしまう、 あるいは考えているつもりが、 いつのまにか深く考えることがなくなってしまうものなのでしょう。 そもそも自分がどのくらい考えているかなんて、 なかなか意識するのは難しいですよね。

入社時にはみんな等しく、 これからは「考える習慣」を身につけよう、 と決意を新たにしたはずなのに、 3年で大きな差がついてしまうのが現実です。 考える習慣を身につけた人がどんどん成長するのに対し、 考えることを習慣化し損なった人は停滞したままなので、 その後も差は広がる一方。 10年 20年もたつととんでもない差になってしまいます。

なぜこんなにも差がついてしまうのでしょうか? ただやみくもに 「考えよう」 としても、 具体的に何をすればいいのかよく分かりませんよね? なので逆に何をしてはいけないかについて今日はお話ししたいと思います。 今日からみっちり 2ヶ月間、 新人研修でいろいろなことを学んでいくみなさんにとって、 「何をしてはいけないか」 を押えておくことはきっと役に立つと思います。

私は仕事柄、 面接をする機会が多いのですが、 お会いする人の中には考える習慣が全くない人もいます。 ご本人にはそういう自覚が全く無く、 人並みには考えていると思っているようなのですが、 私から見ると正に 「人生オワタ」 状態で、 なぜそうなってしまったのだろうかと考えているうちに、 ついついその人の身の上を根掘り葉掘り聞いて人生相談モードへ入ってしまうので、 そういうことを繰り返すうちに、 だんだん原因が見えてきたように感じています。

考える習慣を持たない人に共通する問題点として 「無知の知」 ならぬ 「無知の無知」 があります。 自分が分かってないことを分かってない、 自分の浅慮では到底及ばない領域があることが全く想像できない、 いわば 「井の中の蛙」 状態ですね。 「無知の無知」 状態になってしまうと、 今の自分の考え方で満足してしまい、 今の自分の枠を越えて考えてみようという発想がでてきません。 当然、 考える習慣もなくなってしまうわけです。 なぜこうなってしまうのか? 次の 3つのステップを経て 「無知の無知」 状態に至るケースが多いように思います:

  1. 後で調べればいいや
  2. 何が分からないのか分からない
  3. 分かったつもり

「質問する前に考えろ」 「それくらい Google 検索などを使って調べろ」 「ググれカス」 などと言われるようになったのはいつのころからでしょうか? 確かに何でもかんでも 「教えて君」 では困りますが、 「すぐ質問すること」 = 「悪いこと」 とする風潮はいかがなものかと思います。 こういう風潮が、 「聞くのは恥ずかしい」 「後で調べればいいや」 という意識を生んでいないでしょうか。

ちなみに私は全く正反対で、 「分からないと言える」 = 「カッコイイ」 と中学生の頃から思い込んでるので、 今でも堂々と 「分からない」 を連発しています。 もちろん、 「CTO がこんなことも知らないのか?」 と思われる (^^;) リスクも無いわけではないので、 TPO を考慮せざるを得ないこともあるのがちょっと残念です。

確かに本当に後で調べるのならまだいいのですが大抵は忘れてしまいます。 仮に忘れずに後で調べて言葉の意味を知ったとしても時間は遡れません。 その場で意味を聞いていれば相手と有益な議論を展開できたのかもしれないのに、 その機会は永久に失われてしまうわけです。

そして何より怖いのは、 知らない言葉が出てきても何とも思わなくなってしまうことです。 ふつう、 相手の話の中に意味が取りにくい言葉があれば気持ち悪く感じ、 なんとかその気持ち悪さを解消しようと思うものだと思うのですが、 「後で調べればいいや」 と思ってるとだんだんこの 「気持ち悪さ」 が無くなってきます。 この 「不感症」 が最初のステップです。

そして一つの話の中に知らない言葉がいくつも出てきても、 何とも思わない状態になると次のステップが見えてきます。 知らない言葉が複数出てくれば、 当然話全体が分からなくなるし、 そもそも話自体に興味が持てなくなります。 こうなってしまうと、 「何が分からないか分からない」 状態に陥ります。 いわゆる 「質問したくても何を質問したらいいのか分からない」 状態ですね。

質問しようとしない人に、 「もっと質問しようよ」 と言うと返ってくる言葉が、この 「何を質問すればいいのか分からない」 です。 話を興味を持って聞くということが無くなってしまっているために、 相手が話していない部分を聞き出そうという意欲が失われてしまっています。 もちろん、 人の興味は十人十色ですから、 ある話題に興味が持てないというのは普通でしょう。 問題なのは、 どんな話であっても興味が持てないことにあります。 しかも本人的にはそれが普通な状態なので、 他人の話を興味を持って聞くということがどんな体験だったのか、 もう覚えていなかったりします。 この 「無関心・無気力」 が第2 のステップとなります。

この第2 のステップの怖いところは自覚症状があまり無いことにあります。 自分は 「無気力」 ではない、 と思う人が大半だとは思いますが、 どんな話を聞いても、 質問したいことが思い浮かばないようだと 「第2 のステップ」 がかなり進行中であるわけで要注意です。 なんとか気付いて危機感を持って欲しいですし、 私はことある毎に 「質問しろ〜」 と口を酸っぱくして言ってるのですが、 長年染み付いた習慣というのはなかなか克服できないものなのかも知れません。

第2 のステップは 「分からない」 ということ自体は自覚できているのでまだ救いがあるのですが、 この症状が進むと第3 のステップである 「分かったつもり」 に至ります。 「分からない」 という意識さえあれば何かのきっかけで 「分かろうとする意欲」 が芽生えるかもしれないのですが、 分かっていないこと自体が分からなくなると、 その可能性すら無くなってしまうので末期的です。

何を聞いても 「分かったつもり」 になってしまって、 表面的な理解だけで満足するようになってしまうと、 自分の考え方と相手の考え方が異なっていてもそれに気付かない、 ということが起り得ます。 つまり相手の話を自分の思考の枠内だけで理解してしまうわけです。 まさに 「無知の無知」 です。

と、 いうわけで今日からの研修では決して疑問点を残さないよう、 積極的に質問してください。 また、 「分かった」 と思っても本当に理解しているのか、 今一度自分を疑ってみてください。

例えば、 半年前に内定式で渋滞の話をしました。 忘れてしまった人は私のブログを参照してください。 社会人経験がまだ無いみなさんには、 あの話を完全に理解することはなかなか難しいのではないかと思いますが、 「分からない」 という感覚を持っていますか? そして分からないとすればどこが分からないのか考え、 何を質問すれば自分の理解を深められるか是非考えてみてください。

まだまだ自分は 「分かっていない」 と自分を疑うことこそが、 考えを深めていくために必要なのだと思います。 KLab への入社が、 みなさんの人生において飛躍のきっかけとなることを期待します。

Filed under: 元CTO の日記,自己啓発 — hiroaki_sengoku @ 13:19
2010年3月8日

tinydns のゾーンを MyDNS へ反映させるスクリプトを書いてみた

MyDNS というのは MySQL (あるいは PostgreSQL) のレコードを、 そのままゾーンレコードとして扱えるネームサーバ。 私は MyDNS を使って実験的にダイナミックDNSサービスを (もちろん無償で) 提供している。 実験と言いつつ、 サービス開始以来 2年以上安定的に継続できているし、 先月から海外レンタルサーバを使って地域分散したので、 仮に私の自宅の回線が切れてもネームサーバが見えなくなることはない。

gcd.jp のマスタネームサーバである ns.gcd.jp と、 スレーヴネームサーバである ns2.gcd.jp (海外サーバ fremont.gcd.org の別名。 名前の通りカルフォルニア州フリーモントにある) とは、 MySQL のレプリケーションによってゾーンデータを同期させている。 したがってマスタ側での変更が即座にスレーヴ側に伝わる。

ちなみに、 ネームサーバ間の同期でよく利用されるゾーン転送 (AXFR) は、 ゾーンデータを丸ごと転送するので (ゾーンが大きくなってくると) 同期頻度を高くすることが難しく、 ダイナミックDNSサービスにはあまり向いていない。 MySQL のレプリケーションでネームサーバ間の同期が行なえてしまう MyDNS は、 ダイナミックDNSサービス向きと言える。

ところが gcd.org では (ダイナミックではない) 普通のネームサーバ ns1.gcd.org も運用していて、 これは tinydns を利用している。 せっかく海外にサーバ fremont.gcd.org を借りたのだから、 tinydns で管理しているゾーンも fremont.gcd.org で引けるようにしたいが、 fremont に複数 IP アドレスを付与するのはお金がかかる (月額 $1 追加) ので、 fremont で MyDNS と tinydns の両方を走らせるわけにもいかない。

私が借りてるレンタルサーバ (正確に言うと VPS) Linode は、 もともと DNS サービス (マスタ/スレーヴどちらでも、ドメインいくつでも) を無料で利用できるので、 DNS のためだけに 1IP 追加する気にはちょっとなれない。

もちろん、 tinydns を止めてしまって全てのゾーンを MyDNS へ移行してしまうという解決策も無くはないのだが、 MyDNS に全面的に依存してしまうのは恐い気もする。 できれば tinydns 側はいじらずに、 tinydns のゾーンデータを MyDNS 側へ反映させる仕掛けを作りたい。

というわけで、 tinydns のゾーンデータを読み込み、 MyDNS のゾーンデータの形式で MySQL へレコードを書込む perl スクリプト tinydns2mydns を書いてみた (CVSリポジトリ)。

なお MyDNS には、 mydnsimport という外部からゾーンデータを取り込むツールが付属していて、 tinydns のゾーンデータもインポートできるのだが、 以下の欠陥があってゾーン転送目的には使えない:

  1. ゾーンの全レコードをいったん削除した上でインポートを行なう実装になっている。
  2. SRV レコードをインポートできない。
More...
Filed under: プログラミングと開発環境 — hiroaki_sengoku @ 09:25
2010年3月1日

x86_64 Linux などの 64bit 環境で MD5 を使うときの注意点 hatena_b

MD5 (Message Digest Algorithm 5) は、 RFC 1321 でアルゴリズムが紹介されていて、 Appendix (付録) として C によるリファレンス実装が付属しているが、 その global.h に

/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;

と書いてある。 すなわち 32bit 整数として UINT4 型を定義している。 x86_64 Linux を始め多くの 64bit Unix は LP64 すなわち long int (とポインタ) が 64bit な整数データモデルを採用している。 したがって UINT4 型の定義が 「unsigned long int」 のままで、 この MD5 リファレンス実装を使ってしまうと、 32bit であるべき UINT4 型が 64bit になってしまい、 間違ったハッシュ値を算出してしまう。

16bit CPU が主流だった大昔なら 「int が 16bit なデータモデルを採用している環境」 が多かったのかもしれないが、 RFC 1321 が出た 1992年ごろは既に 32bit CPU が主流だったわけで、 UINT4 型を 「int」 と定義しておいてくれてもよかったのにと思う。 そうすれば、 「long が 64bit なデータモデルを採用している環境」 が多くなる昨今でも (int は 32bit のままなので) 問題を起こさずに済んだだろうに。

試しにテストプログラムを書いてみる:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "global.h"
#include "md5.h"
#define DIGEST_LEN 16
#define BUFFER_LEN 256

int main(int argc, char *argv[]) {
    MD5_CTX context;
    unsigned char digest[DIGEST_LEN];
    unsigned char buf[BUFFER_LEN];
    int i;
    MD5Init(&context);
    while ((i=read(0, buf, BUFFER_LEN)) > 0) MD5Update(&context, buf, i);
    MD5Final(digest, &context);
    for (i=0; i < DIGEST_LEN; i++) printf("%02x", digest[i]);
    printf("\n");
    return 0;
}

32bit 環境 (i686 Linux) では正しく動く:

senri:/home/sengoku/src/md5 % uname -m
i686
senri:/home/sengoku/src/md5 % ls
global.h  main.c  md5.h  md5c.c
senri:/home/sengoku/src/md5 % cc -Wall main.c md5c.c
senri:/home/sengoku/src/md5 % file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped
senri:/home/sengoku/src/md5 % echo "Hello, world" | ./a.out
a7966bf58e23583c9a5a4059383ff850
senri:/home/sengoku/src/md5 % echo "Hello, world" | openssl md5
a7966bf58e23583c9a5a4059383ff850

ところが、 64bit 環境 (x86_64 Linux) だと:

senri:/home/sengoku/src/md5 % uname -m
x86_64
senri:/home/sengoku/src/md5 % cc -Wall main.c md5c.c
senri:/home/sengoku/src/md5 % file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), for GNU/Linux 2.4.0, dynamically linked (uses shared libs), not stripped
senri:/home/sengoku/src/md5 % echo "Hello, world" | ./a.out
fd578222c6a471623ea1e3eb2b6e6f6b

などと、 誤った MD5 の値が出力されてしまう。

MD5 の値を求めること自体が目的であれば、 誤ったハッシュ値が出力されればすぐ気付くのでいいのだが、 値そのものが目的であることは (当然ながら) あまりなくて、 普通はアプリケーションの中で MD5 を利用するので、 32bit 環境で使っていたアプリケーションを 64bit 環境でコンパイルし直して使おうとするとハマる。

More...
Filed under: プログラミングと開発環境 — hiroaki_sengoku @ 09:34
2010年2月25日

本ブログのサーバを海外レンタルサーバ Linode を使って冗長化・地域分散してみた hatena_b

前回前々回に書いたように、 このブログ 「仙石浩明の日記」 (および 「仙石浩明CTO の日記」) は、 私の自宅にある PC サーバで動かしている。 2台の PC からなる冗長構成になっていて、 10年以上の安定稼働実績がある (両サーバ共に停止したことは皆無) が、 回線が (家庭用の) フレッツ光ネクストなので、 インターネットとの接続が切れてしまう可能性は皆無ではない。 実際、 Bフレッツからフレッツ光ネクストへ切り替えたときは 40分間ほど切れてしまった。 一応バックアップ回線として ADSL 回線も契約しているが、 こちらは固定 IP アドレスを割当てていないので WWW サービス用としては使いにくい。

短時間とはいえブログが見えないようなことがあると、 たまたまそのタイミングで (検索エンジン等で見つけて) 訪れた人が、 ブログが既に閉鎖してしまったものと勘違いしてしまうかもしれない。 ここは一つ自宅以外の場所にもサーバを立てて、 回線断の影響を受けないようにしたいところ。 海外のサーバなら地域分散もできてなおよい。

道楽で運営している自宅サーバにそこまで可用性を求めるのは、 やりすぎの感もあるが、 近頃流行りの VPS (Virtual Private Server, 仮想専有サーバ) は、 月額 $20 (初期費用無し) 程度で利用できるらしい。 $20 なら試しに使ってみるのも悪くない。

サービス
プラン名
メモリ
ディスク
帯域
追加額/単位
月額
年額
データセンタの
場所
ServerAxis Xen
VS000.5G-0025.0GP
512MB
25GB
0GB
$.05/GB
$15
$180
Chicago, IL
Linode
Xen 360
360MB
16GB
200GB
$10/100GB
$19.95
$215.46
Fremont, CA
Dallas, TX ...
VPSLink
Xen VPS Link-3
256MB
10GB
300GB
$.50/GB
$19.95
$201.12
Seattle, WA
New York, NY
slicehost
Xen VPS 256 slice
256MB
10GB
150GB
$.30/GB
$20
$216
Dallas, TX
St. Louis, MO

VPSLink 以外は最安のプランで比較した。 VPSLink には、 メモリ 64MB で月額 $7.95 の Link-1 プラン、 メモリ 128MB で月額 $13.95 の Link-2 プランもあるが、 256MB 未満のメモリではできることも限られてしまうので比較対象から外した。

月額基本料だけを比較すると、 ServerAxis が格安に見えるが、 これは帯域課金が含まれていないためで、 例えば 100GB (送受信の合計バイト数) 使うと $5 加算されて $20 と他社並になる。

データセンタの場所 (というかネットワーク上での位置) によって遅延時間が変わってくるので、 どこのデータセンタを使っているかも重要。 例えば同じ Linode でもデータセンタによって、 日本からアクセスしたときの RTT (Round Trip Time, 往復にかかる時間, ミリ秒) が倍以上変わってくる。 それぞれ 10回ずつ ping を打って、 RTT の最小/平均/最大を比較してみる:

データセンタの場所ホスト名 最小平均最大
Fremont, Californiafremont1.linode.com 121.341132.299146.939
Dallas, Texasdallas1.linode.com 171.049173.152174.905
Atlanta, Georgiaatlanta1.linode.com 183.184185.938190.174
Newark, New Jerseynewark1.linode.com 200.629203.053204.755
London, Englandlondon1.linode.com 269.324273.499276.822

米国西海岸だと RTT は 130msec 程度で済むが、 東海岸は 200msec を超えてしまい、 英国はもっと遠い。 西海岸にデータセンタがあるのは Linode と VPSLink だが、 Linode がデータセンタの情報を詳細に公開しているのに対し、 VPSLink は、 Spry Hosting のシアトルのデータセンタを使用している、 ということ以上の情報を公開していない (しかもこのページは 2006年8月の内容のまま) のが少し気になる。

サポートしている Linux ディストリビューションは、 各社だいたい共通で、 CentOS, Debian, Gentoo, Ubuntu の各バージョンが利用できるが、 VPSLink Ubuntu Plan のページに Ubuntu 9.10 Karmic が書かれていない点も、 ちょっと気になった (ちゃんとポリシーを持って 9.10 をサポートしないのならいいのだが、 どうもそうではなく単に運用の手を抜いているだけのような気配がする)。 Web 界隈での評判も Linode のほうがよさげだったので、 Linode を使ってみることに決めた。

サポートしているディストリビューションのバージョンが古くてもアップグレードできるのだろうが、 帯域で課金されるので最初から新しいバージョンをインストールできる方が好ましい。

サービス CentOSDebianGentooUbuntu Fedoraその他
ServerAxis 5.45.02008.09.10- Mandriva SUSE
Linode 5.35.02008.09.1011 Arch SUSE Slack
VPSLink 55O9.0411 Arch Slack
slicehost 5.45.02008.09.1012 Arch RedHat

おそらく各社ともカーネルも入れ替えることができるのだと思うが、 Linode 以外は使っていないので未確認。 Linode の場合は pv_ops (paravirtualization) を有効にしておけば任意のカーネルを利用できる。 したがって (帯域課金さえ気にしなければ ;-) 任意のディストリビューションの利用 (あるいは完全なカスタマイズ) が可能 (私はまだそこまではやっていない)。

なお、VPS サービスは探すといろいろあるようだ。 前述した 4社と比べると公開している情報が不十分 (特に Virtuozzo/OpenVZ な VPS は実際のパフォーマンスを予想しにくく、 実地に使ってみないとなんとも...) なので私は比較検討対象から外したが、 ダメ元で使ってみるのも面白いかもしれない:

サービス
プラン名
メモリ
ディスク
帯域
追加額/単位
月額
年額
データセンタの
場所
SplitServ
Xen 1024
1024MB
15GB
200GBs
$8/400GB
$14.95
$149.50
Los Angeles, CA
Kansas City, MO
WebKeepers
Virtuozzo ライト
512MB
50GB
?1280円
11760円
?
PhotonVPS
Xen VPS WARP 1
512MB
35GB
500GB
?
$16.95
$203.40
Los Angeles, CA
KnownHost
Virtuozzo VS2
512MB
30GB
750GB
$40/100GB
$35
$400
Los Angeles, CA
Dallas, TX
BurstNet
VPS PACKAGE #1
512MB
20GB
1000GB
$25/200GB
$5.95
$71.40
Scranton, PA
VPS NOC
OpenVZ Bronze
512 MB
20 GB
400 GB
?
$12.95
$155.40
Kansas City, MO
CoreNetworks
CoreMR
512MB
12GB
500GB
?
$19.95
$239.40
?
prgmr.com
Xen VPS
512MB
12GB
80GB
?
$12
$115.20
San Jose, CA
HostCadet
VPS Micro
512MB
10GB
400GB
?
$9.99
$119.88
Colorado Springs, CO
NY NOC OpenVZ
Super VPS #1
512MB
10GB
1000GB
?
$10.00
$120
Chicago, IL
North Bergen, NJ
ARP Networks
KVM/QEMU
512MB
10GB
100GB
?
$15
$180
Los Angeles, CA
VirtuallyDedicated
Xen VX384
384MB
24GB
300GB
?
$10.99
$131.88
Chicago, IL
Scranton, PA
GrokThis.net
Xen VPS
320MB
16GB
160GB
?
$20
$200
Philadelphia, PA
DMEHosting
OpenVZ VPS1
256MB
25GB
1000GB
$10/200GB
$5.95
$71.40
Denver, CO
Chicago, IL
Quantact
OpenVZ VS1
256MB
15GB
300GB
$1/GB
$14.99
$179.88
Santa Rosa, CA
RackspaceCloud
Xen CloudServers
256MB
10GB
0GB
$.08-$.22/GB
$10.95
$131.40
Dallas, TX
XENnode
XEN 256
256MB
10GB
200GB
?
$14.99
$143.99
Dallas, TX
Datarealm Xen
PowerVPS
256MB
10GB
1Mbps
Unmetered
$19.95
$215.52
?
HostVirtual Xen
XV0 Server
256MB
10GB
250GB
?
$14.95
$179.40
San Jose, CA
RackUnlimited
Xen RVPS-Starter
256MB
10GB
100GB
?
$8
$96
Asheville, NC
QuickWeb
Xen Lite
256MB
5GB
240GB
?
$17.95
$215.40
San Jose, CA
QuickVPS
Xen プラン1
256MB
10GB
50GB
?
2300円
21600円
日本国内
QuillHost
OpenVZ Standard
256MB
8GB
150GB
?
$9.99
$119.88
Washington, DC
Charlotte, NC

と、いうわけで、 Linode 360 を契約してみた。

More...
Filed under: システム構築・運用 — hiroaki_sengoku @ 08:58
2010年2月10日

CTO日記も livedoorブログから WordPress へ引越しました (URL は変更なし)

「仙石浩明の日記」 に続いて、 「仙石浩明CTO の日記」 も先週末に livedoorブログから自宅サーバへ引っ越した (つまりネームサーバの設定を変更して切替。有料プランの解約はこれから)。 もともと両ブログは相互にリンクを張って密接に連係していたので、 引越を機会に両者を統合した。

統合といっても両ブログは微妙(?)に読者層が異なると思われるし、 何よりページの体裁が大きく変わってしまっては読者の方々を戸惑わせてしまうので、 CTO日記を 「仙石浩明の日記」 の一カテゴリという位置付けにして、 かつページの体裁は WordPress のテーマを切り替えることによって、 どちらのブログもあまり大きな変化がないようにしている。

「仙石浩明CTO の日記」 http://sengoku.blog.klab.org/ をアクセスすると、 次のような PHP スクリプトを走らせた上で、 WordPress を呼び出す (末尾の require 文):

<?php
$new = NULL;
if ($_SERVER['REQUEST_URI'] == "/") {
    $new = "/blog/category/cto/";
} elseif ($_SERVER['REQUEST_URI'] == "/feed/") {
    $new = "/blog/category/cto/feed/";
} elseif (preg_match('@^/\d+/\d+/\d+/@',
                     $_SERVER['REQUEST_URI'], $matches)) {
    $new = $_SERVER['REQUEST_URI'];
...(中略)...
}
if ($new) {
    ...(中略)...
    $ORIG_SERVER_NAME = $_SERVER['SERVER_NAME'];
    $host = "www.gcd.org";
    $_SERVER['SERVER_NAME'] = $host;
    $_SERVER['REQUEST_URI'] = $new;
    $_SERVER['SCRIPT_NAME'] = $new;
    $_SERVER['PHP_SELF'] = $new;
    $abspath = "/usr/local/www/wordpress/";
    $themepath = "${abspath}wp-content/themes/sengoku_cto/";
    define('WP_USE_THEMES', true);
    define('TEMPLATEPATH', $themepath);
    define('STYLESHEETPATH', $themepath);
    require("${abspath}wp-blog-header.php");
...(中略)...
}
?>

つまり http://sengoku.blog.klab.org/ へのアクセスは、 パス名に 「/category/cto/」 を追加することによって、 CTO日記カテゴリへのアクセスに変換する。

ページの体裁については、 「wp-content/themes/sengoku_cto/」 ディレクトリが、 CTO日記のテーマフォルダで、 二つの PHP 定数 TEMPLATEPATH と STYLESHEETPATH をこのディレクトリへ設定することによって、 テーマの切り替えを行なっている。

テーマフォルダの中にあるテーマ関数ファイル 「functions.php」 は、 WordPress の初期化中に読み込まれるので、 ここに PHP スクリプトを書いておくことによって WordPress の挙動を変更することができる。 例えばブログのタイトルを 「仙石浩明CTO の日記」 に変更するには、 以下のスクリプトを functions.php に追加しておけばよい:

function option_blogname_cto() {
    return '仙石浩明CTO の日記';
}
add_filter('pre_option_blogname', 'option_blogname_cto');

つまり、 pre_option_blogname フックに、 option_blogname_cto フィルタを登録する。

WordPress では、 ブログのタイトルなど各種オプションの設定値 (DB に格納している) を、 get_option($setting) 関数を呼び出すことで参照している。 例えばタイトルは get_option('blogname') を呼び出すことで得られ、 URL は get_option('home') で得られる。

get_option($setting) 関数は wp-includes/functions.php で定義されていて、 以下のようにフィルタフック pre_option_* が定義されている:

function get_option( $setting, $default = false ) {
    global $wpdb;

    // Allow plugins to short-circuit options.
    $pre = apply_filters('pre_option_' . $setting, false);
    if ( false !== $pre )
        return $pre;
    ...(中略)...
}

つまり、 「pre_option_設定名」 というフックに登録されたフィルタが値を返すなら、 get_option はオプションの設定値ではなくフィルタが返した値を返すようになる。 前述の例なら、 「pre_option_blogname」 フックに登録された 「option_blogname_cto」 フィルタが 「仙石浩明CTO の日記」 という値を返すので、 get_option('blogname') も 「仙石浩明CTO の日記」 という値を返すようになり、 結果としてブログのタイトルを変更できる、というわけ。

ただし、 前述したように CTO日記は 「仙石浩明の日記」 の一カテゴリという位置付けなので、 ブログのタイトルを変更しただけだと、 ブログ 「仙石浩明CTO の日記」 の 「仙石浩明CTO の日記」 カテゴリということで、 ページのタイトル等が 「仙石浩明CTO の日記 » 仙石浩明CTO の日記」 という冗長なものになってしまう。 そこで、 以下のようなスクリプトを 「functions.php」 に追加して、 タイトルとカテゴリ名が同じときはカテゴリ名が表示されないようにする:

function single_cat_title_cto($category_name) {
    $name = get_option('blogname');
    if ($category_name == $name) return "";
    return $category_name;
}
add_filter('single_cat_title', 'single_cat_title_cto');

single_cat_title フックは、 wp-includes/general-template.php で定義されていて、 ページのタイトルなどに表示されるカテゴリ名を変更することができる。

以上で、 「仙石浩明の日記」 の一カテゴリを 「仙石浩明CTO の日記」 の体裁で見せることができるようになる。 しかし、 元が 「仙石浩明の日記」 であるだけに、 リンク先が全て 「仙石浩明の日記」 のページになってしまう。 例えば、 「仙石浩明CTO の日記」 のトップページの一番下に、 「古い投稿 »」 というリンクがあるが、 このリンク先が https://www.gcd.org/blog/page/2/ になってしまい、 たどると 「仙石浩明の日記」 のトップページの 2ページ目へ遷移してしまう。

また、 本文中 (あるいはサイドバー) に現れるリンクも、 DB のデータは 「仙石浩明の日記」 のパーマリンクを用いているので、 たとえそれが 「仙石浩明CTO の日記」 カテゴリに含まれていても、 そのリンクをたどると 「仙石浩明の日記」 の記事として表示されてしまう。

そこで、 遷移先も 「仙石浩明CTO の日記」 として表示したいリンクを、 フィルタで書き換えることにした。 つまり DB のデータは 「仙石浩明の日記」 へのリンクのままで、 ブラウザに送信する前に都度書き換える。

対象となるリンクは、 記事本文中だけでなく、 前述したページナビ 「古い投稿」 「新しい投稿」 や、 サイドバー (「人気記事」 や 「最近の投稿」) にも現れる。 ページ丸ごと (つまり HTTP レスポンス丸ごと) HTML を書き換えられるフックがあるとよかったのだが、 残念ながらそういうフックは定義されていないようだ。 以下のフックそれぞれについてリンクを書き換えればよさげ:

フィルタフック フィルタが変更できる対象, 第2引数, ...
the_content 記事本文 HTML
the_category 記事の末尾に表示されるカテゴリーリストの HTML,
$separator, $parents
get_pagenum_link ページ末尾に表示されるページナビ 「古い投稿」 「新しい投稿」 の URL
post_link 記事の URL (パーマリンク), $post, $leavename
widget_text サイドバーに表示されるテキストウィジェットの HTML, $instance
wp_list_categories サイドバーに表示されるカテゴリーのリストの HTML
category_feed_link カテゴリーの RSSフィードの URL, $feed

書き換え対象のリンクを決めるために、 まず CTO日記カテゴリに属す記事の ID を取得する:

function setup_cto_id() {
    global $wpdb;
    global $is_cto_id;
    $result = $wpdb->get_results("SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id=17", ARRAY_N);
    foreach ($result as $row) {
        $is_cto_id[$row[0]] = 1;
    }
}

あるカテゴリに属す記事ID のデータを取得する関数など、 WordPress に含まれているんじゃないかと探してみたのだが、 見つからなかったので DB に問合わせて取得するようにしてみた。 毎回 DB アクセスが発生してしまうが、 キャッシュとかはアクセス数が増えてから考える (^^;)。 「term_taxonomy_id=17」 が CTO日記のカテゴリ (決め打ち ^^;)。 CTO日記カテゴリに属す記事は、 配列 $is_cto_id[記事ID] に 1 を代入しておく。

次に URL を書き換えるスクリプト:

function replace_URL_cto($matches) {
    global $is_cto_id;
    global $ORIG_SERVER_NAME;
    if (!is_array($is_cto_id)) {
        setup_cto_id();
    }
    if (is_null($matches[2])) {
        if ($matches[1] == "category/cto/") return "http://$ORIG_SERVER_NAME/";
        return "http://$ORIG_SERVER_NAME/$matches[1]";
    } elseif ($is_cto_id[$matches[2]]) {
        return "http://$ORIG_SERVER_NAME/$matches[1]";
    }
    return $matches[0];
}

function convert_URLs_cto($text) {
    $textarr = preg_split("/(<.*>)/U", $text, -1, PREG_SPLIT_DELIM_CAPTURE);
    $stop = count($textarr);
    for ($i = 0; $i < $stop; $i++) {
        $content = $textarr[$i];
        if (strlen($content) > 0) {
            $content = preg_replace_callback(
                    '@https://www.gcd.org/blog/(\d+/\d+/(\d+)|category/cto/)@',
                    'replace_URL_cto', $content);
        }
        $output .= $content;
    }
    return $output;
}

顔文字を画像に変換して表示するフィルタ wptexturize (wp-includes/formatting.php で定義されている) を参考にさせてもらった。 preg_replace_callback() を使って書き換え対象リンクを探し、 replace_URL_cto で記事ID がCTO日記カテゴリに属す ($is_cto_id[$matches[2]] が TRUE) 場合のみ書き換える。

最後に、 この書き換えフィルタ replace_URL_cto を前述したフィルタフックに追加:

add_filter('the_content', 'convert_URLs_cto');
add_filter('the_category', 'convert_URLs_cto');
add_filter('get_pagenum_link', 'convert_URLs_cto');
add_filter('post_link', 'convert_URLs_cto');
add_filter('widget_text', 'convert_URLs_cto');
add_filter('wp_list_categories', 'convert_URLs_cto', 12000);
add_filter('category_feed_link', 'convert_URLs_cto');

wp_list_categories にフィルタを追加すると Category Order プラグインと衝突するので、 優先順位を下げて Category Order プラグインの後で実行されるようにしている。

また、 the_category, post_link, widget_text, category_feed_link 各フックは、 2つ以上の引数を持つが、 第1引数 (書き換え対象の HTML あるいは URL) のみ使用するので引数の数 (add_filter の第3引数) を省略している。

Filed under: システム構築・運用,プログラミングと開発環境 — hiroaki_sengoku @ 07:46
2010年1月28日

本ブログを livedoorブログから WordPress へ引越しました (URL は変更なし) hatena_b

このブログ 「仙石浩明の日記」 は、 今まで livedoorブログの有料プラン (月額 315円) を利用していた。 比較的自由にデザインをカスタマイズできること、 URL のドメインを自由に設定できることから、 2006年3月9日にこのブログを開設して以来、 今まで 4年近く使い続けてきた。 しかし自前サーバでない不便さ、隔靴掻痒感はいかんともしがたく、 乗り換えを検討したことは何度もあって、 そのたびに不便さと乗り換えの面倒くささを天秤にかけて踏み切れずにいた。

例えば、 HTML文法エラーを修正できない問題点を見つけたときや、 ブログのサイドバーにある 「livedoor Reader」 「RSS」 「livedoor Blog」などのバナーを非表示にしていたら、 ライブドアから警告メールが来て、 やむなくバナー表示を復活させたときなど。 なかでも、 昨年ブログ管理画面 (有料プラン) がリニューアルされたときは、 とても大きなフラストレーションを感じた。 ライブドアはよかれと思ってリニューアルしているのだろうが、 JavaScript を多用した新管理画面は、 私にとっては使いにくいことこのうえないし、 生ログ取得スクリプトも使えなくなった。

そして、 今年に入って 「ブログ共通ヘッダー」 (最上端に表示される livedoor Blogのロゴ, 所属カテゴリ, テキスト広告) が勝手に表示されるようになったのが最後の背中のひと押しとなった。 これを非表示にしたければ PRO プラン (月額 315円) ではなく ADVANCE プラン (月額 840円) に変更しろという趣旨 (要は値上げ) なのだと思うが、 何の連絡もなく画面の一番目立つ最上端に、 醜悪なヘッダー (ADVANCE プランへの移行を促すためにわざと醜悪にしている? *_*) を勝手に挿入するデリカシーの無さに驚き呆れ、 自前サーバへの引越を決めた。

common header

ブラウザ画面最上端 ↑ の 「ブログ共通ヘッダー」 (所属カテゴリ 「IT > プログラミング 」 と 「受験にまつわるエピソードを教えてください」 という広告? 表示) は、 ライブドアのサーバが HTML 中に自動挿入する以下の JavaScript (settings/header.js) によって body 要素へ追加 (appendChild) されている。

(function () {
    var hd = document.createElement('div');
    var str = '';
    str += '<div id="header2" style="z-index:10001"><table cellspacing="0" class="blog-common-header" id="header">';
        ...(中略)...
    hd.innerHTML = str;
    document.body.appendChild(hd);
        ...(後略)...

ユーザがカスタマイズ可能な範囲の外であるため、 この JavaScript の実行そのものを止めることは無理っぽいが、 追加された子要素を削除する JavaScript を実行して消すことは可能。 例えば以下のようなコードを HTML ファイルのどこかに入れておけばよい。

<script type="text/javascript" src="https://www.gcd.org/sengoku/docs/livedoor.js"></script>

livedoor.js は、 body 要素の子要素 「header2」 を取り除く (removeChild) だけの JavaScript:

(function () {
    var element = document.getElementById("header2");
    element.removeChild(element.childNodes.item(0));
})();

正月早々 「ブログ共通ヘッダー」 が勝手に表示されるようになったことに気付き、 直ちにこの対策を行なって非表示にしたのだが、 以前バナーを非表示にしたときライブドアから警告メールが来たことを考えれば、 今回も警告メールが来るのは時間の問題だろうと、 引越を急いだ次第。

私はブログを書くときも HTML で書いていて、 あまり CMS 的な機能は必要としないので、 トラックバックとコメントを受付けるだけの簡単な Web アプリを書こうと思っていたのだが、 試しにインストールしてみた WordPress が思いの外シンプルな作りで、 ちょっといじっているうちに簡単にカスタマイズできてしまったので、 これを使うことにした。

livedoorブログでエクスポートしたデータを (Movable Type / TypePad のデータとして) WordPress でインポートしたら、 (pre 要素なのに) 行頭の空白文字が削除されてしまって往生したが、 大した量でもなかったので手作業で修正してしまった。 もう少し量が多かったら真面目に PHP コードを追ったのだが...

こんなに簡単にできるなら、 もっと早く WordPress へ移行すればよかった。 既存のテーマを見よう見まねでいじっただけなのだが、 以前のデザインをほとんどそのまま踏襲することができた (むしろ余計な div 要素を排除できたので、よりシンプルになった)。

livedoorブログと WordPress では URL (パーマリンク, permalink) の形式が異なる。 例えば、 あるエントリの URL は、 livedoorブログ (旧URL) と WordPress (新URL) で次のようになる:

旧: livedoorブログ新: WordPress
ベースURL http://blog.gcd.org https://www.gcd.org/blog
エントリ /archives/51168556.html /2008/04/154/
月別表示 /archives/2008-04.html /2008/04/
カテゴリ /archives/cat_50026701.html /category/enlighten/
RSS /index.rdf /feed/rdf/

一見して、 WordPress のパーマリンクの方が分かりやすい。 正確に言えば、 WordPress のパーマリンクの形式は任意に設定できて、 livedoorブログ (Movable Type ベース) の形式に合わせることも可能だが、 エントリID (上記の例だと 51168556 と 154) が異なるので形式を合わせること自体にはあまり意味はない。

livedoorブログを利用していた時の URL がそのまま使えるように、 旧URL を新URL へ変換する以下の PHP スクリプトを書いた (switch 文で URL ごとにずらずら case を並べただけ)。

<?php
$new = NULL;
if ($_SERVER['REQUEST_URI'] == "/") {
    $new = "/blog/";
} elseif ($_SERVER['REQUEST_URI'] == "/atom.xml") {
    $new = "/blog/feed/atom/";
} elseif ($_SERVER['REQUEST_URI'] == "/index.rdf") {
    $new = "/blog/feed/rdf/";
} elseif (preg_match('/^\/archives\/(20\d\d)-(\d\d)\.html$/',
                     $_SERVER['REQUEST_URI'], $matches)) {
    $year = $matches[1];
    $mon = $matches[2];
    $new = "/blog/$year/$mon/";
} elseif (preg_match('/^\/archives\/cat_(\d+)\.html$/',
                     $_SERVER['REQUEST_URI'], $matches)) {
    $id = $matches[1];
    $new = "/blog/category/";
    switch ($id) {
    case 50026701: $new .= "enlighten/";   break;
    case 50026704: $new .= "business/";    break;
    case 50026703: $new .= "engineer/";    break;
    case 50026699: $new .= "system/";      break;
    case 50035671: $new .= "hardware/";    break;
    case 50026700: $new .= "programming/"; break;
    case 50021362: $new .= "stone/";       break;
    case 50035209: $new .= "la-fonera/";   break;
    case 50041534: $new .= "hawaii/";      break;
    case 50045637: $new .= "hongkong/";    break;
    case 50026702: $new .= "others/";      break;
    default: $new = NULL;
    }
} elseif (preg_match('/^\/archives\/(\d+)\.html$/',
                     $_SERVER['REQUEST_URI'], $matches)) {
    $id = $matches[1];
    $new = "/blog/";
    switch ($id) {
    case 50071073: $new .= "2006/03/8/"; break;
        ...(中略)...
    case 51168556: $new .= "2008/04/154/"; break;
        ...(中略)...
    case 51552583: $new .= "2009/12/184/"; break;
    case 51555097: $new .= "2010/01/185/"; break;
    default: $new = NULL;
    }
}
if ($new) {
    $host = "www.gcd.org";
    $_SERVER['SERVER_NAME'] = $host;
    $_SERVER['REQUEST_URI'] = $new;
    $_SERVER['SCRIPT_NAME'] = $new;
    $_SERVER['PHP_SELF'] = $new;
    define('WP_USE_THEMES', true);
    require('/usr/local/www/wordpress/wp-blog-header.php');
} else {
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: https://www.gcd.org/blog/");
    exit();
}
?>

http://blog.gcd.org/* にアクセスすると、 ↑ この PHP スクリプトが実行される。

これに加え、 逆方向の変換、 つまり新URL から旧URL への変換も必要。 例えば 「はてなブックマーク」 へ頂いたコメント (例えば前述したエントリに対するコメント一覧) は旧URL に紐づいているので、 各エントリに旧URL を登録しておく必要がある。 WordPress には カスタムフィールド という機能があって、ひとつのエントリに複数の 「キー」 と、 各キーにその値を登録することができる。 そこで沢山の 「ブックマーク」 を頂いたエントリには、 「hatena_b」 というキーで旧URL を登録しておくことにした。 すると、以下のような PHP スクリプトでブックマーク数 を表示できる。

<?php
  $hatena_b = get_post_meta($post->ID, "hatena_b", true);
  if ($hatena_b)
    echo ' <a href="http://b.hatena.ne.jp/entry/' . $hatena_b
       . '"><img style="border:0;" src="http://b.hatena.ne.jp/entry/image/'
       . $hatena_b . '" alt="" /></a>';
?>

最後に、 ネームサーバの設定変更を行なって、 blog.gcd.org レコード (TTL = 3時間) の値を 「CNAME blog-01.livedoor.jp」 から 「CNAME www.gcd.org」 へ変更した。 1/26 19:35 に変更を行なったところ、 19:46 には最初のアクセスが www.gcd.org へ届き、 20時台には大半のアクセスが www.gcd.org へ届くようになった。 20時台にライブドア側へ届いた blog.gcd.org へのアクセスはわずかに 7件、 その後は 1 時間〜数時間ごとに、ぱらぱらアクセスがあるという状況が続いている。 旧レコードを保持しているキャッシュネームサーバが残っていて、 そのネームサーバを使ってるブラウザからのアクセスのみが、 ライブドア側へ届いているといった感じ。

More...
Filed under: システム構築・運用 — hiroaki_sengoku @ 08:26
2010年1月4日

香港で買ったプリペイド SIM カードを日本で使ってみる

あけましておめでとうございます。今年もよろしくお願いします。

香港 CSLPower Prepaid SIM $88 を買った (HK$88 = 約1060円)。 この SIM カードを妻の携帯電話 Motorola ZN200 に入れて、 一週間の香港滞在中、 互いに連絡するときに大いに利用した。 が、通話料が一分間 HK$0.1 (約 1円) と安すぎるので、 HK$82.20 も残ってしまった (つまり HK$5.80 しか使ってない)。

Power Prepaid SIM $88

有効期限は 2010年6月15日までの半年間。 期限内にチャージすればチャージした時点からさらに半年間有効。 SIM カードのパッケージの内側には、 海外 (香港でも 「於海外」 「Overseas」 って言うのか...) でのチャージ方法として A. 自動チャージ (香港での手続きが必要) B. バウチャー (香港で事前に購入が必要) C. PPS の三種類があると書いてある。

Power Prepaid SIM $88 inside

PPS (Payment by Phone Service ?) というと、 電話をかけて支払う方法だとばかり思っていたが、 インターネット経由でも可能であるようだ (「by Phone Service」 と言いながらインターネットでも可能とはこれ如何?)。 Top up Your Account ページで、 チャージ金額 (HK$50 ~ HK$300)、SIMカードの電話番号、クレジットカード番号 を入力することでチャージできそう。 したがって期限切れ直前にチャージすることにより次回 (たぶん年末に) 香港に行くときに使うこともできそうだが、 一年間使わずに寝かせておくよりはと思い、 Yahoo!オークションに出品してみた

この SIM カードは日本でも、 3G 対応の携帯電話なら使用できる (Motorola ZN200 は GSM 専用機なので日本では使えない) ので、 HTC P3600 に入れて試しに少し使ってみた (正確に言うと、 課金される実験は HK$1000 Prepaid SIM を使用したので、 Power Prepaid SIM $88 の残度数は減らしていない。 どちらの SIM も機能的には同じ)。

まず、 着信は普通に可能。 日本から 「010-852-6714-XXXX」 (「010」 は日本において国際電話をかけるときの国際プレフィックス、 「852」 は香港の国番号、 「6714-XXXX」 は、この SIM カードに割り当てられた香港内での電話番号) にダイヤルすれば、 この SIM カードを入れた電話機が日本にあっても着信する (Roaming Service)。 ただし 30秒ごとに HK$25 かかる (国によって HK$8 ~ HK$25。 深圳とかなら HK$8)。

発信は、 中国以外だと直接発信ができないのでコールバックしてもらう方式。 つまり 「*108*」 に続けて相手先の電話番号を香港からかける形で押して、 最後に 「#」 を押した上で発信。 例えば東京都の固定電話 03-5771-1328 にかけるのであれば、 「*108*00181357711328#」 とダイヤル。

すると香港から電話がかかってくる (コールバック) ので、 出ると中国語で何やら言ったあと、 相手先 001 81 3 5771 1328 (001 は香港において国際電話をかけるときの国際プレフィックス、 81 は日本の国番号、 3 は東京の市外局番03) を呼び出してくれる。 相手先が出ればそのまま通話できる。 つまり日本国内宛に電話をかける場合も、 香港から日本への国際電話 2本使って通話することになる。 なお、 「*108*」 の代りに 「*108*1*」 にすると、 コールバックの時の発声を中国語のかわりに英語で言ってくれるらしい (試すとまた課金されてしまうので未確認)。

コールバックに応えた時点で、 相手先につながるか否かにかかわらず課金される。 相手先が出てくれなくても 30秒ごとに HK$25 も課金されてしまうので注意が必要。 試しに私の PHS に前述のダイヤル方法 (*108*00181705013YYYY#) でかけてみた。 すると 「通知不可能」 で PHS が鳴った。 ちょっと鳴らしてみただけなのだが、 通話時間 (コールバックに応えてから切断するまで) としては 19秒もかかり、 HK$6.5 もかかった (香港滞在一週間で使った度数より大きい! *_*)。 数秒鳴らすだけで、 香港内同士 (local call HK$0.1/min) なら 1時間分以上の通話に匹敵する課金なのだから恐れ入る。

というわけで通話の Roaming Service は高すぎて実用的ではない (国際ローミングなんてどこもそんなもの?) が、 日本にいながら香港の番号での着発信の確認をできる意味はあるかも (香港に行く前から電話番号を周囲に伝えておく場合など)。

一方 SMS (Short Message Service) は、 一通 HK$3 なので香港内同士 (一通 HK$0.8) に比べてさほど割高ではない (そもそも local で一通 10円というのが高いと思うけど)。 しかも、 受信側は香港内外問わず無料でメッセージを受け取ることができる。 日本ではあまり一般的ではない SMS だが、 日本以外だととても普及している。 SMS は通信キャリア・国を越えて利用できる共通基盤になっているのに、 日本の通信キャリアはいまだに事業者間接続でモメているようだ。 よく知られているように、 twitter の文字数制限が 140文字なのは、 SMS の制限が 140オクテットであることを踏襲している。

日本を除くほぼ全世界で共通のテキスト・メッセージサービスとして定着した。 現在の全世界のSMSの利用者は約24億人で、 世界中の携帯電話ユーザーの約74%がSMSを利用している。

まず SMS の着信を試してみる。 Skype で SMS を 「+852-6714-XXXX」 に送ってみる (€0.051 = 約8円かかった) と、 携帯電話が日本にあっても着信する。 日本語表示が可能な携帯電話 (HTC P3600) なので、 日本語を含むメッセージも問題なく表示できた。 念のため残度数が減ってないことを確認。

「*109#」 にダイヤルする (もちろん無料) と、 次のような残度数を知らせるメッセージが、 差出人 「179179」 から SMS で届くので残度数を確認できる。

6714XXXX with $82.20 stored-value. The expiry date is 15/Jun/2010.

次に SMS の発信を試してみる。 別の SIM カード (HK$1000 Prepaid SIM) を HTC P3600 に入れて、 HTC P3600 の標準アプリケーション 「メール」 を使って SMS を 「+8526714XXXX」 宛に送ってみた。 宛先欄に 「+」 記号を含めて入力することが重要。 残度数を調べると、 送信に HK$3 かかったことが確認できた。 続いて SIM カードを元の Power Prepaid SIM $88 (電話番号が 6714XXXX) に戻すと、 先ほど別 SIM カードで送った SMS が着信した (SIM カード入れ替えを行なったのは、 手元に 3G 対応携帯電話が一台しかないため)。

Filed under: SIM,香港 — hiroaki_sengoku @ 07:07
2009年12月29日

香港で HSDPA つなぎ放題に挑戦 ~ 5日間で HK$178 (約2000円)

昨年、香港を訪れたときは、 ホテルに無線LAN があるから安心と油断していて、 事前に携帯電話でのデータ通信に関して下調べを怠っていた。 今年も同じホテル (油麻地という立地のよさと安さで選んだ) で、 ホテルの無線LAN は値段が高いことが分かっていたので、 今回こそは携帯電話で、 それも EDGE (GPRS) ではなく HSDPA でインターネットへつなぐぞっと、 渡港前に調べておいた。

Mobile Data Stored Value SIM Card

まず、 昨年利用した中国移動通信Mobile Data Stored Value SIM Card は、 「*106*01#」 へダイヤルすると月額 HK$98 (約1100円) でつなぎ放題。 とても安いが、 EDGE (Enhanced Data Rates for GSM Evolution) なので最大でも 473.6kbps しか出ない (もっと遅いはず)。

イマドキ EDGE の帯域ではつらい。 せっかく 3G な携帯電話 HTC P3600 を持っているのだから、 やはり HSDPA (High Speed Downlink Packet Access) を使いたい。 というわけで Hutchison 3CSL のデータ通信について調べた。

Hutchison 3 の HSDPA Broadband Access Rechargeable SIM Card だと、 設定無しでそのままデータ通信できて 1MB あたり HK$2 で、 一日 (0:00~23:59) の上限が HK$28、 一ヶ月 (開始日~翌月の同じ日の前日) の上限が HK$298。 データ通信のためのアクティベートが不要というのは魅力的。

Power Prepaid SIM Card

一方、 CSL の Power Prepaid SIM Card だと、 1-Day Pass が HK$50、 5-Day Pass が HK$178、 30-Days Pass が $788。 それぞれ最終日 (1-Day Pass なら開始当日、 5-Day Pass なら開始日を 1日目と数えて 5日目) の 24:00 まで有効 (と説明書には書いてあるが、実際には 27:30 ごろまで使えた)。

値段だけ見ると Hutchison 3 の方に軍配が上がるが、 香港在住の知人の話によると、 Hutchison 3 は安いが、 安定性は CSL が上とのこと。 うむむ... 悩ましい。

More...
Filed under: SIM,香港 — hiroaki_sengoku @ 09:36
2009年12月25日

香港の灣仔電腦城で 2万2千円の NetBook、 olevia P10-122HK を買ってみた

香港の灣仔電腦城 (Wan Chai Computer City, MTR 灣仔駅 A4出口すぐ) の 3階 (香港の呼び方だと 2樓) にあるパソコンショップ Cyber-Pro Computer Limited (210-211號鋪) で、 olevia P10-122HK を HK$1899 (約 22,000円) で売っていた。 これは Linux ubuntu 版の値段で、 Windows XP 版は HK$2199 (約 25,500円)。 香港版の Windows XP なんて広東語を喋れない私には無用なので、 むしろ Windows ライセンス無しの方がありがたい。

olevia P10-122HK

写真↑ の 「$」表記は、 もちろん香港ドル (1 香港ドル = 0.129 米ドルくらい)。

ちょうど一年前に香港で買った NetBook も olevia だったので、 二年続けて olevia を買うのは能がないな~ と思ったのだが、 旺角や灣仔や深水埗の電脳街を巡回した限りでは、 HK$2000 を下回る NetBook は数機種しかなく、 その中で一番安かった olevia P10-122HK を買った。 クレジットカード払いだと 3% 増し (+HK$57) になると言われたので、 灣仔電腦城の入口の真正面にある ATM (電脳街に ATM は必需品?) までお金をおろしに行った。

昨年買った olevia X10A-1160 は SOTEC C101W4 と同型機だったが、 今回の olevia P10-122HK も別ブランドで日本でも売られていたりするのだろうか? スペック的には X10A も P10 もほとんど同じで、 電源アダプタの規格 (19V 3.42A, プラグ形状) も同じ。

ChipsetIntel Atom N270 1.6GHz
Memory1GB DDR2
BatteryLithium-Ion 11.1V 2.2Ah
LCD10.1” 1024x600 SVWGA
HDD160 GB (SATA)
I/OD-sub*1 , USB 2.0*3 , Mic-in
Headphone, LAN
Webcam1.3M Webcam
SoundStereo speakers

違いというと、軽く、小さくなったことくらいだが、 値段が 1万円以上安くなって 2万2千円になったのが大きい。 もはや (SIM ロックフリーの) 3G ケータイより安い。 このペースで行くと来年は 1万円強くらいで買えたりするのかも? NetBook が 100ドル PC になってしまうのか。

X10A-1160P10-122HK
PriceHK$2880HK$1899
Weight1.3 kg0.99 kg
Dimension26.5*18.5*2.5cm25*17.5*3cm
WiFi802.11b/g802.11b/g/n

ちなみに、 山寨.com によると、 P10 は olevia (TV や DVD 機器などで有名) が提供する最初の netbook だそうだ。 だとすると、昨年私が買った X10A-1160 は何だったのだろう?

This is the first netbook offering from Olevia, the Olevia P10. A 10.1 inch device that Olevia hopes will herald their march into the markets of the West. This is interesting because Olevia already has a presence in the US and is one of the first major Chinese consumer electronics players to attempt to leverage their brand to sell netbook PCs in the US. Is this the first of a deluge of Chinese brands that will soon flood the US market?
山寨.com から引用

2万円以下の NetBook が普通になると、 NetBook の使われ方が大きく変わりそうな気がする。

More...
Filed under: 香港 — hiroaki_sengoku @ 11:52
2009年12月5日

大相撲初場所の自由席通し券を買ってみた

私は大相撲年六場所のうち、 両国国技館で開催される初場所、夏場所、秋場所は、 たいてい溜り席 (砂かぶり) のチケットを購入している (維持員席ではなく窓口販売分)。 ところが今回は整理券の番号が 300番近くになってしまい (自宅が両国から遠いため、自宅の最寄り駅の始発で行くとこのあたりが限界)、 今日 (販売初日) 国技館の販売窓口で尋ねたら正面・向正面のタマリ席は (全日程で) 11:50 時点で既に完売だった。 東・西のタマリ席6列目は残っていたが、 これは記者席の後ろの席なので私は嫌い (人の往来が激しく相撲に集中できないので)。

かといって枡席は窓口だと 4人マスか、 2人だと特別マスC席 (4人マスを 2人で使う) しか買えない (普通の 2人マスは チケットぴあ 販売のみ)。 4人マスを 2人で使うとゆったりできるのはいいのだが、 マスA席だと 1人あたり 22600円にもなる (4人で使えば 1人あたり 11300円) のでコストパフォーマンスがよくない。 一方、 特別マスC席は 1人あたり 9200円と安いが、 一階席の一番後ろなので 2階のイスA席 (8200円) と大差なく、 私はいいとは思わない。

ならばいっそ椅子席に、と椅子席の販売窓口へ移動。 イスC席を 2人 * 二日分買おうと思って移動したのだが、 ダメ元で 「通し券」 がまだあるか聞いてみた。 通し券というのは十五日間の自由席券の束で 20000円。 毎場所 50セットしか販売されないので、 当然完売だろうと思っていたのだが、 驚いたことに毎場所とも販売初日の昼過ぎまで売れ残っているとのこと。 意外に人気が無いようだ。 ということは整理券の番号が 300番を超えていても買える可能性があるのかも。 さらに整理券一枚で 4セットまで購入できるらしい (1セットしか買えないと私は今まで思い込んでいた)。

自由席券 (2100円) は通し券以外だと当日しか買えない (土日とかだと早朝から並んでも買えないことが多い) ので、 土日祝日しか行かない (行けない ;_;) 場合でも意味がある。 つまり前売りで買えるイスC席を6日分買うと 3600円 * 6 = 21600円になるので通し券の方が安い。 しかも、 整理券一枚だと 2日分 (2人分買う場合) しか買えない (もちろん販売初日以外なら何日分でも買える) のに対し、 通し券なら 15日分を 4セットまで買える。

というわけで、 平日 (1/12~15, 1/18~22) の自由席入場券が余っております (各日程 2人まで)。 ご興味のある方はご連絡下さい (^^;)。

sumo admission ticket
Filed under: その他 — hiroaki_sengoku @ 23:24
2009年12月4日

apache httpd が 「(22)Invalid argument: alloc_listener: failed to get a socket for (null)」 エラーを出して立ち上がらない理由

私は普段持ち歩いているノートPC (レッツノート CF-R7) で coLinux を常用している。 Windows マシンで Linux を使いたい場合、 QEMU や VMware などの PC エミュレータ (完全仮想化) を用いる方法もあるが、 coLinux などの準仮想化の方がパフォーマンス的に有利なので、 日常的に使用する (私の場合、Windows マシンを使っていながらほとんどの作業は Linux の中で完結させている) なら coLinux の方が便利だと思う。

もちろん、 準仮想化であるから標準的なカーネルをそのまま走らせることはできず、 パッチをあてる必要がある。 残念ながら最新カーネル用のパッチはまだ作られていないようで、 現時点では Linux kernel 2.6.26.8 用のパッチが最新。

私は自分で管理している Linux マシン (自宅と職場合わせて 10台以上ある) は、 この coLinux なマシンも含めてハードディスク (正確に言えば Linux のパーティション) の内容を同一にしている。 すなわち、 マスタマシン (senri.gcd.org) の内容を定期/不定期的に rsync を使って各マシンへ同期させている。 マスタマシンのカーネルは Linux 2.6.31.6 なので、 マスタでビルドしたソフトウェアの中には、 Linux 2.6.26.8 ベースである coLinux 環境で動かないものも当然でてくる。

先日 apache httpd 2.2.14 を (マスタマシンで) ビルドしたら、 coLinux 環境で動かなかった:

# uname -a
Linux ikeda.gcd.org 2.6.26.8-co-0.8.0 #1 PREEMPT Sat Nov 14 19:23:55 JST 2009 i686 GNU/Linux
# /usr/apache2/bin/httpd -t
[Sun Nov 29 17:13:41 2009] [crit] (22)Invalid argument: alloc_listener: failed to get a socket for (null)
Syntax error on line 32 of /usr/apache2/conf/httpd.conf:
Listen setup failed

「Syntax error on line 32」 ということだが httpd.conf の 32行目は、

Listen 80

となっているので、 少なくとも 「Syntax error」 ではないことは明らか。 「Listen 80」 の代りに 「Listen localhost:80」 などと書けば、 「failed to get a socket for (null)」 というエラーメッセージが 「failed to get a socket for localhost」 に変わる。

このエラーメッセージを手がかりに apache httpd 2.2.14 のソースを探すと、 エラーを出しているのは server/listen.c の以下の部分:

More...
Filed under: プログラミングと開発環境 — hiroaki_sengoku @ 07:24
2009年11月12日

自宅回線を 100Mbps から 200Mbps へ、帯域を倍にしてみた ~ NGN が自宅にやってきた hatena_b

私の自宅がある神奈川でも、 先月 13日から 「フレッツ 光ネクスト ファミリー・ハイスピードタイプ」 の申込受付が始まったので、 早速申し込んでみた。 今まで使っていたのは 「Bフレッツ ニューファミリータイプ」 だから、 下りの帯域が 100Mbps から倍の 200Mbps に増える。 月額利用料は変わらない。 工事費が 5827円かかるが、 キャンペーン期間中につき月額料金が 3ヶ月間無料になるので悪くない。

10/16日に NTT東日本 0120-116116 に電話して申し込んだところ、 回線切替工事まで最短で 10営業日かかり、 工事の予約状況によると最速で 11/1(日) の工事になるらしい。 続いて NTT コミュニケーションズ 0120-506-506 に電話して、 200Mbps に変更したときプロバイダ (OCN) 側の変更が必要か確認。 個人向けサービス (OCN 光 with フレッツ) は元々 200Mbps に対応しているから契約変更は必要無しとのことだったが、 あいにく私が契約しているのは法人向けサービスであるところの OCN 光アクセス IP8/IP16「Bフレッツ」プラン である。 この場合、 OCN 光アクセス IP8/IP16「フレッツ 光ネクスト」プラン への契約変更が必要となる。

NTT コミュニケーションズの担当者の話によると、 認証サーバの設定を変更するらしい。 PPPoE のユーザ名とパスワードはそのまま同じものを使っていい (新しいユーザ名も付与されるので新旧どちらのユーザ名も使える) が、 認証サーバ側の設定を変更すると旧回線 (つまり Bフレッツ) からの認証は拒否されるらしい。 すなわち認証サーバの設定変更後は、 新回線 (つまり フレッツ 光ネクスト) からでないと認証が通らない。 したがって、 回線が切り替わる前に PPPoE セッションが切れると、 旧回線のままでは再接続できなくなってしまう。 さらに、 設定変更は平日の未明 0:00 ~ 5:00 の間にしか実施しないらしい。

ということはつまり、 11/1(日) に回線工事を行なうには、 10/30(金) の未明に認証サーバの設定変更を行なうことになる。 10/30 未明から 11/1 の回線工事まで丸二日間、 もし PPPoE セッションが何らかの原因によって切れてしまうと、 工事完了後まで二度と再接続できなくなる。 最長丸二日間切れたままというのはあまりに不便なので、 11/2(月) の未明に認証サーバの設定変更を行ない、 同日午前 9:00-12:00 に回線切替工事を行なうことにした。 これなら PPPoE セッションが切れても数時間の切断で済む。

More...
Filed under: IPv6,システム構築・運用 — hiroaki_sengoku @ 10:00
2009年10月27日

パネルディスカッション ~CTO のから騒ぎ for the future~ に登壇しました hatena_b

先日開催された楽天テクノロジーカンファレンス2009 で、 パネルディスカッション ~CTOのから騒ぎ for the future~ にパネラーとして登壇しました。 他のパネラーはベンチャーの CTO の方々。 いずれも 「CTO サミット」 (という名の飲み会) で毎度ご一緒している皆さんなので、 飲み会と同様とても盛り上がりました。 モデレータの森さま (楽天技術研究所所長)、 どうもありがとうございました。

このパネルディスカッション (という名のビール飲みながら放談会, ただし私は飲めないのでウーロン茶) の議事録を書いてくださったかたがいらっしゃったので、 適宜引用しつつ感謝の意を表します。(_O_)

まず冒頭の自己紹介の部分から:

KLab 株式会社の仙石です。 就職してから 16~17 年。 卒業してしばらくはベンチャーに縁がない生活(論文書き)。 ある日突然転職することになり、2000 年に転職。 気の向いたことにどんどんのめり込む性格。 技術者が経営をやるのってどういうこと? という質問はまた後ほど。 KLab を設立してから、 どんどん仕事を捨てて自分を変えている (ピーターの法則に陥らないように)。 部下が成長したらすべて任せてしまう。 すべての仕事を部下に振り終えたら、私は CTO をやめる予定。 早く育成しないと。

CTO と聞くと、 「技術者でありながら経営にも関わるとはどういうこと?」 と疑問に思われるかたも多いかと思うのですが、 私の場合はあまり難しく考えていないのです。 以前インタビューを受けたときにも話したことがあるんですが:

(やってみたいと思ったことがあったら) 片っ端からやってみればいいじゃないですか。 だって、世の中には、好きなものか嫌いなものかしかないですからね。 好きなことからやって行けばいいじゃないですか。 好きなことが幾つかあるとかじゃなくて、私の場合、 好きなことがあったらやってみるんですよ。 やってやって、あるとき飽きちゃうみたいな感じなんです。

たまたま目の前に、 「起業に参加するチャンス」があって、 面白そうだから乗ってみた、 というだけのことなのです。 やってみて向いてないと思えば、 思った時点で止めてしまいます。 例えば実際、 論理回路や遺伝的アルゴリズムの論文を書くこととか、 (前職で)定時直後に退社して日が暮れるまでテニスする生活とか、 (大学の時に)数学者目指して勉強をするとか、 (浪人中に)哲学への道を目指そうとしたこととか、 中途半端なまま止めちゃったことも沢山あります。

パネルディスカッションでは、 Ruby 開発者として有名な まつもとゆきひろ さんも、 質問しました:

まつもと 技術者としての上がりとしての CTO ってどうですか?

仙石 CTO が上がりとは思っていない。

まつもと キャリアパスの途中としての CTO は。

仙石 キャリアパスって全然意識していない。 興味のあることをトコトンやって、飽きたらやめる。 今は私が定義した CTO の道をドンドンやるって感じ。 他の人は違うと思うが。

私の受け答えがぞんざいな言葉になってますが、 もちろん小心な私がこんな物言いをするわけはなく、 単に議事録上での表現ですから、 まつもとさんに対して何て口のきき方だ、 などとは思わないように願います。;-)

私にとっての CTO は 「上がり」 どころか 「キャリアパスの途中」 でもなく、 手当たり次第にやってみたことの一つに過ぎないのですが、 幸か不幸か(?) CTO は 9年間も続いていて、 私の今までの人生で二番目に長い記録です。 一番長いのはもちろんコンピュータに対する興味で、 こればっかりは中学生の時以来、 30年以上も変わらず続いています。 よく飽きないものだと思うのですが、 これが 「向いている」 ということなのだろうと思います。

というわけで、 いろいろ手当たり次第にやって、 向いてないことはさっさとあきらめて、 結果として向いてることだけが残る、 という人生を私は歩んできました。 将来のキャリアパスを描いて目的意識を持って努力する、 いわゆる「真っ当な」生き方とは正反対の生き方なので、 他の人に勧めてよいのか微妙ですね。

さて、 CTO って聞くとみなさんはどんなイメージを持つでしょうか。 十人 CTO がいれば十通りの答が返ってきそうですね。 私自身、(株)ケイ・ラボラトリー (当時, 現 KLab) の創業に加わった当初は、 CTO が何をする人なのか具体的なイメージはまるで持っていませんでした。

 仙石さんは何をされているんですか?

仙石 ボケなくちゃいけませんか? 何もしてません(笑)。
会社を興したときは何から何までやってました。 プロマネ兼プログラマ兼システム管理者。 社内でヘルプデスクをやる羽目になったり。 年を経て人が増え、部下に自分がやってた仕事をどんどん任せた。 次から次へと部下が成長していくので、 私がやっていたことを部下ができるようになる。 あるとき、 「自分がデータセンターに行かなくても何とかなるな」と思い、 仕事をどんどん捨てていった。

これこそが CTO の役割なのかな、と思った。 会社の中でやるべきこと、 やったほうがいいことを新たに作って、 明確にした上で部下に押しつける。 そんな感じでやってきた。 自分が今仕事をしているのはよろしくないことだ。 一生懸命部下に押しつけるのが仕事だ。

もうひとつ言わせてもらっていいですか? CTO っていうのは、 「技術者にとっての社長」という役割を果たすべきではないのかな。 技術者はビジネスに対して本音の所では興味が持てない。 なので、社長に本当に心の底から共感できるかというと、微妙。 そういう社員も多いんだろうな、 そういうときにビジネスのことばかり言ってないで技術の話もすれば、 共感できるんじゃないか。

話長いよ、と思われるんじゃないかと恐れて端折ってお話ししたため、 ちょっと分かりにくかったかも知れません。 特に 「何もしないことが CTO の仕事」 という言い方は誤解を招きかねない言い方なので、 ちょっと心配しつつの発言だったのですが、 幸い twitter では好意的な反応ばかりでした (_O_)。

ちなみに私は今まで twitter を使ったことがなかったのですが、 このパネルディスカッションで twitter の威力を思い知り、 改心して twitter のアカウントを作りました。 よかったらフォローしてください。

このときパネラーの藤本さん (グリー) が twitter で 「仙石さんのあとひとことは3 minutes」 って書いていた (話長くてスミマセン) のですが、 その時 twitter を使っていなかった私は気付かなかったのでした。

当然ですが企業は利益を出さなければ存続できませんから、 24時間儲ける仕掛けのことばかり考えているビジネスの戦略家が社長をやるべきです。 ところが技術者にとってビジネスというのは、 その重要性はもちろん分かってはいるんですが今一つ興味が持てない、 というのが本音ではないでしょうか。 かくいう私も、 9年間 CTO をやっていながら、 儲ける仕掛けのことを考えるよりは、 コンピュータのことを考えていたいタチです。

そういう 「ビジネスより技術が好き」 という技術者にとっては、 目を輝かせて会社の将来を語る社長に対して心の底から共感できるかというと、 なかなか難しいところもあるのではないでしょうか。 社内が 「ビジネスを創り出していこう」 という活気で満ち溢れれば溢れるほど、 疎外感を感じてしまう技術者が出てきてしまう気がします。

技術者ってのはおしなべて真面目ですから、 社内の雰囲気に共感できない自分に対して嫌悪感を抱いてしまう。 あるいはビジネスに興味を持つ自分を無理矢理にでも演じてしまう。 でも、何が好きかなんてのは根源的なものなので、 興味が持てないことを無理に好きになろうとしても土台無理じゃないかと思うのです。 そんな技術者に対して、 「ビジネスに関心が持てないのは悪いことじゃない」 というメッセージを送るのが、 CTO の役目なんじゃないかと私は思っています。

仙石 私の持論は 「餅は餅屋」。 技術とビジネスを考える人がいてもいいけど、 24時間技術のことだけを考える人がいて、 24時間ビジネスのことを考える人がいればいい。 会社なんだから、 役割分担しつつ進めていくのがいい会社だと思う。 技術者はビジネスのことは考えなくていいから、 みんなをアッと言わせることをやろうよ、と。

ちなみに、 社長が技術者であれば技術者が疎外感を感じることはないでしょうし、 実際そういった理由で社長が技術者である会社を選ぶ人も多いのだと思いますが、 会社は儲けなければ存続できません。 高い技術が儲けにつながるとは必ずしも言いきれない昨今、 社長が技術のことばかり考えていて大丈夫なのでしょうか?

「餅は餅屋」 の話を受けて、 役割分担するなら、 お互いをリスペクト (尊敬) することが重要だよね、 という話を藤本さんが投げ掛けました。 私も全く同感です:

藤本 お互い(技術者と非技術者)どうやってリスペクトするのか。

仙石 自分ができないことをできる人を尊敬すればいい。ウチの会社はそうなっている。

藤本 エンジニアリングを追求していきたい人とはどういうコミュニケーションを?

仙石 週 1 の定例ミーティングで、私は会計の話をしている。技術者であっても、いろいろなことに興味を持ってほしい。できなくてもいいから。他の人が何をしているかは分かってほしいし、分からなければリスペクトできない。私も会計の素人だが、会計の話を延々としている。

KLab(株) は 8月が期末で、 ここ何週か決算の話を定例ミーティングですることが多かったので 「会計の話」 になったわけですが、 技術職以外の職種についてもきちんと知って、 お互いをリスペクトできるようになって欲しいと思っています。

さて、 「技術者の成長にとって一番役に立つ会社」 を目指している私としては、 どこかで技術者の成長の話をしたいと思っていたのですが、 会場からの最後の質問で 「自分の部下や新卒 1 年生に、 今後こういう風になるからちゃんとやっておけというのがあれば」 という問いかけがあった (いい質問ですね!) ので、 話しました:

仙石 技術者という職種はすごく難しいと思う。 誘惑がたくさんある。次から次へと新しい技術が出てくる。 「ちょっと」 Ruby を勉強しておこうか、って思うじゃないですか。 いろんな言語が出てきて、 何から何まで「ちょっと」勉強してみるというのがあまりにも多すぎるのでは。 「Hello, world.」 を表示させるだけのように、 表層だけ学んで時間を浪費することが多すぎる。 考えることが大事というのはまったく同感。 どんな時代でも、考える力がすべて。 どこまで深く考えられるか。知識を求めることに貪欲になりすぎるな。

知識だけ詰め込んだ 「偽ベテラン」 に陥らないようにして欲しいと思います。

といった感じで、 パネルディスカッションは終わったのですが、 すでに時間を大幅に超過しているにもかかわらず、 森さんから 「最後に、CTO からの熱いメッセージを手短にお願いします」 と言われたので、

会社に対する不満がウェブで山ほど出てくるが、 嫌々する仕事は成長に役立たない。 嘘でもいいから「この仕事をやっててよかったな」と思ってほしい。 どんな仕事でも好きでやってほしい。 今の仕事を楽しむところから成長は出てくる。難しいですけどね。

実は最近読んだ本 「脳に悪い7つの習慣」 に、

脳は気持ちや生活習慣で、その働きがよくも悪くもなる。
この事実を知らないばかりに、脳力を後退させるのはもったいない。

脳に悪い習慣とは、
(1)「興味がない」と物事を避けることが多い
(2)「嫌だ」「疲れた」とグチを言う
(3)言われたことをコツコツやる
(4)常に効率を考えている
(5)やりたくないのに我慢して勉強する
(6)スポーツや絵などの趣味がない
(7)めったに人をほめない
の7つ。

と書いてあって、 なるほどな~と思いながら読んだので、 仕事を楽しんで欲しいという話をしたのでした。 私自身はなにごとも楽しんで取り組むタチなので今一つ実感できないのですが、 なにごとも嫌々やってると身につかないだろうなぁと思います。

Filed under: 元CTO の日記,技術者の成長 — hiroaki_sengoku @ 11:47
2009年10月8日

__sync_bool_compare_and_swap_4 とは何か? ~ glibc をビルドする場合は、 gcc の –with-arch=i686 configure オプションを使ってはいけない

glibc-2.10.1 をビルドしようとしたら、 「__sync_bool_compare_and_swap_4 が定義されていない」 というエラーが出た:

senri:/usr/local/src/glibc-2.10.1.i386 % ../glibc-2.10.1/configure
        ...
senri:/usr/local/src/glibc-2.10.1.i386 % make
        ...
/usr/local/src/glibc-2.10.1.i386/libc_pic.os: In function `__libc_fork':
/usr/local/src/glibc-2.10.1/posix/../nptl/sysdeps/unix/sysv/linux/i386/../fork.c:79: undefined reference to `__sync_bool_compare_and_swap_4'
/usr/local/src/glibc-2.10.1.i386/libc_pic.os: In function `__nscd_drop_map_ref':
/usr/local/src/glibc-2.10.1/nscd/nscd-client.h:320: undefined reference to `__sync_fetch_and_add_4'
        ...
/usr/local/src/glibc-2.10.1.i386/libc_pic.os: In function `*__GI___libc_freeres':
/usr/local/src/glibc-2.10.1/malloc/set-freeres.c:39: undefined reference to `__sync_bool_compare_and_swap_4'
collect2: ld returned 1 exit status
make[1]: *** [/usr/local/src/glibc-2.10.1.i386/libc.so] Error 1
make[1]: Leaving directory `/usr/local/src/glibc-2.10.1'
make: *** [all] Error 2

__sync_bool_compare_and_swap_4 は gcc の組み込み関数なので、 関数が未定義であることを示す 「undefined reference to ...」 というエラーメッセージは、 誤解を招く不親切なメッセージだと思う。

__sync_bool_compare_and_swap_4(mem, oldval, newval) は、 mem が指し示すメモリの値 (4バイト分) が oldval であれば newval に変更する、 という操作をアトミックに行なう組み込み関数。 アトミック (不可分) 操作とは、 操作の途中が存在してはいけない操作のことで、 この例なら比較 (メモリの値が oldval か?) と代入 (newval に変更) が必ず 「いっぺん」 に行なわれ、 「比較だけ行なったけどまだ代入は行なわれていない」 という状態が存在しないことを意味する。

アトミックに行なうためには、 当然ながら CPU でその操作をサポートしている必要がある (複数個の命令の列で実現しようとすると、 命令列の半ばを実行中の状態が必ず存在してしまう) わけだが、 残念ながら Intel 386 プロセッサでは、 この compare_and_swap (CMPXCHG 命令) をサポートしておらず、 サポートするのは Intel 486 以降の CPU である。 テストプログラムを書いて試してみる:

#include <stdio.h>

int main() {
    int mem[1], oldval, newval;
    oldval=0;
    newval=1;
    mem[0] = 0;
    __sync_bool_compare_and_swap(mem, oldval, newval);
    printf("mem[0]=%d\n", mem[0]);
    return 0;
}

見ての通り、 mem[0] の値を oldval の値 (0) と比較し、 一致していたら newval の値 (1) を代入し、 mem[0] の値を表示するだけのプログラムである。

関数名が 「__sync_bool_compare_and_swap」 であって、 後ろに 「_4」 がついていないことに注意。 gcc が引数の型 (この例では int) を見て、 その型のビット長を後ろにつけてくれる (この例では int 型は 4 バイトなので 「_4」 をつけてくれる)。

gcc では 「-march=タイプ」 オプションを指定することによって CPU タイプを指定できる。 -march オプションを指定しなかったり (この場合は全 CPU でサポートされる組み込み関数のみ利用できる)、 あるいは -march=i386 を指定したりすると、 コンパイル時にエラーになる:

% gcc -Wall test.c
/tmp/cc4eNX6L.o: In function `main':
test.c:(.text+0x3b): undefined reference to `__sync_bool_compare_and_swap_4'
collect2: ld returned 1 exit status
% gcc -Wall -march=i386 test.c
/tmp/cc6chtFj.o: In function `main':
test.c:(.text+0x36): undefined reference to `__sync_bool_compare_and_swap_4'
collect2: ld returned 1 exit status
% gcc -Wall -march=i486 test.c
% ./a.out
mem[0]=1

いまさら i486 というのもアレなので、 今なら i686 を指定するのがよさげ。 私の手元にはいまだ PentiumIII マシンがあるものの、 PentiumIII より古いマシンはない (昨年 ML115 と SC440 を買ったとき PentiumII マシンを引退させた) ので、 pentium3 を指定すれば SSE (Streaming SIMD Extensions) が利用できるようになるが、 glibc をビルドするときに必要かというと、 たぶん必要ない。

というわけでエラーの原因は分かったが、 では glibc をビルドするときは、 どうすればいいだろうか?

とりあえず google で検索してみたら、 gcc の configure オプションに 「--with-arch=i686」 を指定して gcc をビルドする必要がある、 と書いてあるページが見つかった。

--with-arch オプションは、 -march のデフォルトを設定するための configure オプションである。 つまり 「--with-arch=i686」 を指定して gcc を再インストールすると、 gcc に -march オプションをつけなくてもデフォルトが i686 になる。 なるほど確かにそうすれば、 glibc 側で何も変更せずに __sync_bool_compare_and_swap_4 関数が使えるようになりそうである。

いまどき i686 以前の CPU 用のコードが必要になりそうなケースは滅多にないだろうから、 -march オプションのデフォルトを i686 にするのも悪い選択ではないように思えた。 gcc をビルドし直すのは面倒だなーと思いつつも、 ついでに gcc のバージョンを上げておこうと gcc-4.3.4 をダウンロードしてきて 「--with-arch=i686」 付でビルドしてみた。

ところが!

More...
Filed under: システム構築・運用,プログラミングと開発環境 — hiroaki_sengoku @ 09:39
« Newer PostsOlder Posts »