Hatena::ブログ(Diary)

(ひ)メモ このページをアンテナに追加 RSSフィード

2009-04-26 (Sun)

WEB+DB PRESS Vol.50のgit特集とkazeburoさんの連載がよいっすね!

わかばちゃんの髪留めが「D」の形に見えますが何か意味があるのでしょうか?

東京都港区 ひろせ31さん

という質問をわかばのお悩み相談室に投書しようか悩んでいるhirose31です。


まだ全部読んでませんが、目についたのから読んでいってます。

はじめてのGit

gitはチュートリアルをなんとなく読んでなんとなく使ってきた感じなので、内容がまとまっててページ数も手頃なサイズに凝縮されていたので、再習得するのにもってこいでした。

git diff/git diff --cached/git diff HEADの違いや、git revert/git checkout HEAD/git resetの違いとか、日々の典型的な作業やブランチの構成・運用ポリシーとかとか。

文章の構成はチュートリアル形式でgitはじめての人でも読みやすい構成になっているんですが、そこかしこにgitの設計思想的なものが見え隠れしていて流石gitリーダのHamanoさんが書いた文章だなーと思いました。

大規模Webサービスの裏側

kazeburoさんの新連載です。今回は「静的コンテンツの負荷分散」がテーマ。

一口に「静的コンテンツの配信」といっても、配信するものによって特性が大きく違うので、システムの構成も異なってきます。

記事中でもコンテンツの性格によって数種類のシステム構成が紹介されているんですが、いいなーと思ったのは「『なぜ』ここのような構成にしたか」という部分がちゃんと語られていることでした。この手の記事は、Why?の部分がないとただの事例紹介にとどまり「ふんふんそうなんだー」でおわってしまうのですが、Why?の部分の主張があると、自分の考えと同じところ違うところが鮮明になるので、より役にも立ちますし、記憶にも残ります。

次回も大期待です♥

2009-04-24 (Fri)

シェルスクリプトでデバッグプリント

どこでみたかわすれたけど : を使う方法。

#!/bin/sh

[ "$VERBOSE" = '1' ] && VECHO='echo VERBO:' || VECHO=:
[ "$DEBUG"   = '1' ] && { VECHO='echo VERBO:'; DECHO='echo DEBUG:'; } || DECHO=:

echo   go ahead!
$VECHO ugoiteru $$ now!
$DECHO mou owari

exit

実行例

$ ~/t.sh
go ahead!

$ env VERBOSE=1 ~/t.sh
go ahead!
VERBO: ugoiteru 23055 now!

$ env DEBUG=1 ~/t.sh
go ahead!
VERBO: ugoiteru 23115 now!
DEBUG: mou owari

2009-04-22 (Wed)

コードポケット - アプリケーションをささっと作るコツ

誰に教えられたのでもないのですが、ぼくは冬眠前のリスのようにコード片を溜め込んでいます。

コード片とは、ライブラリにするほどまとまった大きさではない、数行〜十数行のコードのことで、溜め込んだコード片は、アプリケーションやツールを作るときに使っています。

例えば「Perlでメール送るのどう書くんだっけかな」とか「Pythonでファイル開いて全部読むのどう書くんだっけかな」とかというときに、溜め込んだ中からコード片をさっと取り出してコピペした後、なじむようにちょっと修正して使っています。


コードポケット

コードを溜め込んでいるディレクトリをぼくは「コードポケット」と名付けていて、コード片を取り出すことを「ポケットからコードを取り出す」と呼んでいます。先日、知り合いが似たようなことを実践していて、その人は「コードスケッチ」と呼んでました。いい名前ですね。

ぼくの場合、コードポケットは ~/lang/言語名/ の下にばらっとファイルがあるだけという昭和風の構成です。コード片が多い言語は用途に応じてサブディレクトリを作ったりもしています。

ポケットからコードを取り出すには、ファイル/ディレクトリ名で検索しています。

