bluegold OpenSolaris と MacBook で自宅ネットワークを構築するメモ 2011-08-06T16:10:12Z https://blog.bluegold.me/feed/atom/ WordPress bg http://blog.bluegold.me <![CDATA[AirMac Extreme で困った事]]> http://blog.bluegold.me/?p=627 2011-08-06T16:08:37Z 2011-08-06T16:08:37Z AirMac Extreme に買い替えてみた

自宅でルーターとして使っていた安物の無線LAN AP の調子が悪く、頻繁に落ちるようになったので、新しい物に買い替えました。

EAP-TLS の実験もしたかったので、今回は AirMac Extreme にしてみました。

AirMac Extreme はアップル製だけあって設定は簡単で、802.1X EAP-TLS で認証をさせても安定しているようです。それはいいのですが。。。

困った事

アップルの製品は設定が簡単でいいのですが、設定項目が少なく、アップルの想定している使い方からちょっとでも外れるとどうにも出来なくなる事があります。

今回も2点ほど困った点があったので、メモしておきます。

  1. ローカル側のIPアドレスが変更できない。

    AirMac Extreme をルーターとして使用する場合、ローカル側の IPアドレスが 192.168.0.1 のように末尾が 1 に固定されていて、変更することができません。
    ローカルのIPアドレスを設定できないネットワーク機器なんてあるはずないと思い、方法を探してみましたが、解決策は無いようでした。

    うちのネットワークは、これまで 192.168.0.254 のように 254 で終わるアドレスをデフォルトゲートウェイにしていたので、このアドレスが変わると固定アドレスを持っているたくさんのサーバーたちの設定も変更する必要が出てきてめんどくさいんですよね。

    しかたないので、常時起動している Linux に 254 のアドレスを割り当てて、ICMP redirect で正しいデフォルトゲートウェイのアドレスを通知するようにしました。(ついでにキャッシュ用のネームサーバーも立てました。)

    最初は OpenSolaris に ICMP redirect を投げさせようとしたんですが、なぜか出来なかった。。。

  2. ftp のポートマッピング(NAT)で標準以外のポートを使えない

    他の人とデータのやり取りをする為に ftp サーバーを立てていますが、標準のポートで起動させておくと勝手にログインしてこようとする人たちがたくさんいます。パスワードとログの管理がめんどくさいので、これまではルーターで標準以外の別のポートから NAT させていました。

    AirMac Extreme でも同様の設定をしてみたのですが、接続できません。

    アップルのフォーラムでも同様に困っている人はたくさんいるのですが、やはり解決策は無いようでした。

    いろいろと試してみた結果をまとめると

    • ftp 以外の NAT は予想した通りに動作する。
    • プライベートTCPポートを 21 にして、パブリックTCPポートが21以外だと、ルータで止められる。
    • プライベートポート、パブリックポートの双方を 21にすると接続できるようになる。
      ただし、FTP のデータポートを正しく扱えなくなるので、実質的に使えない。

余談その1

実験中に OpenSolaris で動かしている ftpサーバーのポートを変えようとしたが、inetadm ではポートを変更する方法がなかった。。。

しかたがないので、/etc/services を修正して対応。。。

余談その2

Mac OS X 10.7 Lion で EAP を使う場合の設定方法がものすごくシンプルになりました。

どこかで見た事あるなぁ、と思ったら iOS と同じになったみたいです。

]]>
0
bg http://blog.bluegold.me <![CDATA[nginxでWordPressの記事を静的配信する]]> http://blog.bluegold.me/?p=608 2011-08-06T16:10:12Z 2011-01-28T16:59:09Z 前に途中まで書いていた記事をようやく公開。(twitter の書き込みを見ると 2010年10月ごろか)

WordPress はユーザ数が多いだけに、必要なものはたいていプラグインとして用意されている非常に使いやすいCMSだと思いますが、毎回動的にしかページを作れないという点にはちょっと不満を持っていました。

nginx や Vernish などのプロキシサーバを別に立ててキャッシュさせる方法を試そうと思っていたのですが、はまりポイントが多いらしく躊躇していました。そんな時に Really Static というプラグインを見つけたときから、今回の話は始まります。

Really Static プラグインの問題点

Really Static プラグインは、ブログの記事の HTML を PHP の curl 関数でダウンロードして static フォルダの中に置いておき、それ以降は PHP で動的に HTML を作るのではなく、静的な HTML ファイルを返す、といった事をしてくれるプラグインです。ちょうど、Ruby on Rails のページキャッシュみたいなイメージですね。

インストールも設定も難しくなく、HTML のダウンロードも WP-cron で少しずつ行われるため、完全に WordPress 内に閉じた環境で実現できるすぐれたプラグインだと思いますが、(私にとっては)ひとつだけ大きな欠点がありました。

それは、Really Static プラグインがサイトの構造(URL)を変えてしまうことでした。
例えば、http://blog.bluegold.me/sample という URL の記事に対して、Really Static の導入後にアクセスすると http://blog.bluegold.me/static/sample.html に 301 redirect されてしまいます。
さらには他のページに書かれたリンクも静的ファイルの URL を直接さすように変更されてしまうので、一度導入してしまうと、後で使うのをやめるときに元に戻すのが難しくなってしまうのではないかと思いました。

最初は Really Static プラグインに手を入れて、リンクの URL を変更させないようにしようと思ったんですが、コードを読むと仕組みは意外と単純だったので、Wordpress に統合することを考えなければ、nginx の try_files だけで、似たようなことが出来ることに気がつきました。

nginx の機能を使う

nginx の try_files はリクエストを処理する際に実際のファイルを探す順番を記述する nginx に固有の設定項目で、Apache では mod_rewrite の複雑なルールを駆使して実現できるようなことをシンプルなルールで記述できるようにしたものです。

現在のこのブログの nginx.conf には以下のような記述がされています。

location {
  gzip_static on;
#  try_files /system/maintenance.html /static/$uri/index.html $uri /index.php?q=$uri&$args;
  try_files /system/maintenance.html /static/$uri/index.html$args $uri /index.php?q=$uri&$args;
}

具体的な設定は WordPress のパーマリンクの設定で変わります。
$uri にはリクエストされた URL のパスの部分が入っています。リクエストを処理する際は以下を順番に調べていって、最初に見つかったものを返します。

※ 2011/01/30 追記
静的HTML化した投稿を表す /static/$url/index.html には $args も付けておかないと、プレビューが出来ませんでしたので修正しました。
  • メンテナンス画面(/system/maintenance.html)
  • 今回追加した静的HTMLのキャッシュ
  • css や画像などの静的ファイル
  • それ以外は WordPress に処理を渡す

この設定だけで静的なHTMLファイルの配信は出来るようになります。

静的HTMLの作成

あとはブログの各記事を HTML としてダウンロードするだけです。

$ wget -r --follow-tags=a http://blog.bluegold.me

(あくまでも例なので、自分のサイト意外にはやらないでくださいね。)

静的HTMLに変換しておくことで、このくらい速くなりました。(それぞれ3回試行)

  平均 最速 最遅
WordPressのみ 0.544s 0.385s 0.832s
静的HTML 0.086s 0.084s 0.088s

実はこのブログは WPtouch プラグインも使っているので、このままでは iPhone 用の画面が表示されません。
この対処法はまた次回。

]]>
2
bg http://blog.bluegold.me <![CDATA[Snow Leopard で隠しファイルを表示するショートカット]]> http://blog.bluegold.me/?p=601 2011-01-03T16:25:11Z 2011-01-03T16:25:11Z Snow Leopard で隠しファイルを表示するショートカット

Mac OS X の Finder では先頭が ‘.'(ドット) で始まるファイル名や不可視属性の着いているファイルは表示されませんが、これらの隠しファイルを「開く/保存」ダイアログで表示するショートカットが Snow Leopard で追加されました。

「Command」キー+「Shift」キー+「 . 」(ピリオド)

補足:ファイルの不可視属性の設定方法

これだけだと短すぎるので、不可視属性の設定方法もメモ

SetFile -a V filename

逆に不可視ファイルを表示させるには V を v にします。

]]>
0
bg http://blog.bluegold.me <![CDATA[OpenSolaris 134b で php-cgi が動作しない]]> http://blog.bluegold.me/?p=590 2011-01-29T18:42:53Z 2010-11-23T14:58:03Z Oracle Solaris 11 Expressがようやく公開されました。このブログを動かしている OpenSolaris 2009.06 の次のバージョンは、当初 OpenSolaris 2010.02 になるはずだったので、9ヶ月遅れてのバージョンアップとなりました。

Sun が Oracle に買われて以降、Solaris がどうなるのかハッキリしない状態が続いていたので、新しいバージョンがリリースされた事は良かったと思います。OpenSolais の体制のままで新バージョンがリリースされていれば最高だったんですけどね。

リリースはされましたが、Oracle Solaris 11 Express は snv_151 で、OpenSolaris 2009.06 の snv_111b からは大きく変わっているらしく、一回でアップグレードはできません。一度 snv_134b(キャンセルされていた OpenSolaris 2010.06 になるはずだったバージョンですね)に上げた後で、パッケージリポジトリ(パブリッシャ?)を変更して再度アップグレードを行う必要があるようです。

最終的に Oracle Solaris 11 Express(毎回書くのは長いな、略称は何だろ?)を使うか、OpenIndiana を使うようになるかは分かりませんが、どちらにしろ 134b にアップデートしておく必要はあるみたいです。

134b へのアップデート方法

アップデートはpkg image-updateコマンドで行いますが、先に SUNWipkg パッケージを更新しておく必要があるみたいです。

pfexec pkg install SUNWipkg
pfexec pkg image-update -v --be-name snv_134b

いろいろとパッケージをインストールして遊んでいたので、2時間くらいかかりました。

本番環境をアップグレードする前に VirtualBox に OpenSolaris 2009.06 をインストールして、アップデートの実験は何度もしていたので、この手順自体は問題なく終わりました。svcsコマンドでサービスの起動状況を確認して、maintenance になっているものも無かったので、アップグレードは無事終わったかと思っていましたが、ブログを表示させようとするとこんな感じになっていました。

お使いのサーバーの PHP では WordPress に必要な MySQL 拡張を利用できないようです。

問題の調査

php-cgi コマンドが正常に動いていないのか、と思い直接実行してみると

# /usr/php/bin/php-cgi -v
PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/php/5.2/zts-modules/apc.so' - ld.so.1: php-cgi: 重大なエラー: 再配置エラー: ファイル /usr/php/5.2/zts-modules/apc.so: シンボル compiler_globals_id: 参照シンボルが見つかりません。 in Unknown on line 0
PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/php/5.2/zts-modules/bz2.so' - ld.so.1: php-cgi: 重大なエラー: 再配置エラー: ファイル /usr/php/5.2/zts-modules/bz2.so: シンボル core_globals_id: 参照シンボルが見つかりません。 in Unknown on line 0
PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/php/5.2/zts-modules/curl.so' - ld.so.1: php-cgi: 重大なエラー: 再配置エラー: ファイル /usr/php/5.2/zts-modules/curl.so: シンボル core_globals_id: 参照シンボルが見つかりません。 in Unknown on line 0
PHP Warning:  PHP Startup: ftp: Unable to initialize module
Module compiled with module API=20060613, debug=0, thread-safety=1
PHP    compiled with module API=20060613, debug=0, thread-safety=0
These options need to match
 in Unknown on line 0
(略)
PHP 5.2.12 (cgi-fcgi) (built: Apr  5 2010 20:00:17)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies

マルチスレッドでない PHP のプロセスから、マルチスレッドを有効にしたモジュールを読み込もうとして失敗しているようです。php コマンドは正常に動作していましたが、nginx は CGI を使えない。そもそも zts-modules なんてディレクトリは php.ini で指定していないのに、どこから出てきたのかがわかりません。

しばらく悩みましたが、phpinfo() の出力を見て、ようやく気がつきました。

Loaded Configuration File	/etc/php/5.2/nsapi/php.ini

これまでは/etc/php/5.2/php.ini を読んでいたのが、バージョンアップ時に変わってしまっていたようです。NSAPI 用の php.ini ならスレッドセーフのモジュールを読むのは自然です。(NSAPI が現役なのかは知りませんが。自分で最後に NSAPI モジュールを書いたのは13年くらい前か。)

原因は分かれば修正は簡単で、/etc/php/5.2/nsapi/php.ini を以下のように修正して問題解決。

543c547
< extension_dir=/usr/php/5.2/zts-modules
---
> extension_dir = "/usr/php/5.2/modules:/var/php/5.2/modules"
]]>
0
bg http://blog.bluegold.me <![CDATA[証明書と RSA 鍵がペアかどうかを調べる方法]]> http://blog.bluegold.me/?p=574 2010-08-26T14:36:34Z 2010-08-26T14:36:34Z 証明書ファイルと RSAの秘密鍵ファイルがペアになっているかどうかの確認方法をよく忘れるのでメモ。

RSA 鍵で作成した証明書の場合、証明書内の公開鍵と秘密鍵は同一のモジュロ(Modulus)を持っているので、これを比較します。

証明書(公開鍵)

openssl x509 -noout -modulus -in certificate_file.pem

秘密鍵

openssl rsa -noout -modulus -in private_key.pem

ついでにCSR

openssl req -noout -modulus -in cert_request.pem

これらの実行結果として表示されるモジュロはかなり長くなるので、更に MD5 ダイジェストを計算した法が比較は簡単になります。

openssl x509 -noout -modulus -in certificate_file.pem | openssl md5
openssl rsa -noout -modulus -in private_key.pem | openssl md5
openssl req -noout -modulus -in cert_request.pem | openssl md5
]]>
0
bg http://blog.bluegold.me <![CDATA[WordPress Amazon S3 Plugin で画像を CloudFront から配信]]> http://blog.bluegold.me/?p=543 2011-01-28T17:05:53Z 2010-08-23T17:37:58Z 以前の記事にもある通り、このブログではスタイルシートや画像、JavaScript ファイルなどの静的ファイルを Amazon S3 に置いて、Amazon CloudFront から配信しています。

URLの切替には自作のプラグインを使っています。記事にした当時は stylesheet_uri と template_directory_uri の置き換えをするだけのものでしたが、今は WP_PLUGIN_URL も置換えて、プラグインが追加するスタイルや画像も CloudFront から配信しています。

ここまではわりと簡単に実装できていたのですが、メディアライブラリ(uploads ディレクトリ)に置いた画像ファイルは記事の中身を書き換える必要があるため、なかなか手を出せずに1年くらい放置していましたが、最近、WordPress Amazon S3 Plugin というものがあるのを知り、さっそく試してみました。

このプラグインのセットアップは簡単で、plugins ディレクトリに置いて有効化したあとで、Amazon S3 の認証情報と画像を置くバケツ名を指定するだけです。

設定が完了した後はしばらく待っていると、wp-cron の仕組みを使い、誰かがアクセスしてきた時にバックグラウンドで画像ファイルを Amazon S3 にアップロードしていきます。(アップロードする画像はキューに入れられ、順番に処理されていくようです。)

画像ファイル毎に Amazon S3 へのアップロード状況が記録され、正常に保存された画像ファイルの URL は次回に表示される時から Amazon S3 の URL に置換えられます。

非常に簡単に使えて効果の高いプラグインなのですが、このブログの環境ではいくつか問題がありました。

画像ファイルが完全URLで指定されている事が想定されている。

このプラグインでは画像ファイルへの URL が http:// から始まる完全 URL で書かれている事を想定しているのですが、当ブログでは、ある記事では完全 URL、別の記事ではルート相対URL、という感じで記事ごとに画像の URL の書き方がバラバラでした。
このため、画像への URL を探す正規表現にマッチしない画像がたくさん出てきてしまいました。

メディアライブラリから画像を「投稿に挿入」していれば、完全URLで書かれるので普通に使っていれば問題は無かったはずなんですが。。。

しかたがないので、これはプラグインのソースに手を入れてルート相対URLでも書き換えられるように修正しました。

CloudFront の URL に対応していない。

このプラグインは画像ファイルのURLを http://>バケツ名<.s3.amazonaws.com という場所に変更するのですが、私のデータは Amazon S3 の中でも北米東海岸のサーバに置かれているため、ファイルの送信にちょっと時間がかかります。どうせなら国内の CloudFront のサーバから配信したいので、以下のようにソースを修正しました。wp-cdn.bluegold.me はヂストリビューションに付けた CNAME です。

*** 212,218 ****
  if (file_exists ( $mediaInfo [ 'cache' ] ) === TRUE) {
          $fileContents = file_get_contents ( $mediaInfo [ 'cache' ] );
          if ($fileContents == 'done') {
!           $cdnUrl = "http://{$this->s3BucketName}.s3.amazonaws.com/" . $mediaInfo [ 'path' ];
            $the_content = str_replace ( $mediaInfo [ 'url' ], $cdnUrl, $the_content );
          }
  } else {
--- 214,221 ----
 if (file_exists ( $mediaInfo [ 'cache' ] ) === TRUE) {
         $fileContents = file_get_contents ( $mediaInfo [ 'cache' ] );
         if ($fileContents == 'done') {
! //       $cdnUrl = "http://{$this->s3BucketName}.s3.amazonaws.com/" . $mediaInfo [ 'path' ];
!           $cdnUrl = "http://wp-cdn.bluegold.me/" . $mediaInfo [ 'path' ];
             $the_content = str_replace ( $mediaInfo [ 'url' ], $cdnUrl, $the_content );
         }
 } else {

このプラグインは非常に簡単に使えるので、Amazon S3 のアカウントを持っている人にはお勧めできますね。

]]>
1
bg http://blog.bluegold.me <![CDATA[nginx を SMF で管理する]]> http://blog.bluegold.me/?p=500 2010-08-23T17:42:26Z 2010-08-02T16:36:59Z もう1年以上前に書いていた下書きをようやく公開。

前回(と言っても1年半前か) までで nginx と PHP の fast-cgi のビルドと設定が終わったので、OS の起動時に自動的に起動するようにサービスとして登録を行います。

OpenSolaris ではサービスの管理に SMF という仕組みを使用しています。SMF はサービスの依存関係を記述できたり、サービスの起動を監視して自動的に再起動してくれたりと、Linux などで使われている /etc/init.d の rc スクリプトに比べるとメリットがありますが、コマンドが独自だったり、自分で SMF にサービスを登録するには manifest と呼ばれる XML ファイルを書く必要があるので、慣れるまではハードルがあります。(この辺は Mac OS X の launchd と似ている。)

以下が、私が nginx を管理するために作成した nginx.xml です。

<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='export'>
  <service name='network/nginx' type='service' version='0'>
    <create_default_instance enabled='true'/>
    <single_instance/>
    <dependency name='fs' grouping='require_all' restart_on='none' type='service'>
      <service_fmri value='svc:/system/filesystem/local'/>
    </dependency>
    <dependency name='net' grouping='require_all' restart_on='none' type='service'>
      <service_fmri value='svc:/network/loopback'/>
    </dependency>
    <exec_method name='start' type='method' exec='/usr/local/sbin/nginx -c /usr/local/conf/nginx.conf' timeout_seconds='60'>
      <method_context working_directory='/usr/local/logs'>
        <method_credential user='root' group='root'/>
        <method_environment>
          <envvar name='PATH' value='/usr/bin:/bin:/usr/local/bin'/>
        </method_environment>
      </method_context>
    </exec_method>
    <exec_method name='stop' type='method' exec=':kill' timeout_seconds='60'>
      <method_context/>
    </exec_method>
  </service>
</service_bundle>

このファイルを以下のように SMF に登録します。

# svccfg -v import nginx.xml

同様に PHP の FastCGI のプロセスも SMF に登録します。

<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="manifest" name="php-fcgi">
 <service name="network/php-fcgi" type="service" version="0">
   <create_default_instance enabled="true"/>
   <single_instance/>

   <dependency name="net" grouping="require_all" restart_on="none" type="service">
     <service_fmri value="svc:/network/loopback"/>
   </dependency>

   <exec_method name="start" type="method" exec="/usr/local/sbin/php-fcgi.sh" timeout_seconds="60">
     <method_context working_directory="/usr/local/www">
      <method_credential user="php" group="webservd" privileges="basic,net_privaddr"/>
      <!--method_credential user="root" group="root" /-->
       <method_environment>
         <envvar name="PATH" value="/usr/php/5.2/bin:/usr/local/sbin:/usr/bin:/bin" />
       </method_environment>
     </method_context>
   </exec_method>

    <exec_method name='stop' type='method' exec=':kill' timeout_seconds='60'>
      <method_context/>
    </exec_method>

 </service>
</service_bundle> 

この xml も同じように svccfg コマンドで登録します。

起動用の shell スクリプトはこちらのサイトのものを、ほぼそのまま使っています。

#!/bin/bash

LC_ALL=ja_JP.UTF-8

#FastCGI Webserver path
FCGI_WEB_SERVER_ADDRS="127.0.0.1"

## ABSOLUTE path to the PHP binary
PHPFCGI="/usr/php/bin/php-cgi"

## tcp-port to bind on
FCGIPORT="9000"

## IP to bind on
FCGIADDR="127.0.0.1"

## number of PHP children to spawn
PHP_FCGI_CHILDREN=5

## number of request before php-process will be restarted
PHP_FCGI_MAX_REQUESTS=1000

# allowed environment variables sperated by spaces
ALLOWED_ENV="PATH"

## if this script is run as root switch to the following user
USERID=webservd

################## no config below this line

ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_CHILDREN"
ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS"
ALLOWED_ENV="$ALLOWED_ENV FCGI_WEB_SERVER_ADDRS"

if test x$UID = x0; then
  EX="/bin/su -m -c \"$PHPFCGI -q -b $FCGIADDR:$FCGIPORT\" $USERID"
else
  EX="$PHPFCGI -b $FCGIADDR:$FCGIPORT"
fi

echo $EX

# copy the allowed environment variables
E=

for i in $ALLOWED_ENV; do
  E="$E $i=${!i}"
done

# clean environment and set up a new one
nohup env - $E sh -c "$EX" &

サービスが SMF に登録できれば、svcadm コマンドで起動停止を切り替える事ができます。

起動

# svcadm enable nginx
# svcadm enable php-fastcgi

停止

# svcadm disable nginx
# svcadm disable php-fastcgi
]]>
0
bg http://blog.bluegold.me <![CDATA[VeriSign のタイムスタンプ証明書]]> http://blog.bluegold.me/?p=472 2010-08-26T14:38:53Z 2010-07-31T06:08:05Z VeriSign のタイムスタンプ証明書の有効期限について気になる今日この頃。

VeriSign のAuthenticode用の証明書を使っています。 これは .exe や .cab ファイルなどにコードサイニングを行うためのマイクロソフトの仕様に沿った証明書で、昔は ActiveX 専用なイメージでしたが、最近は IE がファイルをダウンロードする時にも検証されるので、それなりに重要なものだったりします。

基本的に証明書の有効性は証明書自身の有効期間の間しか確認できません。(その為の有効期間なわけですから当然ですが) しかし、例えばインストーラを作成してウェブに公開するような時に、コードサイン用証明書の有効期限が切れて更新するたびに、公開している全てのファイルに対して署名をやり直すのは大変です。

こういった事にならないように、通常は署名時にタイムスタンプを付けておきます。タイムスタンプは「あるファイルがタイムスタンプをつけた時点で存在し、タイムスタンプをつけてからは変更されていない」事を証明するためのサービスで、デジタル署名にタイムスタンプがついている場合は、署名した証明書の有効期限が過ぎた後も、有効性を確認することができます。

ただ、タイムスタンプ自身も電子署名の一種なので、証明書の有効期限が存在します。この有効期限を過ぎるとタイムスタンプの有効性が確認できなくなるので、有効期間の残りが少なくなってくると意味がなくなってしまいます。

ようやく本題。
VeriSign でも http://timestamp.verisign.com/scripts/timstamp.dll というURLでタイムスタンプサーバを 公開していているのですが、そこでタイムスタンプの署名に使われる証明書の有効期限は以下のようになっています。

真ん中の画像の「VeriSign Time Stamping Services Signer – G2」がタイムスタンプ用の証明書で、有効期限は 2007/06/05 から 2012/06/15 までとなっています。

これを書いているのが、2010/07/31 なので、もう残りが2年ない。。。
有効期限の残りが2年を切る前に流石に更新されるか、少なくともロードマップのアナウンスがあるかと思ってたんですが、何もなかったんですよね。

元から有効期限が5年しかないので、毎年更新するくらいでちょうどいいと思うんですが。

]]>
0
bg http://blog.bluegold.me <![CDATA[VisualStudio で IE8 をデバッグするには]]> http://blog.bluegold.me/?p=464 2011-01-27T18:44:19Z 2010-06-10T08:51:45Z IE8 上での開発でちょっとハマッタのでメモ

ActiveX や ToolBar(Browser Object) のデバッグを行うさいは、IE をデバッギー(debugee)としてVisual Studio からアタッチするのですが、今日久しぶりにやってみたら設定したブレークポイントで止まってくれません。

Visual Studio の設定ミスかと、しばらく試行錯誤しているうちに iexplore.exe のプロセスが複数いることに気がつきました。そこで、ようやく IE8 からタブごとに別プロセスで実行されることを思い出しました。

「じゃあ、自分がデバッグしたいプロセスを探してアタッチすれば。。。」と思ったのですが、毎回そんなことをやるのはさすがにめんどくさいので、Google先生に聞いてみました。

で、このサイトで解決策を発見。

IE8 がタブごとに独立したプロセスを生成しないようにレジストリの値を変更します。

  • キー: HKCU\Software\Microsoft\Internet Explorer\Main
  • 名前: TabProcGrowth (DWORD)
  • 値: 0

Windowsネタを書くのははじめてなのか。。。

]]>
0
bg http://blog.bluegold.me <![CDATA[Snow Leopard で IP alias を設定する]]> http://blog.bluegold.me/?p=450 2010-08-23T18:04:19Z 2010-06-04T01:57:32Z

Snow Leopard でNICにIP aliasを設定する方法のメモ。

IP alias の追加

sudo ifconfig en0 alias 192.168.0.1 255.255.255.0

IP alias の削除

sudo ifconfig en0 -alias 192.168.0.1

ついでに Linux と OpenSolari での設定方法もメモ。

Linux の場合

IP alias の追加

# /sbin/ifconfig eth0:1 192.168.0.1/24

IP alias の削除

# /sbin/ifconfig eth0:1 down

OpenSolaris の場合

IP alias の追加

pfexec ifconfig gbe0:1 plumb
pfexec ifconfig gbe0:1 192.168.0.5 netmask 255.255.255.0 up

IP alias の削除

pfexec ifconfig gbe0:1 down
pfexec ifconfig gbe0:1 unplumb

Snow Leopard のやり方のほうが、何個目のエイリアスなのかを考えなくてもいいので楽なのかなぁ。
エイリアス単位でインターフェースの UP/DOWN はできなそうだけど。

]]>
0
bg http://blog.bluegold.me <![CDATA[Redmine を監視して再起動する]]> http://blog.bluegold.me/?p=444 2010-06-04T02:01:13Z 2010-04-20T16:35:50Z

正確には Redmine が原因なのかどうかは判明していませんが、OpenSolaris 上に構築した Redmine が起動後何時間かすると500 Internal Errorを返すようになってしまいました。

Redmine は以下のような環境で動かしています。

  • Redmine 0.9.3
  • OpenSolaris 2009.06
  • Ruby 1.8.7-p249
  • Rails 2.3.5
  • Unicorn 0.97.0
  • nginx 0.7.65

Ruby は /opt/sunstudio12.1/bin/cc(Sun Studio Express 12)でビルドしています。

OpenSolaris に付属の /usr/bin/ruby を使っていた時には問題なく動作していたんですが、Redmine 0.9.3 にバージョナップした所、致命的な問題が発生したため、Ruby を自分でビルドするように変更していました。

落ちているの気がついたら手動で再起動をしていたのですが、さすがにメンドウになってきたのでスクリプトを書きました。

#!/bin/sh

while `/bin/true`
do
    http_code=`curl --insecure -w "%{http_code}" -s -o /dev/null https://redmine/login`
    ts=`date +"%Y/%m/%d %H:%M:%S"`

    if [ $http_code -eq 200 ]; then
        echo $ts OK
        sleep 300
        continue
    fi

    cd /var/www/redmine
    pid=`cat tmp/pids/unicorn.pid`

    kill -USR2 $pid
    sleep 5
    kill $pid

    echo $ts unicorn $pid reloaded.
done

exit 0

手順としては、5分おきに curl で HTTP のステータスコードのみを受け取り、200 OKが帰ってこない場合は再起動、という流れです。

Unicorn は SIGUSR2 を送ると自分自身を fork() してから終了するはずなのですが、終了せずに残るので子プロセスの起動を待ってから SIGTERM を送っています。