以下のような、 iname (あいなめ) という名の大文字小文字を同一視して名前の部分一致検索するシェル関数と、よくtypoするのでinaemというaliasを作っています。

iname() {
  find . -type d -name .svn -prune -o \( -iname "*$1*" -print \)
}
alias inaem=iname

例えばrubyでファイルを読みたいなーというときは、こんな風にして探しています。

$ cd ~/lang/ruby
$ iname file
./file
./profile
./profile/doprofile.sh
./profile/profileme.rb

「file」というディレクトリが引っかかったのでその中を見てみると、open-each.rbというファイル名のおめあてのコード片がありました。

ポイントはファイル/ディレクトリの名前のつけ方で、将来の自分が検索しそうなキーワードをいくつか羅列した名前にしたり、シンボリックリンクをはって別な名前をつけたりしています。

ポケットになにを入れるか

10年以上ポケットにコード片を詰め込んできて、自分なりのコツがいくつかあるので紹介します。

  • 自分で書いたり動かしたりしたコード片をポケットに入れる
    • よそからコピペしたのをそのまま入れるより、コピペしてからちょっとでもいじって動かしてみてコメントつけたコード片の方があとあと役に立つ度が高い気がします。
  • 鮮度を保つ
    • コードの書き方や使うライブラリは、流行り廃りがあるので、「お!いいな、このコード」「へーこういう書き方もあるんだー」と思ったらすかさず自分のポケットの中のコード片も更新するようにします。
  • OSSのプロダクトとかはポケットに入れない
    • おっきすぎてはいりません。
    • いれちゃうと検索でヒットするのが増え過ぎます。今ならコードサーチで検索すれば十分でしょう。
    • コードポケットは、あくまで自分が書いた/見つけた小さいコードを入れておく、というのがミソだと思っています。

最後に、ぼくのポケットの中のファイル数を晒します。コードじゃないファイルもカウントしてるんで正確性は低いですが、まぁこんな感じという雰囲気は伝わるんでないかと思います。

$ for l in *; do printf "%-12s %4d\n" $l $(find $l -type f|wc -l); done | sort -k2nr
perl         1460
java         1010
c             568
sql           231
sh            186
php           141
js             41
ruby           37
as             33
erlang         30
rrd            30
ps             28
make           22
graphviz       21
tk             20
awk            17
gnuplot        13
python         13
sed            10
elisp           5
tcl             5
expect          4

Enjoy!

Special thanks!

2009-04-21 (Tue)

OracleとSunが買収した企業を視覚化してみました

f:id:hirose31:20090421183249p:image:h800:left

SunはコバルトとかlustreのCluster File Systemsも買ってたんだなーとか、

OracleはBerkeley DBのSleepycatとかInnobaseも買ってたんだなーとか、

BEAも買ってたんだなーとかとか。


元データ

あわせてよみたい

追記

  • 誤字 s/acquistion/acquisition/ を修正しました。id:h_test さんありがとうございましたー
  • ついでに http://en.wikipedia.org/wiki/Oracle_Corporation の方のデータを使うようにしました
  • f:id:hirose31:20090421122552p:image:h24 permalink変えたくなかったんで古い画像を差し替えようと思ったんすけど、やりかたわからなかったんで古いのはそのままです。

2009-04-20 (Mon)

nginxで名前ベースのバーチャルホストの複数指定をするときの注意点

先日、wikipedia:冒険遊び場 に参加してきて、森の中を駆けずり回ったり、泥んこ遊びをしたり、たき火でおにぎりや焼きイモを焼いたりましまろを炙ったりして食べたhirose31です。あといまだにnginxかngnixかつづりがおぼえられないhirose31です。

nginx (0.6系) で、ひとつのserverブロックで複数の名前ベースのバーチャルホストを設定するには、server_nameディレクティブをこんな感じで指定します:

  1. 列挙する: chikin.curry.example.com beef.curry.example.com pork.curry.example.com
  2. 先頭(か末尾)にワイルドカード: *.curry.example.com
  3. 正規表現