とりあえずは、これで気にはならなくなりましたが。。。

そのうち、God あたりに切り替えよう。

]]>
0
bg http://blog.bluegold.me <![CDATA[Xenのディスクイメージをマウントする]]> http://blog.bluegold.me/?p=410 2010-03-24T07:10:19Z 2010-03-05T13:21:47Z XenのイメージファイルをLinuxからマウントする方法のメモ

Xenのディスクイメージファイルは以下のように固定ディスクをそのままファイルに移したような構造になっています。

# file test.img
test.img: x86 boot sector; partition 1: ID=0x83, active, starthead 1, startsector 63, 208782 sectors; partition 2: ID=0x82, starthead 0, startsector 208845, 2104515 sectors; partition 3: ID=0x83, starthead 0, startsector 2313360, 18651465 sectors, code offset 0x48

なので、基本的にはループバック・デバイスとしてマウントする事が可能です。
ただし、ディスクイメージはパーティションに区切ってあると思いますので、その分にひと手間ひつようです。

基本的な作業の流れは以下のとおり。

  1. losetup コマンドでディスクイメージファイルをループバック・デバイスに割り当てる。
  2. kpartx コマンドでディスクイメージ内の各パーティションにデバイスファイルを割り当てる。
  3. 必要なパーティションのデバイスファイルを mount コマンドでマウントする。

losetup コマンドでディスクイメージファイルをループバック・デバイスに割り当てる。

losetup -fコマンドで空いているループバック・デバイスを探して、そのデバイスにイメージファイルを割り当てます。

# losetup -f
/dev/loop0
# losetup /dev/loop0 /var/lib/xen/images/test.img
# losetup -a
/dev/loop0: [0900]:153944114 (/var/lib/xen/images/test.img)

kpartx コマンドでディスクイメージ内の各パーティションにデバイスファイルを割り当てる。

ループバック・デバイスに割り当てた仮想ディスクにパーティションの状況をfdiskコマンドで調べます。

# fdisk /dev/loop0

このディスクのシリンダ数は 1305 に設定されています。
間違いではないのですが、1024 を超えているため、以下の場合
に問題を生じうる事を確認しましょう:
1) ブート時に実行するソフトウェア (例. バージョンが古い LILO)
2) 別の OS のブートやパーティション作成ソフト
   (例. DOS FDISK, OS/2 FDISK)

コマンド (m でヘルプ): p

Disk /dev/loop0: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders
Units = シリンダ数 of 16065 * 512 = 8225280 bytes

デバイス Boot      Start         End      Blocks   Id  System
/dev/loop0p1   *           1          13      104391   83  Linux
/dev/loop0p2              14         144     1052257+  82  Linux swap / Solaris
/dev/loop0p3             145        1305     9325732+  83  Linux

コマンド (m でヘルプ): q

3つのパーティションが存在することが確認できます。
kpartx -aでそれぞれのパーティションをデバイスファイルに割り当てます。
/dev/mapperディレクトリの下に新たなデバイスファイルが作成されます。

# kpartx -a /dev/loop0
# ls -l /dev/mapper/
合計 0
crw------- 1 root root  10, 62  2月 24 00:07 control
brw-r----- 1 root disk 253,  0  3月  5 22:07 loop0p1
brw-r----- 1 root disk 253,  1  3月  5 22:07 loop0p2
brw-r----- 1 root disk 253,  2  3月  5 22:07 loop0p3

仮想ディスクでLVMを使っているとここから先がめんどくさいので、私はXenの仮想ディスクではLVMは使いません。

必要なパーティションのデバイスファイルを mount コマンドでマウントする。

あとは通常のディスクと同じようにマウントするだけです。

# mount -t ext3 /dev/mapper/loop0p1 /mnt/tmp
# ls -l /mnt/tmp
-rw-r--r-- 1 root root  952782 11月  4 08:46 System.map-2.6.18-164.6.1.el5xen
drwxr-xr-x 2 root root    1024 11月  9 15:51 grub
-rw------- 1 root root 2383144 11月  9 15:51 initrd-2.6.18-164.6.1.el5xen.img
drwx------ 2 root root   12288  6月 17  2009 lost+found
-rw-r--r-- 1 root root   80032  3月 13  2009 message
-rw-r--r-- 1 root root  107413 11月  4 08:47 symvers-2.6.18-164.6.1.el5xen.gz
-rwxr-xr-x 1 root root  817164 11月  4 09:53 xen-syms-2.6.18-164.6.1.el5
-rw-r--r-- 1 root root  375762 11月  4 06:11 xen.gz-2.6.18-164.6.1.el5

使い終わった後の手順

必要なくなった仮想ディスクを開放するには、逆の手順で行います。

# umount /mnt/tmp
# kpartx -d /dev/loop0
# ls -l /dev/mapper/
合計 0
crw------- 1 root root 10, 62  2月 24 00:07 control
# losetup -d /dev/loop0
# losetup -a
# losetup -f
/dev/loop0

]]>
0
bg http://blog.bluegold.me <![CDATA[OpenSolarisのftpdでファイル一覧の表示に問題]]> http://blog.bluegold.me/?p=400 2010-04-08T15:47:18Z 2010-02-22T17:31:57Z 外部のデザイナーさん(HiGash.Net の中の人だけど)と仕事をしたときの話です。

私の構築したステージング用のサーバにデザイナーさんの作ったコンテンツを置いてもらう必要があったので、「sftp でいいですか?」と聞いたら「ftpの方がいい」と言われたので、急遽 ftp サーバの用意をすることになりました。

軽く「いいよ」と答えたものの、自分で最後に ftpd をたてたのはもう10年近く前のことで何も覚えてません。
Solaris なのでSMFで管理されているftpdがあるだろうと思い、試してみると

$ pfexec svcadm enable ftp
$ svcs -l ftp
fmri         svc:/network/ftp:default
name         FTP server
有効         true
状態         online
next_state   none
state_time   Tue Feb 23 02:02:15 2010
リスタータ   svc:/network/inetd:default
contract_id

無事に起動できました。簡単簡単。

念のため、ファイアウォール越しに ftp コマンドで接続テストを行い、passive mode が on でも off でも問題がなかったので、使ってもらいました。

しかし、しばらくすると「FTPサーバに接続は出来たけど、ファイルが何も表示されない」との報告が。。。

使っている ftp のクライアントソフトはFFFTPだという事なので、同じトラブルにあっている人がいるだろうと思いGoogleに聞いてみたところ、このページで原因と思われる記述を発見しました。

「タイムスタンプに含まれる日本語文字列の処理の問題」

ftpコマンドで接続して確認すると、ファイルの更新日付が確かに日本語で返ってきています。これなら in.ftpd のロケールを変えてあげれば問題は解決しそうです。

また、Googleに聞いてみるとこのページに回答がそのまま書いてありました。

SMF なので svccfg を使うのかと思ったら、in.ftpd は inetd に管理されているので、inetadmというコマンドを使うんですね。初めて知った。

以下のコマンドで、FFFTPでも正常にファイル一覧が表示されるようになりました。

$ pfexec inetadm -m ftp inherit_env=FALSE
$ pfexec svcadm restart ftp

]]>
0
bg http://blog.bluegold.me <![CDATA[nginx: SNI拡張を使ってVirtualHostでTLSを設定]]> http://blog.bluegold.me/?p=376 2010-02-22T17:33:12Z 2010-02-14T14:36:17Z 前回の記事でSNI(Server Name Indication)拡張を有効にしたnginxのバイナリを作成したので遊んでみました。SNI拡張は、個々の仮想ホスト(VirtualHost)で独自のサーバ証明書を利用するために作られた TLSv1 の拡張仕様です。

TLSやSSLを使ったウェブサーバーでは一般的には仮想ホストは使えない、という事になっています(何事にも例外はありますが。)仮想ホストは HTTP のリクエストヘッダの Host フィールドの値を元に振り分けられますが,HTTPのリクエストを出すよりも手前の TLS/SSL のハンドシェイク時にサーバ証明書の検証が行われるので,クライアントが接続しようとしているホスト名とサーバ証明書のホスト名が異なってしまい,不正な証明書と表示されてしまいます。

SNIは接続しようとしているホスト名を、クライアントからサーバに伝えるための仕様です。(ホスト名はハンドシェイク前に伝えないと行けないので、平文で送られる事になりますが。。。)これ自体は素晴らしいのですが,Windows XP の IE がサポートしていないので今ひとつ広まっていません。

まずは SNI を使わないで仮想ホストを設定する場合の例です。

ssl_certificate server_cert.pem;
ssl_certificate_key server_cer.key;
server {
    port 443;
    ssl on;
    server_name host1.example.com;
}
server {
    port 443;
    ssl on;
    server_name host2.example.co.jp;
}

サーバ証明書は1枚しか指定できないので,server_cert.pem には host1.example.com と host2.exacmple.co.jp の双方が記述されている必要があります。ホストが同一のドメインに存在する場合はワイルドカード証明書を使う方法もありますが,例のようにドメインが異なる場合は双方のホスト名をCNもしくはsubjectAltNameに記述します。この方法では仮想ホストが増える場合は証明書を発行し直す必要があります。

次に SNI を使う場合の例です。

server {
    port 443;
    ssl on;
    ssl_certificate host1.example.com.pem;
    ssl_certificate_key host1.example.com.key;
    server_name host1.example.com;
}
server {
    port 443;
    ssl on;
    server_name host2.example.co.jp;
    ssl_certificate host2.example.co.jp.pem;
    ssl_certificate_key host2.example.co.jp.key;
}

仮想ホスト毎に証明書が指定する事ができるようになります。

実際に SNI をサポートしている Firefox などのブラウザでアクセスすると、それぞれ異なる証明書を持つ事が確認できます。

ただ、現在の nginx に固有の問題かもしれませんが,仮想ホスト毎にクライアント証明書による認証の有無を切り替えるのは出来ないみたいです。ssl_verify_client off;な設定の仮想ホストが1つでもあると,クライアント認証を行う仮想ホストに対してもクライアント証明書が送られません。

クライアント認証が必要ない仮想ホストに対してもssl_verify_client optional;を指定すると大丈夫なようですが。(Nginx の Wikiの説明ではoptional ではなく、askになっているので注意が必要です。)

]]>
0
bg http://blog.bluegold.me <![CDATA[Mercurial: nginx で hgwebdir.fcgi のセットアップ]]> http://blog.bluegold.me/?p=379 2010-02-14T14:38:38Z 2010-02-07T15:04:09Z Mercurial 付属の hgwebdir.fcgi を nginx で動かすメモ

CVS(やSubversion)をバージョン管理システムに使っていた頃はリポジトリの情報を見るのにViewVCを使っていましたが、ViewVCはMercurialをサポートしていません。Mercurial にはウェブ用の管理画面(hgweb/hgwebdir)が付属しているので、別のツールを使うニーズが少ないんでしょうね。

Mercurial のリポジトリ毎に対応する Redmine のプロジェクトが存在するので、そちらを見ればおおよその事は分かるのですが、Redmineのリポジトリブラウザはブランチを意識して作られていないので不便といえば不便です。

hgwebの事は Mercurial への移行を検討していたときにも調べていたんですが、Django, flup, setuptools, ez_setup.py, easy_install, .. とPythonに不慣れな人間にはなじみのない単語が続々と出てきたので、ちょっと敬遠していましたが、ちょっと時間が取れたのでチャレンジしてみました。

hgwebdir のセットアップをする前に必要なソフトウェアのインストールを行います。環境は OpenSolaris 2009.06 で、可能な限り pkg を使ってインストールしていきます。インストールしたのは以下のパッケージです。

SUNWPython26
SUNWPython26-extra
SUNWpython26-setuptools

OpenSolaris 2009.06 のパッケージ管理システムにも Mercurial はありますが、バージョンが 1.1.2 と古く、クライアントの環境と合わないので、最新バージョンを easy_install からインストールします。

$ pfexec easy_install Mercurial
$ hg --version
Mercurial Distributed SCM (version 1.4.2)

Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

次に flup が必要だそうなのでインストールします。

$ pfexec easy_install flup

hgwebdir を FastCGI で動作させるのにはいろいろな方法があるらしいのですが、Python特有のやり方はよく分からないので、lighttpd の spawn-fcgiを使いました。インストールは以下の通り簡単です。

$ wget http://www.lighttpd.net/download/spawn-fcgi-1.6.3.tar.gz
$ gzip -dc spawn-fcgi-1.6.3.tar.gz | tar xvf -
$ cd pawn-fcgi-1.6.3
$ ./configure
$ make
$ pfexec make install

ここまででようやく下準備がおわりました。
hgwebdir.fcgi は /usr/demo/mercurial/hgwebdir.fcgi をコピーして使っています。
UTF-8 で表示するために、HGENCODING の設定を行う部分のコメントをはずしています。

os.environ["HGENCODING"] = "UTF-8"

hgweb.config は単純です。

[paths]
/ = /path/to/repos/*

これを以下のようなスクリプトで起動しています。

#!/bin/sh

LANG=ja_JP.UTF-8
export LANG

FCGI=/opt/local/bin/spawn-fcgi
exec $FCGI -s /tmp/.fcgi_hgwebdir -G webserved -M 0660 ./hgwebdir.fcgi

nginx の設定ファイルは以下のようになりました。
初めて try_files を使ってみましたが、設定がとてもシンプルになりますね。
hgwebdir は PATH_INFO を利用してブラウズするリポジトリを探すようなので、その部分の置き換えにちょっと手を入れています。

server {
    listen       80;
    server_name  hg.example.com;
    root   /path/to/public;
    index  index.html;

    access_log  /var/log/nginx/hg-access.log  main;

    location / {
        try_files $uri @hgweb;
    }

    location @hgweb {
        fastcgi_pass   unix:/tmp/.fcgi_hgwebdir;
        fastcgi_read_timeout    5m;
        set $path_info "";
        if ($fastcgi_script_name ~ "^/(.*)$") {
            set $path_info $1;
        }
        fastcgi_param PATH_INFO $path_info;
    }
}

]]>
0
bg http://blog.bluegold.me <![CDATA[OpenSolarisで64bitのnginxをビルドする]]> http://blog.bluegold.me/?p=362 2010-02-08T00:16:26Z 2010-02-04T09:05:29Z

nginxの新しいバージョン(0.7.65)がリリースされていたので,バージョンアップしてみました。

しばらく前に見つかっていたSSLの脆弱製の実験をやろうと、久しぶりに SSL を有効にしたバイナリを作ろうとしたのですが,オプションの設定の仕方を忘れていて苦労しました。また、忘れても大丈夫なようにメモ。

OpenSolaris 2009.06 に含まれるOpenSSLは 0.9.8a と古いので、現時点での最新バージョンであるopenssl-0.9.8lをダウンロードしてきて使いました。今回はSNI(Server Name Indication)を有効にしたいのでenable-tlsextオプションを渡しています。

./config --prefix=/usr/local no-shared enable-tlsext
make
pfexec make install

これだけでもビルドは出来るのですが,OpenSolaris 2009.06 のデフォルトの GCC 3.2.3 ではなく新しい /usr/bin/gcc-4.3.2 を使いたいので,少し手を入れています。

export CC=/usr/bin/gcc-4.3.2
export CFLAGS='-DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -march=native -O3 -Wall -DL_ENDIAN -DMD32_REG_T=int -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM' 
./Configure --prefix=/usr/local no-shared enable-tlsext solaris64-x86_64-gcc
make
pfexec make install

export CC=/usr/bin/gcc-4.3.2した後にconfigスクリプトを実行すると,solaris64-x86_64-gcc-4.3.2 みたいな os:compiler になってエラーになってしまうんですよね。回避方法を探すのに手間取ってしまいました。

次に nginx のビルドですが,普通に configure を実行すると 32bit のバイナリが出来てしまいますので、gcc に渡すオプションも configure に渡します。

./configure --prefix=/usr/local --with-http_stub_status_module --with-http_gzip_static_module --with-http_ssl_module --with-cc=/usr/bin/gcc-4.3.2 --with-cc-opt='-m64 -march=native -O3 -I/usr/local/include ' --with-cpu-opt=amd64 --with-ld-opt='-m64 -L/usr/local/lib -L/usr/lib/amd64'
make
pfexec make install

ビルドした内容を確認

$ file /usr/local/sbin/nginx
/usr/local/sbin/nginx:  ELF 64-bit LSB executable AMD64 Version 1, dynamically linked, stripped

$ /usr/local/sbin/nginx -V
nginx version: nginx/0.7.65
built by gcc 4.3.2 (GCC) 
TLS SNI support enabled
configure arguments: --prefix=/opt/local --with-http_stub_status_module --with-http_gzip_static_module --with-http_ssl_module --with-cc=/usr/bin/gcc-4.3.2 --with-cc-opt='-m64 -march=native -O3 -I/usr/local/include' --with-cpu-opt=amd64 --with-ld-opt='-m64 -L/usr/local/lib -L/usr/lib/amd64'

SNIも有効になっています

]]>
0
bg http://blog.bluegold.me <![CDATA[Mercurial で削除してしまったファイルを元に戻す]]> http://blog.bluegold.me/?p=348 2010-02-07T15:59:36Z 2010-02-01T17:43:10Z

3ヶ月ほど前に、10年以上使い続けたCVSからMercurialにソース管理を移行しました。(Subversion は手になじまなかった。)

移行して不便に感じるのはViewVCが使えなくなった事くらいで、普段はあまり違いは感じていませんが、1つだけ直感的にやり方が分からなくて困る事があります。

ワーキングディレクトリで作業中に誤って必要なファイルを削除してしまった場合、例えば

$ ls -l
total 8
-rw-r--r--  1 user  staff  1345 Jan 16 22:33 Makefile
drwxr-xr-x  5 user  staff   170 Jan 16 22:45 help/
drwxr-xr-x  5 user  staff   170 Jan 16 22:33 tutorial/
$ rm Makefile

としてしまった場合、必要なファイルが存在しない事は hg status コマンドで調べる事ができます。

$ hg status
! Makefile

CVS(やSubversion)では、誤って削除したファイルはcvs update(svn up)で元に戻すことができますが、Mercurial ではそうはいきません。

$ hg update
ファイル状態: 更新数 0、マージ数 0、削除数 0、衝突未解決数 0
$ ls -l
total 0
drwxr-xr-x  5 user  staff  170 Jan 16 22:45 help/
drwxr-xr-x  5 user  staff  170 Jan 16 22:33 tutorial/

このように削除されたファイルはそのままです。

Mercurial では update コマンドはワーキングディレクトリのリビジョンを変更するコマンドなので、この動きで正しいらしいのですが、CVS等から乗り換えてくるとちょっとビックリします。

このような場合はhg revertを使うのが正しいらしいです。

$ hg revert Makefile
$ ls -l
total 8
-rw-r--r--  1 user  staff  1345 Feb  2 02:41 Makefile
drwxr-xr-x  5 user  staff   170 Jan 16 22:45 help/
drwxr-xr-x  5 user  staff   170 Jan 16 22:33 tutorial/
]]>
0
bg http://blog.bluegold.me <![CDATA[tcpdump でキャプチャしたファイルを WireShark で解析]]> http://blog.bluegold.me/?p=337 2010-02-02T15:39:44Z 2010-01-29T16:31:09Z

WireSharkを使ってダンプを解析するためのキャプチャファイルをtcpdumpで保存するためのオプションを毎回忘れてしまうのでメモ。

tcpdump -n -i en0 -s 0 -w dumpfile.cap [filter]

tcpdump -w filenameだけでも、キャプチャファイルは作れるが、デフォルトではキャプチャ用のバッファ(snaplen)が 68バイトと小さく(TCP のヘッダー分のサイズらしい)、あふれたデータを取りこぼしてしまいます。tcpdump で見ている分には必要の無いデータですが、WireShark で「Follow TCP Stream」を見ようとした時に壊れていたりします。

そこでオプション ‘-s’ を指定して snaplen のサイズを大きく設定しています。(0は無制限、と言っても65535バイトくらいしか見た事ない)

(Open)Solarisの場合は悩む事無く、以下のように普通にファイルに保存するだけで大丈夫です。

snoop -r -d bge0 -o dumpfile.cap [filter]
]]>
1
bg http://blog.bluegold.me <![CDATA[Snow Leopard: crontab が編集できない]]> http://blog.bluegold.me/?p=319 2010-01-12T08:42:13Z 2010-01-05T03:30:39Z 昨年の後半は、勤めていた会社の経営が傾いたのをきっかけに、退職して新しい会社の立ち上げに参加したり、自分自身も引越しをしたりと、なかなかブログを更新する時間が取れませんでした。新年になり、ようやく全てが落ち着いてきました。

仕事のほうも、しばらくは自宅で開発作業を行うので、今までよりはブログに時間をかけられるんじゃないかなぁ。

自宅に仕事の環境を整えるために、年末年始は4台のPC(PCサーバ2台を含む)のセットアップを行っていました。4台といっても中身は Xen, Solaris Zone, VirtualBox で仮想化してるので時間はかかりました。

OpenSolaris でファイルサーバを作ったので、MacBook の開発環境のバックアップも定期的にそちらに残そうとcrontab -eで編集して保存したところ、意外なエラーが帰ってきました。

crontab: temp file must be edited in place

これまでも Mac で crontab の編集は行っていましたが、エラーになったのは初めてです。

メッセージからすると、vi で編集後のファイルの i-node が変わっているのが原因っぽいですが、.vimrc はもう3年くらいずっと使っているもので大きく変えたりはしていません。Google に聞いてみると以下の設定を追加すれば大丈夫だとの記述を発見しました。

set nowritebackup

が、私の環境ではこの方法ではダメでした。

次に見つけたこのサイトを参考にしたところ、crontab の編集ができるようになりました。

set backupskip=/tmp/*,/private/tmp/*

/private/tmp があるので、この人も Mac を使っているんでしょうね。

]]>
0
bg http://blog.bluegold.me <![CDATA[zfsとタイムスライダーでハマった事]]> http://blog.bluegold.me/?p=305 2010-08-23T17:46:43Z 2009-09-29T10:09:41Z

今回の秋の連休は有休も使って9連休にしていました。
休み明けのボケた頭では仕事にならないので、午前中は開発用サーバたちのパッケージのアップデートをしていたところ、その中の1つにログインできませんでした。

そのホストは OpenSolaris 2009.06 の中に立てた Linux Branded Zone(BrandZ と書いた方がいいのかな)にインストールした CentOS3 でした。Solaris の Zone なので、ホストOS の方からは自由に Linux のファイルシステムに入っていけます。中のファイルを調べたところ、ログファイルの1つが46GB以上に肥大化してしまってディスクの残り容量が無くなってしまっているのが原因のようでした。

これなら、巨大化したログファイルを削除すれば問題解決だな、と軽い気持ちでrm ログファイル を実行したところ、意外な結果が戻ってきました。

cannot delete file: no space left on device.

ディスクに空き領域が無いからファイルを消したいのに、空き領域が無いからファイルを消せないと言われても。。。

ファイルシステムが壊れているのかと zpool scrub を実行してもエラーは無し。

Google 先生に質問してみたところ、zfs の既知のバグのようでした。曰く、ディスクの残り容量が無くなるとスナップショットが存在するファイルは削除できない。スナップショットの無いファイルを消して空き領域を作るか、スナップショットを削除すればよいようです。

が、zfs は使っているもののスナップショットなんて取ったことはありません。
不思議に思い zfs list -t snapshotを実行したところ、以下のように大量のスナップショットが存在していました。

rpool/ROOT/OpenSolaris-200906-090928@2009-07-10-00:41:02                      17.4M      -  2.85G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-10-17:54     39.5K      -  6.93G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:weekly-2009-07-10-17:54      40K      -  6.93G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:monthly-2009-07-10-17:54   1.11M      -  6.93G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-11-00:00     3.67M      -  6.94G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-12-00:00     2.86M      -  7.14G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-13-00:00     5.29M      -  7.14G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-14-00:00     21.1M      -  7.26G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:weekly-2009-07-15-00:00    1.29M      -  7.26G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-16-00:00      528K      -  7.26G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-17-00:00     3.73M      -  7.26G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-18-00:00     1.67M      -  7.35G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-19-00:00     1.05M      -  7.35G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-20-00:00     1.08M      -  7.35G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-21-00:00     1.22M      -  7.35G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:weekly-2009-07-22-00:00    1.35M      -  7.35G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-23-00:00     1.35M      -  7.35G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-24-00:00     5.91M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-25-00:00     5.93M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-26-00:00     5.87M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-27-00:00     6.60M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:daily-2009-07-28-00:00     6.42M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:hourly-2009-07-28-11:00    1.73M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:hourly-2009-07-28-12:00    1.71M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:hourly-2009-07-28-13:00    1.93M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:hourly-2009-07-28-14:00    1.88M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:hourly-2009-07-28-15:00    1.79M      -  7.40G  -
rpool/ROOT/OpenSolaris-200906-090928@zfs-auto-snap:hourly-2009-07-28-16:00    1.26M      -  7.40G  -
...

犯人(?)は zfs の自動スナップショット機能でした。たしかにインストール直後に試しにタイムスライダーを有効にしたことがありましたが、こんな事になるとは。

大量のスナップショットを削除するようにシェルスクリプトを作成して問題は解決しました。ただ、ググっている時に「rpool の容量がなくなるとリブートもできなくなる」のような話もあったので、タイムスライダー(自動スナップショット)はちょっと恐くて使えないなぁ。

]]>
0
bg http://blog.bluegold.me <![CDATA[Linux Software RAID のディスク交換]]> http://blog.bluegold.me/?p=287 2010-08-23T17:48:06Z 2009-09-17T06:59:34Z

今月の頭にお客さんに収めたサーバ機のハードディスクが1週間で壊れたので、急遽ディスクのリプレースに行ってきました。今回のシステムは Linux の Software RAID で 2 本のディスクを使用して RAID1 を組んでいたのでデータ自体は無事だったのですが、手を離れたと思った瞬間のトラブルは心臓に悪いですね。

めったに行わない作業なので、自分用にメモ。

  • RHEL5 のレスキューCD でブート
    プロンプトで linux rescue と入力
    レスキューモードで起動する
  • 途中で、既にインストールされている Linux を検出するかを聞かれるので適当に答える
    (今回はオフラインで作業するのでマウントはさせませんでした)
  • 存在するディスクから RAIDデバイスを探す
    mdadm -Es > /etc/mdadm.conf
    
  • 見つけた物理デバイスから md デバイスを作成
    mdadm --assemble --scan
    
  • ディスクを不良ディスクに指定して取り除く
    mdadm --manage /dev/md0 --fail /dev/sdb1
    mdadm --manage /dev/md0 --remove /dev/sdb1
    
    mdadm --manage /dev/md1 --fail /dev/sdb2
    mdadm --manage /dev/md1 --remove /dev/sdb2
    
  • ここでシャットダウンしてディスク交換
  • 交換したら、先程と同様にレスキューモードで起動させる
  • 新しいディスクのパーティションを元からあるものと完全にあわせる
  • 新しいディスクをアレイに追加
    mdadm --manage /dev/md0 --add /dev/sdb1
    mdadm --manage /dev/md1 --add /dev/sdb2
    
  • ディスクをアレイに追加すると自動的にリビルドが始まるので、終わるまで待つ
    進行状況は下のようにして確認

    cat /proc/mdstat
    

リビルドが終わるまでの6時間を客先で待ち続けるのは辛かった。。。

]]>
0
bg http://blog.bluegold.me <![CDATA[Rails 2.3 のタイムゾーン]]> http://blog.bluegold.me/?p=278 2010-08-23T17:50:54Z 2009-09-14T11:08:34Z 2006年頃に Rails 1.2 で作成したアプリケーションを Rails 2.3 にアップグレードしています。

プログラムの移行自体は1週間ほどで完了したのですが、テストをしていてタイムゾーン関連の問題に遭遇しました。

データベースに有効期限を表すフィールドがあるのですが、1時間前から1時間後まで有効なレコードを作成して、現在が有効期間内かどうかを調べるテストが失敗したので問題に気がつきました。

Rails 2.x ではタイムゾーンが導入されたのは知っていたので、下のように設定を行っていました。

config.time_zone = 'Tokyo'
config.active_record.default_timezone = 'Tokyo'

しかし、ログを見ていると JST と UTC とタイムゾーンが混ざっているようだったので、単純なアプリを作成して調べてみました。すると、以下のような結果に

c = Sample.find(:first)
>> c[:created_at]
=> Mon, 24 Aug 2009 17:09:49 +0000
>> c.created_at
=> Tue, 25 Aug 2009 02:09:49 JST +09:00
>> c[:created_at].class
=> DateTime
>> c.created_at.class
=> ActiveSupport::TimeWithZone

同じフィールドでも [] メソッドでデータを取得するのと、フィールド名を指定して取得するので、クラスもタイムゾーンも異なるんですね。ちょっとビックリしました。

どこかにタイムゾーンを意識しないコードがあって、この2つを混同してしまってるんだろうな。
調べるのはメンドクサイな。

]]>
0
bg http://blog.bluegold.me <![CDATA[Snow Leopard で FreeMind]]> http://blog.bluegold.me/?p=264 2010-08-23T17:52:35Z 2009-09-09T03:00:00Z 前回の記事で問題となっていた、DVDの不良は週明けに渋谷のアップルストアに行って交換してもらいました。店員さんもなれた感じの対応でしたので、同じような返品交換がけっこうあったんでしょうね。「交換用の DVD もアップルストアで中身を開封して確認したわけではないので、これにも不具合が絶対に無いとは言いきれない」のような事を言っていたのでは、ある意味正直な店員さんだったんだろうな。

新しい DVD で再インストールしたところ、それまで起動できていなかった Mail, iPhoto, QuickSilver などは正常に使えるようになりました。普段使っているアプリに関しては(いくつか対応待ちのものがあるものの)移行は問題ないかと思っていましたが、昨日FreeMindが動かないのに気がつきました。仕事の議事録等は FreeMind で書くのが習慣となっていたので、このアプリが動かないとけっこう困ります。

動かないというのは正確ではなくて、実際には以下のようなダイアログが出てきました。
snow_leopard_rosetta_install_offlince
インターネットに接続している状態では、下のように Rosetta のインストールを促すようです。
snow_leopard_rosetta_install

なので、Rosetta をインストールしてしまえば解決なのですが、せっかく Snow Leopard に移行したんだから PowerPC のバイナリの無い環境にしたいので、解決方法を調べてみました。

エラーダイアログにある通り、問題は JavaApplicationStub が Universal Binary になっていない点にあります。JavaApplicationStub は文字通り Java で書かれたアプリケーションを Mac OS X のネイティブアプリのように見せるためのスタブとなる実行ファイルです。FreeMind.app の中から JavaApplicationStub を探して調べると、以下のようになっていました。

$ file FreeMind.app/Contents/MacOS/JavaApplicationStub 
FreeMind.app/Contents/MacOS/JavaApplicationStub: Mach-O executable ppc

やはり、ppc のバイナリしか入っていません。
Universal Binary な JavaApplicationStub も存在するはずなので、HDD の中を調べたところ以下の場所にありました。

$ file /System/Library/Frameworks/JavaVM.framework/Versions/A/Resources/MacOS/JavaApplicationStub
/System/Library/Frameworks/JavaVM.framework/Versions/A/Resources/MacOS/JavaApplicationStub: Mach-O universal binary with 3 architectures
/System/Library/Frameworks/JavaVM.framework/Versions/A/Resources/MacOS/JavaApplicationStub (for architecture x86_64):	Mach-O 64-bit executable x86_64
/System/Library/Frameworks/JavaVM.framework/Versions/A/Resources/MacOS/JavaApplicationStub (for architecture i386):	Mach-O executable i386
/System/Library/Frameworks/JavaVM.framework/Versions/A/Resources/MacOS/JavaApplicationStub (for architecture ppc7400):	Mach-O executable ppc

このファイルで FreeMind.app/Contents/MacOS/JavaApplicationStub を上書きしたところ、Rosetta 無しで起動するようになりました。

]]>
1
bg http://blog.bluegold.me <![CDATA[Snow Leopardのインストールエラー]]> http://blog.bluegold.me/?p=253 2010-02-14T14:53:05Z 2009-08-29T08:21:13Z 昨日は Snow Leopard の発売日だったので、会社帰りに渋谷のアップルストアに行って購入してきました。アップルストアはちょうど何かのイベントが始まるところだったらしく、人がいっぱいでレジがどこかも分からない状態でした。無事に購入して家に帰ったのですが、ちょっと予想外の事態になりました。

今までは新しいバージョンがでる度に Mac を買い替えていたので、OS のアップグレードは初めてですが、インストールは何回か行った事があるので、それほど心配はしていませんでした。

OSのアップグレードなので、何があっても大丈夫なように Time Machine でバックアップを取ります。それから SIMBL や MenuMeters などの怪しそうなソフトを止めてから、Snow Leopard の DVD を挿入してインストールを開始しました。

インストールが始まって「残り45分」と表示されたので、本でも呼んで時間をつぶしてようと思ったのですが、2分ほどでエラーが表示されて止まりました。

メッセージは以下の通りです。

install DVDが読み込めませんでした。
注意してディスクを清掃してから、もう一度インストールしてみてください。

DVDを取り出して見ても(新品なんだから当然だが)汚れなんかは付いていない。再度インストールを試してみても、やはりエラーで終了。DVDドライブの調子が悪いのかと別のDVDを入れてみてみても問題なし。

DVDから起動してみたら何か変わるかと思い、インストールログを表示させながら試したところ、何個かの pkg ファイルのコピーに失敗しているのが分かりました。何回か同じ手順でやってみたところ、エラーになるファイルは毎回異なっているようでした。

なら、プリンタドライバや言語等のパッケージを選択せずに、可能な限り少ないパッケージ数でインストールすれば大丈夫かも、と考えやってみたところ、無事にインストールが完了しました。

この時点で夜中の2時を回っていたので、そのまま寝てしまいました。

Google先生で調べてみると、同じような問題は「ファミリーパック問題」として、たくさん報告されているようです。うちはファミリーパックではなくて、ふつうのパッケージでしたが。私と同じようにパッケージ数を絞ってインストールに成功している人も多いようです。

「インストールに苦労しても、使えればいいや」と思っていたのですが、問題がたくさん見つかりました。やはり正常にはインストールできていなかったようです。今のところ気がついている問題点は

  • Mail が起動しない
  • iPhotoが起動しない
  • iCal がどこにも存在しない
  • QuickSilver(10.6用にバージョンアップ済み)が動かない
  • カレンダーの Bashboard ウィジェットの表示が変

くらいかな。

いくつかのアプリが起動しない原因は同じで、DAVKit.framework の読み込みに失敗して起動できない。
実際のエラーメッセージは以下の通り。

Dyld Error Message:
  Library not loaded: /System/Library/PrivateFrameworks/DAVKit.framework/Versions/A/DAVKit
  Referenced from: /System/Library/Frameworks/CalendarStore.framework/Versions/A/CalendarStore
  Reason: image not found

たしかに、この場所にはファイルが存在していないです。
CalendarStore とも書いてあるので、iCal の CalDAV 関連にフレームワークなのかな、と想像しています。iCal が丸ごと消えているので、このパッケージのインストールに失敗したんでしょう。

DVD から iCal.pkg を取り出して展開して個別にファイルを置いてあげれば大丈夫かと考えてみましたが、iCal.pkg の読み取りはエラーになってしまいました。

月曜日にまたアップルストアに行って交換してくるしか無いかなぁ。

]]>
0
bg http://blog.bluegold.me <![CDATA[PKI day 2009]]> http://blog.bluegold.me/?p=242 2010-08-23T17:53:54Z 2009-06-24T16:00:20Z JNSAの主催するPKI day 2009に参加してきました。

「政府機関及び金融機関のSSLサーバ暗号設定に関する調査結果について」という講演で興味深い調査結果が発表されていました。

https でサービスを提供している政府系や金融系のWebサーバーに関して、「サポートしている暗号アルゴリズム」と「実際に使用される暗号アルゴリズム」を調査したとの事ですが、ちょっと驚く結果になっていました。

曰く、調査したWebサーバのうち7割以上が新しいアルゴリズムである AES256-SHA をサポートしていますが、XP 上の IE7 では9割弱のサーバに対して比較的古くて問題の見つかっている RC4-MD5 で接続してしまうそうです。Firefox では AES256-SHA が最も多く、Vista の IE7 では AES128-SHA が最も多い結果となっていました。(Vistaでの結果も謎で AES256 が有効でも AES128 を優先して使う。)

SSL(TLS)では、サーバとクライアントがそれぞれ自分がサポートしている暗号アルゴリズムのリストを相手に示して、お互いにサポートしているアルゴリズムの中から実際に使用するものを決定します。このネゴシエーションでは「互いにサポートするアルゴリズムのうち最も暗号強度の高いアルゴリズム」が選択されるものだとばかり思っていたので、実際にはアルゴリズムの優先順位は暗号の強度とは無関係に決まっているみたいです。(IE の場合。Firefox では暗号強度の高い順になっている。)

Windows XP 用の CNG を用意しなかったマイクロソフトの判断は、今となっては間違っていたって事なんでしょうね。(2010年問題はネットブックには影響しないからいいのかな。)

もう一つ驚いたのが、SSL2.0 をサポートするサーバの数で、金融系では3割程度ですが(それでも予想よりはずっと多い)、政府系では6割程度がまだサポートしている、と。

昨年仕事で関わったサーバがユーザーの強い希望で SSL 2.0 を有効にしたのをちょっと思い出してしまいましたが、半年前の調査との比較で「AESを有効にしたらSSL 2.0も有効になった」サーバがかなりあるそうなので、誰も深く考えていないだけなのかもしれません。

]]>
0
bg http://blog.bluegold.me <![CDATA[XCacheの管理について]]> http://blog.bluegold.me/?p=222 2010-08-23T18:08:48Z 2009-06-22T17:23:02Z 前に書いたWordPressでXCacheを有効にするについて、「記事の通りにやったのに動かない!」と HiGash.Netの中の人に怒られたので、書きもれていた管理ページの表示方法について簡単にまとめます。

「動かない」と言われた時は「後で書いておくよ」と軽い気持ちで答えてしまっていましたが、よく考えると XCache の管理ページなんてインストールした時に表示させただけで、その後はすぐに munin での監視を始めてしまったので、あまり記憶に残っていません。nginx 側で BASIC 認証を設定していたのが原因だったかで、うまく動かなくて苦労した記憶はあるのですが。(munin の設定については後述)

前に書いた記事で php.ini の設定を載せましたが、管理者の設定が抜けていました。

[xcache.admin]
xcache.admin.auth = On
xcache.admin.user = "admin"
; xcache.admin.pass = md5($your_password)
xcache.admin.pass = "d41d8cd98f00b204e9800998ecf8427e"

パスワードは MD5 でハッシュを計算しておく必要があります。
コードとしては下のような簡単なものですが、このURLでハッシュを計算するものを作ってみました。

<!--
http://blog.bluegold.me/pass.php?password=XXXX 
XXX の部分にパスワードを入力します
-->
xcache.admin.pass = "<?php echo md5($REQUEST["password"]); ?>"

php.ini に管理者の設定を行った後で XCaxhe に付属の管理ページ(xcache.php)を開くと、パスワード認証をした後で管理ページが表示されると思います。
xcache

XCacheに付属の管理ページではキャッシュされているスクリプトや、使用メモリ、キャッシュヒットやキャッシュミスの回数などの基本的な情報を調べることはできますが、得られる情報はあくまでも「その時点」での情報でしかないので、キャッシュミスが増えているか等は分かりません。

このサイトでは munin を利用して XCache のキャッシュ状況をモニターしています。munin はサーバなどをモニタリングして統計画像を作るためのソフトで、この種のソフトとしては非常に簡単に設定を行うことができます。監視用のプラグインは比較的用意に作ることができ、既に多くのソフトウェアに対応しています。

XCache用のプラグインは標準ではインストールされていないので、ここから munin_xcache-0.2.tar.bz2 をダウンロードします。インストールは他のプラグインと同様に出来ますが、このプラグインは少し変わっていて「監視される側の php ファイル(munin_xcache.php)」 も一緒に入っています。こちらはウェブサーバーから見える場所においておく必要があります。

munin のグラフ
しばらくすると、このようなグラフが出来てきます。

6/16 の晩に WordPress 2.8 にアップグレードしたので、そこからキャッシュミスが多くなってきています。

]]>
0
bg http://blog.bluegold.me <![CDATA[Safari4 でフラッシュが使えない]]> http://blog.bluegold.me/?p=212 2010-08-23T18:05:50Z 2009-06-11T02:35:41Z Safari4がリリースされたので、すぐにバージョンアップして問題なく使っていたんですが、WordPressの記事を投稿しようとして不具合を一つ見つけました。

画像をアップロードしようとしたところ「Flashアップローダー」のボタンが表示されていないので、おかしいなと思い他のページも見ていくと Akismet や WordPress.com Stats の統計も見れなくなっていました。

Safari4 ではプラグインが別プロセスになったので、その関係で Flash に影響が出てるのかな、と思い Google で調べてみましたが、同じような症状の人がいないみたいでした。

自分の環境特有の問題のようなので、設定とかプラグインを見ていくと SafariStand を外したところで、Flash が見れるようになりました。

原因が分かったので、開発元のサイトから Safari4 用のプラグインをダウンロードしてきて、無事解決しました。

他にも同じ現象になる人がいるかもしれないのでメモしておきます。

]]>
1
bg http://blog.bluegold.me <![CDATA[Google Developer Days 2009]]> http://blog.bluegold.me/?p=195 2010-08-23T18:09:50Z 2009-06-10T16:17:21Z Google Developer Days 2009

Google Developer Days 2009に参加してきました。

最近、仕事でクラウド関連の調査や開発が多くなってきているので、Google App Engineについての話を聞きにいったんですが、さすがにGoogleだけあって面白そうなセッションがたくさんあって、結局はいろいろと聞いてきてしまいました。

開発用 Android 携帯プレゼントは、予想してなかったんでちょっとうれしい。ただ、新しい iPhone を買うつもりだったので、あまり使わないだろうなぁ。(やっぱりというか、もうYahoo オークションで売ってる人もいるみたい。)

以下のセッションを聞いてきました。

  • HTML5により拓かれる次世代Web
  • Javaで動かすGoogle App Engine
  • Google Chromeの内部構造
  • Google & Open Source
  • Google テクノロジーライトニングトーク
  • Google Wave API

どのセッションも興味深い内容でしたが、既に公開されている情報も多かったですかね。Chromeの開発体制とかの話はたいへん面白かったですが。今回、なにより印象に残ったのがAndroidのセッションに並んでいる人の多さでした。Chrome のセッションが終わってセッションルームから出ると、次の Android のセッションのために廊下をずっと人が並んでいました。去年のこの時期はWWDCに行っていたので、iPhoneに関しては熱気を肌で感じていたんですが、Androidもこんなに多くの人が参加しようとしていたとは。

今まであまり興味の無かったAndroidやOpenSocialについての概要について聞けたのは良かったかな、と思っています。特に OpenSocial はなんとなく OpenSolaris と読み間違えて、OpenSolaris の話だと思いながら記事を読んでガッカリした事が多く、意図的に無視してきた感があるので。

Google Wave のベータプログラムのアカウントをもらえたのが、今回一番うれしかったかも。

「昼食は有名なGoogleの社食のごはんがでるかも」とひそかに期待して行ったので、何もなくてがっかりしたのはココだけの話。

]]>
1
bg http://blog.bluegold.me <![CDATA[nginx のバージョンアップ]]> http://blog.bluegold.me/?p=184 2010-08-13T07:29:30Z 2009-06-05T16:57:50Z

nginx のバージョン 0.7 系が stable になっていたので、サーバソフトウェアのアップデートを行いました。(久しぶりのブログの更新は OpenSolaris 2009.06 について書こうと思ってたんですが、これはまた後で。。。)

インストールしたのは nginx 0.7.59 です。リリースのアナウンスが 25 May 2009 なので、2週間くらい前に出たばかりだったようです。 0.6系と0.7系の間の変更点についてまとまっている資料を探したのですが、見つかりませんでした。

Change Log を見るとかなりの修正箇所があるようですが、大きくまとめると以下の機能が増えているようです。

*) caching of proxied and FastCGI servers;
*) "try_files" directive;
*) the "location" and "server_name" directives support captures in regular expressions;
*) XLST and image filters;
*) a preliminary IPv6 support;
*) nginx/Windows.

WindowsサポートとIPv6、あまり関係なさそう。。。

try_filesはファイルを探す順番を指定するディレクティブで、例えば「あるファイルが存在する場合はメンテナンス画面を表示する」ような場合、今までは if 文をいくつか書いて条件分岐させていたのをすっきりと記述することが出来るようです。設定例を見るといろいろな応用が出来るようです。

インストールはいつもの通り

./configure --with-http_stub_status_module
                   --with-http_gzip_static_module
                   --with-cc-opt='-O3' 
make
make install

だけで大丈夫でした。

ただ、私の環境ではなぜか configure が途中で失敗していて、しばらくはまりました。結局は .bash_profile で環境変数 CC と CFLAGS を指定していたのが原因でした。nginx の configure スクリプトは autoconf で作られたものでは無いので、予想もつかないところが問題になるなぁ。

nginx 0.6 系で使用していた nginx.conf で起動させたところ、2点ほど問題がありました。

  1. gzip_types に text/html を設定していると警告が出る。
    gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    

    0.6系では上のような設定で問題ありませんでしたが、0.7 では以下の警告が出ます。

    duplicate MIME type “text/html” in /etc/nginx/nginx.conf

    text/html は暗黙的に設定されているようなので、以下のように修正。

    gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    
  2. 特定のPHPファイルだけ BASIC認証させていたが、PHPとして実行されなくなった。

    WordPress のログインページを BASIC 認証をさせるために、以下のような設定をしていました。

        location /wordpress/wp-login.php {
            auth_basic "secret";
            auth_basic_user_file htpasswd;
        }
    

    nginx 0.6 系では BASIC 認証後に wp-login.php が実行されていましたが、0.7系では BASIC認証はされるものの、PHPファイルが実行されずにソースファイルがそのまま転送されてきました。

    どのように修正すべきか分からなかったので、以下のように fastcgi の設定を入れて ad hoc に修正しました。

        location /wordpress/wp-login.php {
            auth_basic "secret";
            auth_basic_user_file htpasswd;
    
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $fastcgi_script_name;
            include        fastcgi_params;
        }
    

    こういうケースでは今後は try_files ディレクティブを使えって事なんでしょうね。

]]>
0
bg http://blog.bluegold.me <![CDATA[XCache を複数の WordPress で使う場合の問題]]> http://blog.bluegold.me/?p=174 2010-08-23T18:12:59Z 2009-05-03T16:24:58Z 以前のエントリで WordPress のオブジェクトキャッシュを XCache の保存する方法について書きましたが、その後問題が発生したのでメモ。

複数の WordPress を1つのホストで稼働させる際に XCache Object Cache Plugin for WordPress 2.5+ を使用すると、オブジェクトキャッシュが混ざってしまうようです。

このサイトではhttp://blog.bluegold.me用とhttp://mama.bluegold.me用に2つの WordPress を稼働させています。それぞれ専用のデータベースを持つ独立したブログになっていますが、双方でオブジェクトキャッシュを有効にしたところ、しばらくして blog.bluegold.me 側の WordPress の管理コンソール(wp-admin)にログインできなくなりました。

XCache をインストールしてからは時間が経っていたので関係しているとは全く思わずに、MySQL 側でパスワードを何度も更新してログインを試みたり、WordPress 2.7.2 2.7.1 にバージョンを上げたばかりだったので、仕様が変わったのかと調べてみたりしたものの原因は分かりませんでした。

管理コンソールいろいろなIDとパスワードを入力しているうちに、blog.bluegold.me のユーザ名(bg)を入力すると「ユーザ名が違います」を表示されるのに、mama.bluegold.me 側のユーザ名(papa)を入力すると「パスワードが違います」と表示される事に気がつきました。ありえない事が起きているのが分かってきたので、試しにpapa の正しいパスワードを入力してみたところログインに成功し、bgのダッシュボードが表示されました。

ここでキャッシュが悪さをしている事がわかったので、オブジェクトキャッシュの使用を止めて、キャッシュをクリアするために PHP の FastCGI のプロセスを再起動しました。

調べてみると、やはり同じような問題を抱えている人はいるようで、以下のサイトに詳しく書かれていました。ユーザ情報が混在するのは仕様なんですかね...
http://jamescoletti.com/multiple-wordpress-installs-and-object-cache-collision

]]>
2
bg http://blog.bluegold.me <![CDATA[WordPressの画像をAmazon CloudFrontに置く]]> http://blog.bluegold.me/?p=164 2011-01-28T17:07:05Z 2009-04-16T06:12:44Z last.fm

このブログは今のところ自宅に置いてあるサーバで運用しています。
手直にあるので管理は簡単なのですが、自宅の回線はアップストリームの帯域幅が大きくないので、ページを表示するさいの画像読み込みの遅延が以前から気になっていました。

このサイトでは以下のように nginx を設定することで、可能な限り静的なコンテンツの使用する帯域幅を小さくしようとしていますが、それでもファイル転送量のほとんどは画像ファイルになっています。

location / {
    if (-f $request_filename) {
        expires 30d;
        break;
    }
}
location ~* ^.+\.(html|css|txt|tar|bmp|rtf|js)$ {
    gzip_static on;
    expires 30d;
}

以前から画像を外部のサイトに置いて転送負荷を減らそうと考え、一部の画像をflickrに置いたりしていますが、これはという解決策がありませんでした。

最近、仕事関係で Amazon のウェブサービスについて調べていてAmazon CloudFrontというサービスがあるのを知り、WordPress のテーマの画像を置いてみたらどうなるのかを調べてみました。

Amazon CloudFront は Amazon の提供するウェブサービスの1つで、いわゆるCDNです。Amazon S3に保存したファイルをインターネット上に分散配置されたキャッシュサーバに置く事で、静的なコンテンツを高速に配信する事ができるようになっています。

有料のサービスなので利用には Amazon Web Service のアカウントが必要になりますが、以下のように安価な価格設定になっているので費用対効果は高いと思います。

United States
$0.170 per GB – first 10 TB / month data transfer out
$0.010 per 10,000 GET Requests
Japan
$0.221 per GB – first 10 TB / month data transfer out
$0.013 per 10,000 GET Requests

Amazon S3 の使い方はいろんな場所で説明されているので省きます。使用しているテーマのディレクトリから画像や css, js ファイルを CloudFront に配備してください。
S3 に置いたファイル(オブジェクト)に対して Everyone の Read 権限を与える必要がある点だけ注意してください。
Firefox のプラグイン S3OrganizerはCloudFront にも対応しているのでお勧めです。

CloudFrontに置いたファイルをWordPressから参照する方法はテーマファイル次第ですが、私のサイトで作ってもらったテーマでは bloginfo(‘template_directory’); と bloginfo(‘stylesheet_url’); の2つの値を変更するだけで大丈夫そうでした。
私はWordPressもPHPも詳しくなく、この二つの値を変更する「正しい方法」が分からなかったため適当にプラグインを書いてみました。
(こうやって野良プラグインが増えていくんだろうな)

プラグインのソースは以下の通りです。

<?php
/*
 * Plugin Name: CloudFront
 * Plugin URI: http://blog.bluegold.me/cloudfront
 * CloudFront plugin is a plugin designed to help you drastically speed up your blog's load time by loading content onto Amazon CloudFront.
 * Version: 0.1
 * Author: Blog Bluegold.me
 * Author URI: http://blog.bluegold.me
 * */