ここで注意しなければならないのは、nginxがLocationヘッダのリダイレクトをする場合です。例えば、http://example.com/dirname のようにパスがディレクトリなのに末尾のスラッシュがないリクエストが来た場合のレスポンスがこれにあたります。

デフォルトでは、nginxがLocationヘッダで使うホスト名はserver_nameディレクティブで最初に指定されている文字列です。

例えば、こんな感じで設定している場合、

http {
  ...
  server {
    listen       4649;
    server_name  ~^(chikin|be+f|pork)\.curry;

リダイレクトがかかるようなHTTPリクエストをすると、レスポンスはこんな感じなってしまいます。

goa[~]$ curl -i http://beeeeeeeeeeeef.curry.example.com/tabetai
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Mon, 20 Apr 2009 09:23:46 GMT
Content-Type: text/html
Content-Length: 178
Location: http://~^(chikin|be+f|pork)\.curry/tabetai/
Connection: keep-alive

<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>

Locationヘッダのホスト名がこれではまずいですね^^

というのにさっき気がついたので、

server_name_in_redirect  off;

にしました。

offにすると、server_nameディレクティブじゃなくて、クライアントがリクエストしてきたHostヘッダの文字列がLocationのホスト名として使われるようなります。

server_name_in_redirectはserverブロックはもちろん、httpブロックにも書けるので、httpブロックでoff指定して全serverブロックで有効になるようにしました。

あわせて確認したい

愛用のMacBook 13" Aluminum のインナーケース

f:id:hirose31:20090420011723j:image:left

MacBookを毎日持ち歩くようになって、衝撃やキズが気になったので BUILT のインナーケースを使ってます。

素材は、ウエットスーツみたいな感じでやわらかめ。MacBookにピッタリフィットなのでインナーケースとしてバックの中に入れても無駄にかさ張らなくていい感じです。

あと、短辺にジッパーがついていて縦長に出し入れできるので、写真みたいにバックパックやトートバックに入れっぱスコっと出したり入れたりできるのも選んだポイントです。

ただこれ、サイズがいろいろあるので購入するときは要注意です。

ネットだと店舗によって製品名表記や寸法がまちまちで、サイズがあうか不安だったので、自分は原宿のAssistOnに行ってその場でMacBookを入れさせてもらって確認してから買いました。


おまけ

BUILTのデザインはどっかでみたことあるなーと思ってたら、ワインケースやベビーグッズも出してるんですね。

BUILT BABY ワンボトルホルダー 4192 BK

BUILT BABY ワンボトルホルダー 4192 BK

2009-04-19 (Sun)

ganglia (gmond) を拡張するモジュールをPythonで書いてみた

ganglia (http://ganglia.info/) 3.1以降では、データの収集を行うgmondを拡張したい場合、C言語のモジュールを書くほかに、modpython (libpython) をロードすることにより、pythonでも拡張モジュールを書けるようになっています。

なので書いてみました。


このモジュールは、ユーザが指定したネットワークインターフェースについてだけ、トラフィック(転送バイト数とパケット数)をモニタするものです。

トラフィックのモニタなら標準添付のmod_netがあります。Linuxの場合の実処理は libmetrics/linux/metrics.c でなされているのですが、こんな実装になっています:

  • /proc/net/dev を読んで転送バイト数などの値を得る
  • ネットワークでバイスが複数ある場合は、合算する
  • ただし、loとbond*なデバイスは除く

これだと、ルータ用途などで複数の物理NICがあり、それぞれのデバイスのモニタをしたいときに困ります。

自分の場合も、タグVLAN(bond0.2とか)で論理分割している上位回線のトラフィックだけをモニタしたかったのが、このpythonモジュールを書いた動機です。


pythonでgmondモジュールを角煮は、hookポイントが定められているのでそれに従って実装します。とてもシンプルなので、

を読めばすぐ書けるんじゃないかと思います。


ちなむと、ganglia 3.0の頃は、カスタムデータを追加するのに gmetric コマンドを使っていたのですが、モニタ項目が多くなると fork のコストもばかにならなくなるので、gangliaのCライブラリとリンクした拙作のPerlのXSモジュールを使っていました。

あわせて読みたい

みんなのPython 改訂版

みんなのPython 改訂版

Python!!

The Art of Capacity Planning

The Art of Capacity Planning

gangliaを使っているらしいFlickrの話。著者のスライドが

にあるのでこっちも必見。

2009-04-10 (Fri)

DNS NOTIFYを受け取ってくれる無料のセカンダリDNSサービスと、NOTIFYを送るスクリプト

個人所有のドメインのDNSサーバは、マスタは自宅サーバ(djbdns)でセカンダリはXNameの無料のセカンダリネームサーバのサービスを使っていました。

それなりに動いてくれていたXNameですが、不満な点が1つありました。それは、マスタを変更したときのゾーン情報の伝搬に時間がかかる点です。XNameは数台のセカンダリネームサーバを提供していて、伝搬速度はサーバによってもタイミングによってもばらばらですが、早いときは数十分、遅いときは5,6時間たってようやく更新されることもありました。

XNameもDNS NOTIFY受けてくれたらいいのになーなんて思いつつも、個人所有ドメインでそんなシビアなサービスもしてないので、ま、いっかーと思っていたんですが、先日、EveryDNS.netがダウンして巷でわーぎゃーわーぎゃーな騒ぎになったときに、ちょろっと調べてみたらいくつかDNS NOTIFYを受け付けてくれる無料のセカンダリDNSサービスをやってることをみつけたので、そのひとつのEditDNSを試してみることにしました。

追記

2010/1/1からセカンダリDNSサービスは有料になるそうです。


あとはDNS NOTIFYを送るツールが必要です。自分が使っているのはdjbdnsなので同梱されていません。ぐぐると tinydns-notifyというPerlスクリプトがあったのですが、NOTIFYを送る先のネームサーバやゾーンの指定がいまいち自分のほしいものとは違ったので、そこを書き換えたスクリプトを作りました。

あとでぐぐぐったらNOTIFYを送るツールがなんこがみつかったので、用途があえばそっちを使ってもいいと思います。

マスタの更新には、make installと実行すると、レコードが列挙されたテキストファイル片をいくつかcatして、dataを作り、tinydns-dataでdata.cdbを作り、マスタのサーバにscpする、というMakefileを書いて使っていたので、scpしたあとにsend-dns-notifyを実行してEditDNSのネームサーバにNOTIFYを送るようにしました。注意するのは、send-dns-notifyを実行するのはマスタのホストで実行するのと、もしマスタのホストが複数のIPアドレスを持っている場合は、send-dns-notifyの-bオプションでセカンダリからのゾーン転送要求を受け取る(=axfrdnsがlistenしている)IPアドレスを指定する点です。

いまのところEditDNSのネームサーバは、NOTIFYを送ればほぼすぐにゾーン情報を取りに来てくれるので、いつ更新されるのかとヤキモキしなくていいので快適です。

ちなみに、EditDNSのネームサーバにはUSとEUにあるのですが、自分が計った限りでは、USにあるネームサーバのほうが応答速度が早かったので、DNS NOTIFYは全ネームサーバに送りつつも、NSレコードにはUSのサーバのみを書いてます。

ちなみに、XNameもEditDNSもマスタDNSサーバのサービスもやってるので、複数のサービスをつかえばマスタもセカンダリも無料でネームサーバが上げられるんじゃないかと思います。あと、無料サービスなんで、もしかしたら制限(セカンダリのドメイン数)とかあるかもしれませんがよくしらべてないす。

参考

2009-04-06 (Mon)

2009-04-01 (Wed)

tcpdumpとiptablesの関係

追記 2009-04-03

まったくもってブコメでいただいた指摘の通りです><

h2onda linux, tcpdump tcpdump(というかlibpcap)は、データリンク層(OSI layer2)レベルでパケットを取得する packet プロトコルを使ってるので、そうなります。参照: man packet(7) 2009/04/02

はてなブックマーク - h2ondaのブックマーク / 2009年4月2日

tt_clown network 細かいけど,図は逆(NIC が下)のが良いかなと思った./ "ip"tables と言う位だから,IP層でパケットをフィルタしてるて事だろうな.tcpdumpEthernet Frameも見えるので,後は分かるな?・・・てとこか. 2009/04/02

はてなブックマーク - tt_clownのブックマーク / 2009年4月2日

packet(7)によれば、

packet ソケットは、デバイスドライバ (OSI レイヤ 2) レベルで 生のパケット (raw packet) を送受信するために用いられる。 packet ソケットを使うと、ユーザー空間で物理層の上に プロトコルモジュールを実装することができる。

...

ocket_type には SOCK_RAW と SOCK_DGRAM のいずれかを指定する。 SOCK_RAW はリンクレベルヘッダを含む raw パケットを、

...

SOCK_RAW パケットでは、パケットをデバイスドライバと受け渡しする際、パケットデータに変更が行われることはない。パケットの受信時には、アドレスの解析だけは行われ、標準的な sockaddr_ll アドレス構造体に渡される。

404 - エラー: 404

とのことなので、((SOCK_RAWを使っている)libpcapを使っている)tcpdumpは、L2の中でもデバイスからいちばん近いところでピチピチのパケットを観測できるわけですね。で、次のステップとして、OSI的により上位のL3に渡され、そこでiptablesでフィルタリングなどが行える、と。

あとこれは裏を取ってないんですが、L2のEthernetフレームをフィルタリングできる ebtables は、同じL2でもSOCK_RAWより上位に位置してるんですかねー L2:{SOCK_RAW→ebtables} → L3:{iptables} → L4:... みたいな。


とにかく、id:h2onda さん、id:tt_clown さんはじめブクマしてくださったみなさん、ありがとうございました!

追記 あわせて読みたい



本文

Linuxでiptables、ipvs、ip routeとかそのへんのネットワーク系の設定をする際に、パケットの到達確認をするのにtcpdumpは非常に有益なわけですが、tcpdumpのレイヤとiptablesなどのレイヤの関係を把握していないと混乱することが年に数回はあります。

例えば「INPUTチェインでDROPしているのにtcpdumpで見るとパケットが届いてるわ…」とか。

コードレベルでなくて挙動観察レベルですが、tcpdumpとiptablesの世界の関係はこんな感じっぽいです。

f:id:hirose31:20090401195923p:image:w600

この階層構造を意識してパケットの気持ちになると、

  • INPUTでDROPしてても、tcpdumpでは(DROP前の)パケットが観測できる
  • tcpdumpで観測する限り、INPUTでDROPしているのとOUTPUTでDROPしているのとは見分けられない
  • PREROUTINGでDNATしてアドレス変換している場合、変換後のアドレスはtcpdumpでは観測できない
  • POSTROUTINGでSNATしてアドレス変換している場合、変換後のアドレスはtcpdumpで観測できる
  • PREROUTINGでREDIRECTしている場合、tcpdumpで観測できるdestinationアドレスは元々のものである

というのも理解できるでしょう。

あわせて見たい

さっきの図の元ネタはこのへんです:

特に後者のLVS-HOWTOは、iptables(netfilter)の世界のどのへんにipvsが食い込んでいるかわかるので、パケットをマングル!マングル!する方には必見の図と思います。

2003 | 11 | 12 |
2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 05 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 12 |
2012 | 01 | 02 | 03 | 06 | 08 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 |
2015 | 01 | 02 | 07 | 10 |
2016 | 01 | 05 | 10 | 12 |
2017 | 07 |