$cdn_base = "__EDIT_HERE__";

function    filter_cdn_css($url) {
    global $cdn_base;
    return $cdn_base . "/style.css";
}

function    filter_cdn_template_dirctory($url) {
    global $cdn_base;
    return $cdn_base;
}

add_filter('stylesheet_uri','filter_cdn_css');
add_filter('template_directory_uri','filter_cdn_template_dirctory');
?>

これを WordPress の wp-content/plugins/cloudfront/cloudfront.php という名前で保存するだけです。

]]>
0
bg http://blog.bluegold.me <![CDATA[GnuPGでメーリングリスト宛のメールを暗号化する]]> http://blog.bluegold.me/?p=159 2010-08-13T07:28:47Z 2009-01-07T15:38:31Z gnupg

年末にGPGMailのRelease 1.2.0(v56)が出ていたので、さっそくアップデートしました。ベータの取れた正式版としては初めてLeopardをサポートするバージョンだと思います。

GPGMailは暗号化メールの送受信をおこなうといった意味では必要な機能を備えています。しかし、鍵管理などはGnuPGの機能をそのまま使っているため、GnuPG自体の知識が必要となります。各ユーザの鍵に関してはMacGPGプロジェクトのGPG Keychain Accessを利用すればGUIから管理することができるようになりますが、メーリングリストのアドレスに複数の鍵を対応させるような設定はGUIからはできません。

日本語での情報がほとんど無いようなのでメモしておきます。

GnuPGでメーリングリスト宛てのメールを暗号化する場合の考えたかにはいくつかあるとは思いますが、基本的には「メーリングリストのアドレス専用の鍵で暗号化する」か「メーリングリストに参加している個々のアドレスの鍵で暗号化する」かのどちらかです。前者は送る側も受け取る側も通常のメールアドレス用の鍵と同じように扱えるため非常に簡単ですが、メーリングリストのメールを受け取る全てのユーザが同一の鍵を共有する事になるのでセキュリティ上の問題があります。通常は後者を選択する事になると思います。

この方法ではメールの送信者(つまりメールを暗号化する側)が、メーリングリストに参加している各ユーザの実際のメールアドレスをあらかじめ gpg.conf に設定しておく必要があります。

たとえば、ml@example.com というアドレスがメーリングリストで、実際には user1@example.com, user2@example.com の2つのメールアドレスに配信される場合、~/.gnupg/gpg.conf に以下のような記述を行います。

group   ml@example.com = user1@example.com user2@example.com

アドレスはスペース区切りです。アドレスの数が多くて1行に書ききれないような場合は、以下のように複数の行にわけて記述する事ができます。

group   ml@example.com = user1@example.com user2@example.com ...
group   ml@example.com = user20@example.com user21@example.com

この設定はMacGPGの GPGPreferences でも設定可能と言えば可能ですが、gpg.conf を直接編集するのと難易度はあまり変わらないように思います。

]]>
0
bg http://blog.bluegold.me <![CDATA[POPFileを使用してGmailのラベルを設定する]]> http://blog.bluegold.me/?p=153 2010-08-23T18:24:58Z 2008-12-25T15:20:25Z 今週から会社のメールがGoogle Apps for Your Domainに移行しました。今までのメールサーバはPOP3しか使えなかったのですが、Gmailに移行したのを機にIMAP4を使ってみることにしました。
私は主にLeopardのMail.appを利用してメールを読んでいるので、Googleの公式のヘルプにある通りの手順で簡単に設定することができます。

ただ、このままだとGmailが「迷惑メール」と判断したメールがMail.appでは未読メールとして表示されたり、Mail.appでメールを削除した際にGmailのゴミ箱に移動されずに「Deleted Messages」ラベルが付けられる、などの問題が発生します。そこで、Gmail側の「迷惑メール」フォルダなどにMail.appで「メールボックスの用途」を設定しました。これでメール管理をMail.app側に統合化する事ができ、便利に使えるようになりました。

POP3でメールを読んでいた頃はPOPFileを利用して、迷惑メールのフィルタやメールの振り分けを行っていました。Gmailには迷惑メールのフィルタ機能が元から備わっていますが、メールの振り分けをPOPFileほどは柔軟に設定できません。たとえば、会社のメールアドレスには誰かが全員用のエイリアス用に購読したNikkei BPやキーマンズネットのニュースがたくさん送られてくるのですが、単純なルールでこれらをまとめて「ニュース」フォルダに振り分けるのは(ほぼ)不可能です。

そこで、POPFileをIMAP4の環境で使用する方法について調べてみました。

POPFileのIMAPモジュールはPOPモジュールと異なりプロキシではありません。そのため、POPFileを利用するのにメールクライアントの設定を変更する必要はありません。これは良いことですが欠点もあります。プロキシとして動作しない為に、サブジェクトを変更したりX-Text-Classificationヘッダを付加する事ができません。

IMAPモジュールはメールクライアントの動作とは無関係に定期的にIMAPサーバに接続し、メールの本文の内容を判断して適切なフォルダ(Gmailの場合はラベル)に振り分けます。IMAPモジュールはいったん設定を行うと後は自動的に処理を続けるロボットのようなプログラムなので、クライアントPCで動作させるよりは常時稼働しているサーバの上で動かした方が良いのかもしれません。

IMAPモジュールの使い方は公式サイトの説明にある通りですが、Leopard(Mac OS X)で使用するには注意する点がいくつかあります。(POPFile v1.1.0 を使用しています。)

imap.gmail.com

POPFile コントロールセンターの「設定」ページの「IMAPサーバー ホスト名」にGmailのIMAPサーバ名、imap.gmail.com を入力しても接続できずに、以下のエラーがログに残ります。

2008/12/25 23:48:08 10142: IMAP-Client: 136: IO::Socket::SSL error: IO::Socket::SSL: bind: Address family not supported by protocol family
2008/12/25 23:48:08 10142: imap: 1624: Could not CONNECT to server.
2008/12/25 23:48:08 10142: imap: 1493: Could not connect to server.

エラーメッセージをGoogleで検索すると、IPv6が関係しているエラーのようです。Leopard に固有の問題のようですが、「imap.google.com の AAAA レコードが見つかる為に IO::Socket::SSL がサポートしていない IPv6 で接続しようとしている」ためにエラーになっているらしい。将来のバージョンで修正されると思いますが、それまでのワークアラウンドを考えます。

要は、imap.gmail.com の AAAA レコードが見つかることが原因なので、たとえば、imap.gmail.com の(IPv4の)IPアドレスを調べて、それをIMAPサーバーのホスト名に設定したり、そのIPアドレスを逆引きして得られる実サーバのホスト名を設定すれば、とりあえず使用できるようになります。(今、私の環境から調べるとrv-in-f111.google.comです。)ただ、imap.gmail.comを構成する多数のサーバの中の1台にしか接続できなくなるため、そのうち接続出来なくなるかもしれません。

日本語のIMAPフォルダ名

IMAPモジュールではPOPFileのバケツ毎に振り分けるIMAPのフォルダを設定する必要があります。この設定はPOPFile コントロールセンターの「設定」ページから行いますが、このページは日本語の IMAPフォルダ名に対応していません。たとえば、「迷惑メール」フォルダは「&j,dg0TDhMPww6w-」と表示されます。これは modified UTF-7 というエンコーディングだそうですが、このままでは振り分けるべきフォルダがどれなのかが分かりません。

これも将来のバージョンで修正されると思いますが、当面は以下のような方法で調べるしかないようです。

$ irb -rnet/imap
irb(main):001:0> %w(迷惑メール 下書き 送信済みメール ゴミ箱).each {|key| puts "#{key} -> [Gmail]/#{Net::IMAP.encode_utf7(key)}"}
迷惑メール -> [Gmail]/&j,dg0TDhMPww6w-
下書き   -> [Gmail]/&Tgtm+DBN-
送信済みメール -> [Gmail]/&kAFP4W4IMH8w4TD8MOs-
ゴミ箱   -> [Gmail]/&MLQw33ux-

]]>
0
bg http://blog.bluegold.me <![CDATA[WordPressのwpadsプラグインで日本語を使用するには]]> http://blog.bluegold.me/?p=147 2010-08-23T18:26:09Z 2008-12-24T02:42:33Z このブログでは広告を表示するのにWPAdsプラグインを利用しています。このプラグインは重み付けによって複数の広告を切り替えて表示する機能など非常に便利なものですが、広告の「Description」や「HTML Code」に日本語を入れると文字化けしてしまう問題があります。

今日はちょっと時間があったので文字化けの原因について調べてみました。

日本語の文字を含んだ広告を作成してWPAdsのデータベースを直接見てみたところ正常に保存されているようなので、原因は管理ページの表示部分にあると予想して wpads-options.php を見たところ、以下のようなコードになっていました。

<tr>
    <td valign="top">Description</td>
    <td>
        <input name="banner_description" type="text" size="50" value="<?php echo htmlentities($banner->banner_description);?>" /><br />
        Any text that helps you identify this banner
    </td>
</tr>
<tr>
    <td valign="top">HTML Code</td>
    <td>
        <textarea name="banner_html" rows="6" cols="80"><?php echo htmlentities($banner->banner_html);?></textarea><br />
        Copy and paste the HTML code to show the ad (for example, the Google AdSense code)
    </td>
</tr>

どうもhtmlentities()によるエスケープ処理で日本語が化けてしまっているようです。htmlentities() は文字コードを省略されると ISO-8859-1 として処理されるようなので、正しく処理するように ‘UTF-8’ を渡します。(ついでに XSS の問題がありそうなので ENT_QUOTES オプションを追加。)

修正後のソースは以下のようになります

<tr>
    <td valign="top">Description</td>
    <td>
        <input name="banner_description" type="text" size="50" value="<?php echo htmlentities($banner->banner_description, ENT_QUOTES, 'UTF-8');?>" /><br />
        Any text that helps you identify this banner
    </td>
</tr>
<tr>
    <td valign="top">HTML Code</td>
    <td>
        <textarea name="banner_html" rows="6" cols="80"><?php echo htmlentities($banner->banner_html, ENT_QUOTES, 'UTF-8');?></textarea><br />
        Copy and paste the HTML code to show the ad (for example, the Google AdSense code)
    </td>
</tr>

patch: wpads-utf8.patch

]]>
7
bg http://blog.bluegold.me <![CDATA[Useful WordPress SQL Hacks]]> http://blog.bluegold.me/?p=140 2010-02-14T14:55:04Z 2008-12-22T11:39:18Z 8 Useful WordPress SQL Hacksという記事の7番を参考にして、このブログでもWordPressのSQL実行回数を計測してみました。

計測方法は以下のコードを footer.php に追加するだけです。

<?php if (is_user_logged_in()) { ?>
    <?php echo get_num_queries(); ?> queries in <?php timer_stop(1); ?> seconds.
<?php } ?>

結果は以下のようになりました。
トップページを3回表示させた時の時間です。

24 queries in 0.540 seconds.
24 queries in 0.545 seconds.
24 queries in 0.550 seconds.

WordPressで24 queriesは多いのか少ないのかは分かりませんが、1ページ作るのに 0.5 秒は非力なこのマシンでもちょっと遅いか。

そこで、MySQLのクエリキャッシュを有効にする事にしました。
このブログのサーバ機はメモリが256MBしかないので、いままでは無効にしていました。

my.cnfの具体的な設定値は以下の通り。

query_cache_limit=1M
query_cache_min_res_unit=4k
query_cache_size=16M
query_cache_type=1

同じようにトップページを3回表示させたところ、若干の速度向上がありました。
微妙と言えば微妙ですが。。。

24 queries in 0.512 seconds.
24 queries in 0.510 seconds.
24 queries in 0.510 seconds.

]]>
0
bg http://blog.bluegold.me <![CDATA[Rails 1.2.6 と gem 1.3.0 を一緒に使う]]> http://blog.bluegold.me/?p=132 2010-08-23T18:27:31Z 2008-12-17T16:18:53Z Merbが最近はやっているようなので、インストールして使ってみようと思いました。Merb には Rubygems 1.3.0 以上が必要なのでアップデートしたところ、仕事で開発している Rails 1.2.6 で作られたアプリケーションに gem の deprecated メッセージが出てくるようになってしまいました。

たとえば script/console を実行すると以下のようなメッセージが出てきます。

$ script/console 
Gem::SourceIndex#search support for String patterns is deprecated
./script/../config/boot.rb:20 is outdated
Loading development environment.
Gem::SourceIndex#search support for String patterns is deprecated
./script/../config/../config/boot.rb:20 is outdated
>> 

このアプリは Rails を使っているのでとうぜんWeb用のアプリなのですが、管理用に独自のコマンドラインシェルを用意しています。こちらのコマンドの実行時にも同様のメッセージが出てきてしまっています。「Rails 2.2 系に上げるいい時期かな」とも思わないでもないのですが、製品として提供している物なので、今期末にいくつか控えている納品を終えるまではバージョンを上げるわけにもいきません。

仕方がないのでクイックハック
script/console の最初で stderr を /dev/null に捨てるようにしました。

#!/usr/bin/env ruby
$stderr.reopen('/dev/null')
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/console'

deprecated なメッセージを簡単に抑制する設定とかもあるんだろうか。。。

]]>
0
bg http://blog.bluegold.me <![CDATA[Mac OS X 10.5.6 と GPGMail]]> http://blog.bluegold.me/?p=127 2010-02-14T14:54:02Z 2008-12-16T15:48:47Z Mac OS X 10.5.6 が出ていたので、さっそく適用してみました。
アップデート後もしばらくは何の問題も無く使えていたのですが、Mail.app を起動したところクラッシュ。
再度実行したら、またクラッシュ。

クラッシュした時のメッセージを良く読んでみたら、原因が書いてありました。

アプリケーション Mail は予期せず終了しました。この問題は GPGMail プラグインが原因である可能性があります。

GPGMailは Mail.app用の GnuPG のフロントエンドで、会社でやり取りするメールの暗号化に使っています。アップデートを探しに開発元のSen:TEのサイトを見てみた所、

IMPORTANT: You need at least GPGMail d55 since MacOS X 10.5.6; previous versions of GPGMail will crash Mail.

と、とっくに対応されていました。

最新の GPGMail に入れ替えたところ、Mail.app が正常に起動するようになりました。

]]>
0
bg http://blog.bluegold.me <![CDATA[last.fm のプレイリストをブログに表示するには]]> http://blog.bluegold.me/?p=117 2010-08-23T18:28:45Z 2008-12-11T15:53:57Z last.fm

HiGash.Netの中の人にWordPressのキレイなテーマを作ってもらったので、last.fmの「最近聴いたトラック」を表示するプログラムを作りました。

last.fm の公式のウィジェットを使用すれば簡単にブログに貼付ける事ができますが、公式の物はFlashを使っていて自分でデザインを変更できないので、自分で作ってみました。last.fmはaudioscrobblerというAPIを用意しているので、このAPI経由で情報を取得します。今回は Ruby の scrobbler gemを利用しています。

scrobbler gem のインストールは以下のように簡単です。

$ sudo gem install scrobbler

scrobblerのドキュメントを見ながら、プログラムを書いていきます。
手順はだいたい次のようになります。

  1. last.fmのユーザの「最近聴いたトラック」の一覧を取得する
  2. トラックのアルバムアートワークを取得する

last.fmのユーザの「最近聴いたトラック」の一覧を取得する

scrobblerライブラリを使うと簡単で、last.fmのユーザ名を指定してScrobbler::Userのオブジェクトを作成するだけです。

user = Scrobbler::User.new('bluegold')
recent_tracks = user.recent_tracks

Scrobbler::User#recent_tracks の戻り値はScrobbler::TrackのArrayになっています。Scrobbler::Track は再生した曲の情報を表すオブジェクトで、曲のアルバム名やアーチスト名、last.fmのURLなどの情報を保持しています。last.fmの URLは、たとえば Sheryl Crow の Real Goneの場合はこのページの事です。

最近再生したトラックを表示するだけなら、ここまでで終わりです。

トラックのアルバムアートワークを取得する

Scrobbler::Track のオブジェクトにもimageやthumbnailなどのattributeは存在するのですが、これらは’only seems to be used on top tracks for tag’とのことでScrobbler::User#recent_tracksでは値が設定されていません。そこでトラックのアーチスト名とアルバム名からScrobbler::Albumのオブジェクトを作成して、そこからアルバムアートワークを取得します。Scrobbler#Trackのオブジェクトから得られるアルバム名は(アーチスト名も?)エスケープされていて、そのままでは正しくデータを取得出来ない場合があったので、CGI#unescapeHTML を利用して元に戻しています。

track = recent_tracks.first
album = Scrobbler::Album.new(
  track.artist,
  CGI.unescapeHTML(track.albumname)
)
image_url = album.image(:small)

上のコードで1曲分のアートワーク画像へのURLが得られるので、表示したい曲数分繰り返します。

あとは好きなようにHTMLを書いてスタイルを設定するだけです。完成した結果はこのブログのフッターに表示されている通りです。

]]>
0
bg http://blog.bluegold.me <![CDATA[WordPressでXCacheを有効にする]]> http://blog.bluegold.me/?p=83 2011-01-28T17:07:35Z 2008-11-19T15:28:29Z 前回の記事でPHPの設定は完了していますが、ついでにPHPアクセラレータも導入してみます。PHPアクセラレータはPHPの実行時に中間的に生成されるバイトコードをキャッシュや最適化を行う事により、実行時のロスを減らす仕組みです。

PHPアクセラレータにはeAcceleratorAPCなどいろいろとあるようですが、今回は使った事のないXCacheを使ってみます。XCacheはバイトコードのキャッシュの他にPHPの変数をキャッシュする機能があるので、この機能をWordPressで使うように設定も行います。

XCacheのビルドは以下の通り簡単に行うことができます。

wget http://xcache.lighttpd.net/pub/Releases/1.2.2/xcache-1.2.2.tar.gz
gzip -dc xcache-1.2.2.tar.gz | tar xvf -
cd xcache-1.2.2
./configure --enable-xcache
make
make install

php.ini ファイルにXCacheの設定を記述します。
ソースに付属しているサンプルの xcache.ini からあまり変えていません。

[xcache-common]
zend_extension = /usr/local/lib/php/extensions/no-debug-non-zts-20060613/xcache.so

[xcache]
xcache.shm_scheme =        "mmap"
xcache.size  =               22M
xcache.count =                 1
xcache.slots =                8K
xcache.ttl   =             86400
xcache.gc_interval =         600

xcache.var_size  =            2M
xcache.var_count =             1
xcache.var_slots =            8K
xcache.var_ttl   =             0
xcache.var_maxttl   =          0
xcache.var_gc_interval =     300

xcache.test =                Off
xcache.readonly_protection = Off
xcache.mmap_path =    "/dev/zero"
xcache.coredump_directory =   ""
xcache.cacher =               On
xcache.stat   =               On
xcache.optimizer =            On

xcache.size は使用するアプリケーションの種類によって調整した方がよいと思います。XCacheはeAcceleratorなどと違い、キャッシュは全てメモリ上に持つようなので大きめに設定しておいた方が良いかもしれません。

バイトコードのキャッシュは以上の設定でphpのFastCGIを再起動するだけで使用出来ますが、変数のキャッシュを利用するにはアプリケーション側で対応する必要があります。WordPressにはXCache for WordPressというプラグインがあるようですが、最近のバージョンのWordPressでは動作しないようなので、XCache Object Cache Plugin for WordPress 2.5+を使用する事にしました。

xcache
インストールは簡単ですが、XCache Object Cache Plugin for WordPressは通常のWordPressのプラグインとはインストールするパスが異なるので注意が必要です。プラグインのファイルは object-cache.php 1つだけで、これをWordPressのコンテントディレクトリ(通常は xp-content ディレクトリ)に置きます。私も最初は説明を読まずに他のプラグインと同じように xp-content/plugins ディレクトリに置いて、しばらく悩みました。

このようにバイトコードと変数の双方がキャッシュされている事を確認出来ます。これだけで体感出来る程度には速度が向上するので、導入する価値はあると思います。

]]>
1
bg http://blog.bluegold.me <![CDATA[nginxでphpを利用する]]> http://blog.bluegold.me/?p=72 2010-08-23T18:30:35Z 2008-11-12T15:09:58Z

nginxからphpを利用するには、FastCGIを有効にしてphpをビルドしておく必要があります。
php-5.2.6 を以下のようにビルドしました。

./configure  
    --with-curl=/usr --enable-fastcgi 
    --enable-mbstring --enable-zend-multibyte 
    --enable-mbregex --with-mysql 
    --with-mcrypt --with-mhash 
    --with-openssl --with-gd 
    --enable-gd-native-ttf --enable-gd-jis-conv 
    --with-jpeg-dir=/usr --with-xpm-dir=/usr 
    --with-freetype-dir=/usr
make
make install

メールで記事を投稿する為に openssl と gd の関係のオプションを追加してます。
openssl は gmail に対して POP で接続する為に、gd はKtai Entryで画像を添付したメールを処理するのに必要でした。

FastCGIのプロセスを以下のように起動します。

/usr/local/bin/php-cgi -q -b 127.0.0.1:9000

127.0.0.1:9000 は FastCGI の接続を待ち受ける IPアドレスとポート番号です。
この値は環境に合わせて別の物に変更する事が可能です。

続いて nginx 側の設定ファイルを作成します。

前回の記事で基本的な設定は nginx.conf に書いてあるので、ここでは VirtualHost の設定だけを記述します。

phpをFastCGIで実行するのに最低限必要な設定はこれだけです。

server {
    listen       80;
    server_name  bluegold.me blog.bluegold.me;
    root   /var/www/blog;
    index  index.php index.html index.htm;
&lt;p&gt;    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/blog/$fastcgi_script_name;
        include        fastcgi_params;
    }
}

127.0.0.1:9000 の部分は FastCGI のプロセスのオプションと同じ値を設定します。

]]>
0
bg http://blog.bluegold.me <![CDATA[nginx.conf についてもう少し]]> http://blog.bluegold.me/?p=65 2010-08-23T18:31:16Z 2008-10-23T15:48:32Z

前回紹介したnginx.conf についてもう少し掘り下げて説明します。

ログフォーマット

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '"$status" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" "$gzip_ratio"';

    access_log  /var/log/nginx/access.log  main;

nginx は良い所のたくさんあるソフトウェアですが、新しいだけに nginx のデフォルトのログフォーマットのままではAWStatsなどのログ解析ソフトに読み込ませる事ができません。そこで Apache の combind フォーマットと同じになるように設定しています。

この設定はGoogleで検索して見つけたのですが、nginx のバージョンが違うのかそのままでは AWStats や Webalizer でエラーになった為、多少変更しています。$request と $status をダブルクォーテーションで囲む必要がありました。

VirtualHost設定

nginxの設定はとても簡単で、単純な VirtualHost の設定は以下のような少ない記述だけで十分です。

    # error catch
    server {
        listen       80;
        server_name _;
        root   /var/www/temp;

        index  index.html;

        access_log  /var/log/nginx/temp-access.log  main;
    }

root を DocumentRoot, index を DirectoryIndex と読み替えれば、Apacheの設定ができる人にはほぼ説明がいらないくらいだと思います。”server_name _;”は全てのリクエストを受け付けるVirtualHostで Host: ヘッダの指定されていないリクエストなどの他の VirtualHost が処理しないリクエストがこの VirtualHost に回ってきます。当然、サービスを提供する VirtualHost には適切な server_name を設定しておきます。

脆弱製のあるサーバを探しているスキャナの多くは IP アドレスを手がかりにサーバに接続してくるので、このような設定にしておく事で、スキャナのリクエストを「何も無い VirtualHost」に閉じ込めてしまう事ができます。実際にこのホストにも phpMyAdmin や xampp の管理画面を探すリクエストが来ています。

この設定は、codered が流行した頃に大量のアタックのログを本来のサービスのログから分離する為に始めたんですが、あまり一般的じゃないのかな。

]]>
1
bg http://blog.bluegold.me <![CDATA[WordPressのバックアップを Gmail に保存する その3]]> http://blog.bluegold.me/?p=45 2010-08-23T18:32:38Z 2008-10-20T16:28:18Z 前回、暗号化を行った事によりバックアップの保存の目的はほぼ果たしているのですが、気持ちが悪いので添付ファイルについても考えてみました。

gmail と uuencode をキーワードに Google で検索した所、mutt を使うのが一般的らしい。
↓のように ‘-a’ キーワードで添付するファイルを指定するだけで添付ファイルとして扱ってくれます。

mutt -a name.afz -a mysql_name.afz -s "name backup `date`" to_address

複数の添付ファイルにも対応しているので、この方法で問題ないかとも思ったのですが、1つだけ問題がありました。mutt では Envelope From を引数で変更することが出来ず、muttrc/.muttrc に別途設定する必要があります。

なんかめんどくさそうな感じがしたので、結局は Ruby でフィルタプログラムを書くことにしました。

以下のような物になりました。

#!/usr/bin/env ruby
#
# sendmail.rb</p>

require 'rubygems'
require 'tmail'
require 'net/smtp'
require 'nkf'
require 'etc'
require 'socket'
require 'optparse'


def usage( status, msg = nil )
  output = (status == 0 ? $stdout : $stderr)
  output.puts msg if msg
  output.print(&lt;&lt;EOS)
Usage: cat msg | #{File.basename $0} [-j|--ja] [-s <subject>] [-f <from>] <to>

  -s,--subject=sbj   subject of the message. (default=(none))
  -f,--from=from     from address.
  -a,--attachment=file attachment
  -j,--ja            handle japanese message. (default=off)

EOS
  exit status
end

def main(args)
  subject = nil
  from = guess_from_address()
  to = []
  attachments = []
  ja_locale = false

  OptionParser.new do |opt|
    opt.banner = "Usage: #{$0} [options]"

    opt.on('-s', '--subject=subj', 'subject of the message. (default=(none))') do |arg|
      subject = arg
    end
    opt.on('-f', '--from=from', 'from address.') do | arg|
      from = arg
    end
    opt.on('-j', '--ja', 'handle japanese message. (default=off)') do
      ja_locale = true
    end
    opt.on('-a', '--attachment=file', 'attachment') do |arg|
      attachments &lt;&lt; arg
    end

    to = opt.parse!(args)
  end

  usage(1) if to.empty?

  setup_mail(from, to, subject, $stdin.read, ja_locale, attachments)
end

def setup_mail( from, to, subject, body, ja_locale, attachments )
  mail = TMail::Mail.new
  mail.date = Time.now
  mail.from = from
  mail.to = to
  mail.subject = subject if subject
  mail.mime_version = '1.0'

  # 本文の処理
  if attachments.empty?
    message = mail
  else
    message = TMail::Mail.new
    message.transfer_encoding = '7bit'
  end
  if ja_locale
    message.body = <span class="caps">NKF.</span>nkf('-j', body)
    message.set_content_type 'text', 'plain', 'charset' =&gt; 'iso-2022-jp'
  else
    message.body = body
    message.set_content_type 'text', 'plain'
  end

  # 添付ファイルの処理
  unless attachments.empty?
    mail.parts.push(message)

    attachments.each do |filepath|
      body = nil
      File.open(filepath) { |f| body = f.read } rescue nil
      next if body.nil?

      attachment = TMail::Mail.new
      filename = File.basename(filepath)

      encoded_body = [body].pack('m').chomp.gsub(/.{76}/, "\\1\n")
      attachment = TMail::Mail.new
      attachment.body = encoded_body
      attachment.transfer_encoding = 'base64'
      attachment.set_content_type('application', 'octet-stream', 'name' =&gt; filename)
      attachment.set_content_disposition('attachment', 
                 'filename' =&gt; filename)

      mail.parts.push(attachment)
    end

    mail.write_back
  end

  puts mail.encoded

  mail
end

def guess_from_address
  user = getlogin()
  unless user
    $stderr.puts 'cannot get user account; abort.'
    exit 1
  end
  if domain = (Socket.gethostname || <span class="caps">ENV</span>['HOSTNAME'] || <span class="caps">ENV</span>['HOST'])
    user + '@' + domain
  else
    user
  end
end

def getlogint
  begin
    require 'etc'
    Etc.getlogin
  rescue LoadError
    <span class="caps">ENV</span>['LOGNAME'] || <span class="caps">ENV</span>['USER']
  end
end

main(ARGV)

TMail のサンプルの sendmail.rb をほぼそのまま使っています。
引数 ’-a’ で添付ファイルを指定出来るように変更しました。(getopts が deprecated になっていたので optparse で書き直しています。)

]]>
0
bg http://blog.bluegold.me <![CDATA[WordPressのバックアップを Gmail に保存する その2]]> http://blog.bluegold.me/?p=40 2010-08-23T18:32:24Z 2008-10-19T16:21:39Z バックアップファイルを 256bit AES で暗号化する方法について考えます。

バックアップの作成に使用した afio には、バックアップ対象のファイルを個別に圧縮する機能があります。圧縮に使用する外部プログラムは引数で変更出来るので、これを利用して暗号化を行います。

まずは、下のような暗号化用のフィルタを作成します。

#!/bin/sh
# encrypt_filter.sh

opt="-pass env:FILTER_PASSWORD"

if [ -r /etc/wp_backup_password ]; then
    opt="-pass file:/etc/wp_backup_password"
fi
gzip -c | openssl enc -e -aes-256-cbc $opt

次に afio に -P オプションでフィルタプログラムを使用させます。

afio -ovz -Z -U -P encrypt_filter.sh backup.afz

これでバックアップファイルが作成される際に個別のファイル毎に暗号化されるようになります。

/etc/wp_backup_password ファイルが暗号鍵になります。このファイルはバックアップを元に戻す時に必要になるので安全な場所に保管しておかないといけません。パスワードファイルの中身はなんでも構わないので、うちのサイトでは以下のようにしてランダムに作成しています。

dd if=/dev/urandom of=/etc/wp_backup_password bs=256 count=1

このファイルはバックアップを行うアカウント以外からは読み込めないようにパーミッションを設定しておく必要があります。

]]>
0
bg http://blog.bluegold.me <![CDATA[WordPressのバックアップを Gmail に保存する]]> http://blog.bluegold.me/?p=28 2010-08-23T18:32:11Z 2008-10-18T06:34:56Z 毎日のブログのバックアップの保管場所をどこにしようかと悩んでいたんですが、Gmailに送ってしまえば良い事に気がつきました。
容量的には問題はないですし、毎日のバックアップの置き場としては問題無さそうです。

暗号化とかは後で考えるとして、とりあえず下のようなスクリプトを書いてみました。

#!/bin/sh

AFIO=/usr/local/bin/afio
MYSQLHOTCOPY=/usr/bin/mysqlhotcopy
SENDMAIL=/usr/sbin/sendmail

WORKDIR=/var/tmp
WWWDIR=/var/www
LOGDIR=/var/log

if [ -f /etc/wp_backup ]; then
    . /etc/wp_backup
fi

if [ ${MYSQL_USER:-nothing} = "nothing" ]; then
    exit 1
fi
if [ ${MAIL_FROM:-nothing} = "nothing" ]; then
    exit 1
fi

function cleanup() {
    rm -rf $WORKDIR/mysql
    rm -f $WORKDIR/$name.afz
    rm -f $WORKDIR/mysql_$name.afz
}
trap "cleanup" EXIT

name=${1:-blog}

if [ ! -d $WORKDIR/mysql ]; then
    mkdir $WORKDIR/mysql
fi

(
echo "BACKUP START: `date`"

# backup mysql
$MYSQLHOTCOPY -u $MYSQL_USER -p $MYSQL_PASSWORD $name $WORKDIR/mysql

cd $WORKDIR/mysql
find $name | $AFIO -ovz -Z -U $WORKDIR/mysql_$name.afz

# backup wordpress
cd $WWWDIR
find $name | $AFIO -ovz -Z -U $WORKDIR/$name.afz

echo "BACKUP FINISHED: `date`"
) >> $LOGDIR/wp_backup.log 2>&1

# send the backup files
(
cat <<__END__
From: $MAIL_FROM
To: $MAIL_TO
Subject: $name backup `date`

blog name: $name
date: `date`

`uuencode $name.afz < $WORKDIR/$name.afz`

`uuencode mysql_$name.afz < $WORKDIR/mysql_$name.afz`

__END__
) | $SENDMAIL -f $MAIL_FROM -t $MAIL_TO

exit 0

バックアップを Gmail に送信する事はできたので問題は解決したかと思ったんですが、Gmail は uuencode の添付ファイルを認識しないんですねぇ。手元の Apple Mail でも認識していないので単に時代遅れなだけか。

もう少し考えねば

]]>
0
bg http://blog.bluegold.me <![CDATA[blog構築メモ: nginx を設定する]]> http://blog.bluegold.me/?p=4 2010-08-23T18:31:57Z 2008-10-16T07:56:01Z

せっかく自宅にサーバを構築するので、会社では触らないソフトを使用してみる企画。

第一回はWebサーバとしてnginx を取り上げます。

nginx(えんじん えっくす)はロシアの人が作っているWebサーバで、軽量高速が特徴らしい。 WordPressの本家 でも使っているようなので、相性も良いだろうと言う事で。

nginx をビルドする

tarball を取ってきて普通に configure, make, make install だけです。

tar zxvf  nginx-0.6.32.tar.gz
cd  nginx-0.6.32
./configure --with-openssl=/usr --with-http_stub_status_module
make
sudo paco -D make install

nginx の設定

nginx.conf というファイルを編集します。nginx には Apache の .htaccess に相当する設定ファイルは無いようなので、基本的には全ての設定はこのファイルに書く事になります。シンプルと言えばシンプルですが、複数の Virtual Host の設定を1つのファイルに記述すると見通しが悪くなるので、設定ファイルを複数のファイルに分けて nginx.conf から include する事もできるようになっています。

試行錯誤した結果、このサイトの現在の nginx.conf は下のようになっています。

user  nobody;
worker_processes  3;

error_log  /var/log/nginx/error.log  info;

pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
    use epoll;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '"$status" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" "$gzip_ratio"';

    access_log  /var/log/nginx/access.log  main;
    rewrite_log on;

    gzip on;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_min_length 1100;
    gzip_buffers 4 8K;
    gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    off;

    keepalive_timeout  65;

    client_max_body_size 10M;

    # error catch
    server {
        listen       80;
        server_name _;
        root   /var/www/temp;

        index  index.html;

        auth_basic &quot;secret&quot;;
        auth_basic_user_file /var/www/htpasswd;

        access_log  /var/log/nginx/temp-access.log  main;
    }

    # load the virtual server settings
    include /usr/local/nginx/conf.d/*.conf;
}

細かい設定の話は次回

]]>
0