各種言語の文法

以前のブログで各種言語の文法がBNFとかで書いてあるサイト群をメモりました。
でも、SQLのBNFリンクは入れてなかったことに最近気づいたので、改めてこちらに記事を作りなおしておきます。

C/C++, Java, COBOL, Prolog, SmallTalk
http://www.csci.csusb.edu/dick/samples/index.html
Python
http://www.python.jp/doc/2.3.5/ref/
Ruby
http://www.ruby-lang.org/ja/man/html/_B5BFBBF7BNF_A4CBA4E8A4EBRuby_A4CECAB8CBA1.html
PHPPHPの場合、言語仕様では文法が決まってないそうです。リンク先は、有志の人がそれっぽく作った文法ということになります。
http://www.phpcompiler.org/doc/grammar.html
ECMAScript
http://tomcopeland.blogs.com/EcmaScript.html
Javascript
http://www.mozilla.org/js/language/grammar14.html
ActionScript
http://www.m2osw.com/en/action_script.html#grammar
C#
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf
  • Annex A. Grammar参照
SQL
http://savage.net.au/SQL/

なお、正確な言語文法が知りたい方は、それぞれの言語仕様書を見た方が良いです。上記リンク先は、ある程度文法がわかればよい人向けです。

PHPインタラクティブモードの便利な使い方

ブログに書くネタは結構あるんだけど、整理してから書こうとするとなかなか書けない・・・。

しょうがないんで、ネタは小出しに書くことにしよう。

PHPで何かのライブラリのオブジェクトを使う際、どんなメソッドがあるのかよくわからにことが多々あります。リファレンスを見りゃいいんですが、それが面倒な時は、PHP (CLI)のインタラクティブモードを使うと便利です。

インタラクティブモードの場合、statementが完成するたびに(セミコロンで区切られるたびに)処理が実行されるようです。

[PHP]
$ php -a

close
[1] => getAttribute

[24] => expand
)
(Windowsだと Ctrl-Zで終了)

$
[/PHP]

インタラクティブモードで、よく利用する関数は以下 (全部、リフレクション系関数)、

  • get_class_methods( mixed $class_name )  [クラスのメソッドを配列として返す]
  • get_object_vars ( object $object ) [オブジェクトのプロパティを配列として返す]
  • get_declared_classes(void) [定義済のクラスの名前を配列として返す]
  • get_defined_functions(void) [定義済の関数の名前を配列として返す]
  • get_defined_vars(void) [定義済の変数の名前を配列として返す]
  • get_loaded_extensions(void) [コンパイル/ロードされている全てのモジュールの名前を配列として返す]
  • get_extension_funcs ( string $module_name ) [あるモジュールの関数名を配列として返す]

dmesgによるHDDデバイス名探し

ひさびさ更新。

今回は、HDDデバイス名をdmesgコマンドで調べる時の事を考えてみます。
dmesgで出力されるメッセージは結構長いので、grepなどの検索を利用したいのですが、HDDがPATA(=IDE)接続のときと、SATA接続のときで、検索パターンを変えないといかんです。そのパターンについて以下に記述。

なお、以下の方法はLinux Kernel2.6系の話です。
Linux Kernel2.4系だと、SATAもhdaとかで認識するらしいので。

* HDDがPATAの場合
dmesg | grep hdを使います。

$ dmesg | grep hd
    ide0: BM-DMA at 0x1810-0x1817, BIOS settings: hda:DMA, hdb:pio
hda: TOSHIBA MK4025GASL, ATA DISK drive
hda: max request size: 128KiB
hda: 78140160 sectors (40007 MB), CHS=65535/16/63, UDMA(100)
hda: cache flushes supported
 hda: hda1
SCSI device sda: 40088160 512-byte hdwr sectors (20525 MB)
SCSI device sda: 40088160 512-byte hdwr sectors (20525 MB)

hda: TOSHIBA MK4025GASL, ATA DISK drive
っていうところで、型番がわかります。

* HDDがSATA接続の場合
HDDはsd~で認識されるので、dmesg | grep sd としたいところですが、
それだと型番が表示されません。とはいえ、grep sdで引っかかる行の直前に型番が表示されるので、
dmesg | grep -B 5 sd
として、grepでマッチした行の前5行分も表示すると良いでしょう。lessで見ながら検索するのもお勧め。

$ dmesg | grep -B 5 sd
ata1.00: ATA-8: Hitachi HDP725050GLA360, GM4OA52A, max UDMA/133
ata1.00: 976773168 sectors, multi 16: LBA48 NCQ (depth 0/32)
ata1.00: configured for UDMA/133
  Vendor: ATA       Model: Hitachi HDP72505  Rev: GM4O
  Type:   Direct-Access                      ANSI SCSI revision: 05
SCSI device sda: 976773168 512-byte hdwr sectors (500108 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
SCSI device sda: 976773168 512-byte hdwr sectors (500108 MB)
sda: Write Protect is off
sda: Mode Sense: 00 3a 00 00
SCSI device sda: drive cache: write back
 sda: sda1 sda2 sda3
sd 0:0:0:0: Attached scsi disk sda
--
ata4.00: configured for UDMA/133
  Vendor: HL-DT-ST  Model: DVDRAM GH20NS10   Rev: EL00
  Type:   CD-ROM                             ANSI SCSI revision: 05
  Vendor: ATA       Model: ST3750640AS       Rev: 3.AA
  Type:   Direct-Access                      ANSI SCSI revision: 05
SCSI device sdb: 1465149168 512-byte hdwr sectors (750156 MB)
sdb: Write Protect is off
sdb: Mode Sense: 00 3a 00 00
SCSI device sdb: drive cache: write back
SCSI device sdb: 1465149168 512-byte hdwr sectors (750156 MB)
sdb: Write Protect is off
sdb: Mode Sense: 00 3a 00 00
SCSI device sdb: drive cache: write back
 sdb: unknown partition table
sd 3:0:0:0: Attached scsi disk sdb
--
...

まず、注目する箇所は以下、
Vendor: ATA Model: Hitachi HDP72505 Rev: GM4O
Type: Direct-Access ANSI SCSI revision: 05

自分の経験上、Vendor: ATA, Type: Direct-AccessだとHDDなのだと思います。
型番はModel: ~ と出力されるのですが、場合によって型番の末尾が省略されるので注意です。
今回の場合、型番の正式名称は、
ata1.00: ATA-8: Hitachi HDP725050GLA360, GM4OA52A, max UDMA/133
の行のHDP725050GLA360になります。

もうひとつのHDDは省略されておらず、
Vendor: ATA Model: ST3750640AS Rev: 3.AA
Type: Direct-Access ANSI SCSI revision: 05
から、ST3750640ASになります。

SATA HDDがsda等として認識される理由 (SCSIに見える理由)

http://okwave.jp/qa3351535.htmlより引用:

    カーネルのファイルシステムの階層構造の問題で,
    SATAの最下層のデバイスドライバsata-strageなどがその上位のプロトコルドライバとしてscsi_modを指定しているためです。
    つまりアプリから見るとSCSIディスクにみえるのはsata-strageがSCSIプロトコルをエミュレーションしているためです。

    これに対してIDEデバイスはディスクドライバとしてide-diskなどがありますからちゃんとIDEに見えます。

    USBメモリなども同じ理由でSCSIに見える場合が多いと思います。

HDDインターフェイスの名称

Wikipediaによると、
HDDインターフェイスの名称は出現年の古い順に
IDE(製品会社独自の規格名) -> ATA(統一規格名) -> SATA(統一規格名)、PATA(=ATA)
っていうことらしい。
IDEをベースにATA規格ができたから、IDE = ATAと呼ばれるようになったようです。
その後、新規格のSATAが出てきて、昔のATAをPATAと呼ぶようになったと。

ブラウザキャッシュの無効/有効

ブラウザキャッシュは意識して設定しないと簡単に無効になったり有効になったりしてしまいます。
必ず無効にしたい or 必ず有効にしたいというポリシーがあるなら、きちんとした設定が必要です。

・ブラウザキャッシュを無効する方法
http://blog.knockoutmarch.com/2008/02/06/2323.html
より引用
[html]






[/html]

・ブラウザキャッシュを有効にする方法

そもそも、あるリンクをクリックした後のブラウザキャッシュ挙動には2パターンあることに注意
1. キャッシュしてあるコンテンツが新しくなっていないかwebサーバに問い合わせる。新しくなってなければキャッシュを使う。 (Last-Modified & If-Modified-Since & 304 status)

2. webサーバに問い合わせず、キャッシュをそのまま使う (Expires or Cache-Control: max-age)

しかも、ブラウザによってhttpレスポンス/リクエストヘッダのLast-Modified, Expiresなどの解釈や優先順位が違うことに注意。
http://labs.cybozu.co.jp/blog/kazuho/archives/2006/02/utilizing_cache.php
http://fdays.blogspot.com/2007/11/ie6cache-controlcache.html

以上を踏まえると、PHPコンテンツに対して、ブラウザキャッシュを上記2番の方法で一定時間有効にしたいときは下記のようにしとけば良さそう ( $interval 秒だけキャッシュを有効にしたいとする)
[PHP]
header( “Expires: ” . gmdate( “D, d M Y H:i:s”, time() + $interval ) . ” GMT” );
header( “Cache-Control: max-age=” . $interval);
header( “Pragma: cache”); // no-cache以外にすればOK
[/PHP]

キャッシュを無効にしたい場合も、有効にしたい場合も、同じようなhttpリクエスト項目を複数指定する必要があるのがだるい・・・

レンタルサーバsakuraにsymfonyをインストール

私はレンタルサーバとしてsakuraを使ってます。

PHPフレームワークのsymfonyをsakura上で動かしたかったので、インストール方法を探ってみたところ、すでにやってる方がいらっしゃったのでサクッとインストールできました。

http://ueblog.natural-wave.com/2008/06/15/sakura-symfony/

はてなからWordPressへ移行

はてなダイヤリーは自由度が少ないので、レンタルサーバ借りて自分でWordPressを立ち上げることにしました。

以前書いていた、はてなダイヤリーはこちらです。そのうち、記事も移動させたいなあ。

Movable Typeも試してみたけど、Perlはほとんど扱ったことがないので、改造しづらいです。

WordPressはPHPで書かれてるので改造しやすそうだったので採用しました。

下記サイトを見ながら適当にWordPress入れました。
http://s2g.jp/masatsu/log/2008/0323224122.htm

英語学習サイトiknow

最近、英語の勉強をしようとiknowを始めました。詳しくは下記リンク先をどうぞ。

http://www.iknow.co.jp/

個人的には脳トレに近いノリを感じています。導入はスムーズにできますが、継続してやれるかは、私のモチベーション次第ですね(当たり前か・・・)。

とりあえず、TOEICチャンネルの「まずは!TOEIC基礎・総仕上げ」をやってます。難易度が高いチャンネルにも興味があったので、ためしに、留学実現チャンネルのdictationをやってみたら、文章が長すぎて挫折しました・・・。

iknowは現在無料です。収入は広告費と有料サービスから得るそうですが、どの程度うまくいくのかが気になるなあ。

http://www.iknow.co.jp/free

PHPはリファレンスカウントGCを使っているというお話

バイト先でHyper Estraierを使った全文検索機能を実装する機会がありました。

そこで、EstraierPureライブラリを使って、PHPスクリプトを通じてHyper Estraierにテキストのインデックスを作成させるようにしたのですが、複数のテキストファイルをインデックス化する途中で下記PHPエラーが出てPHPプロセスが終了しました。

PHP Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 22423 bytes) in /var/lib/Services/HyperEstraier/Utility.php on line 278

なんかメモリが足りなくなっとるらしい。

また、インデックス化に失敗したテキストファイルから実行再開すると、そのテキストのインデックス化に成功した後、別のテキストファイルをインデックス化する時に同様のエラーが出てプロセスが終了します。

以上の結果からメモリリークの疑いが強いのですが、EstraierPureは100%PHPコードなので、PHPのメモリ管理に原因がありそうです。

ということで、PHPのメモリ管理方法を調べてみたところ、リファレンスカウント方式のGCだと判明しました*1。今までTracing GC系だと思ってたよ・・・

現在、PHPのリファレンスカウントGCは循環参照しているオブジェクトは解放できません。おそらく、EstraierPureの中で循環参照があって、そのオブジェクトが解放されずにリークし、最終的にメモリが足りなくなるのでしょう。

PHP6からは、Pythonでも使われているCycle Collector*2が実装されるそうなので*3、今回の問題もPHP6を使えば解消します。

ってまだPHP6は正式リリースされてないし、今更PHP5から変えられるかーっていう状況。PHP5.3でもCycle Collectorが導入されるといいなあ。・・・結局リリース待ちなわけだけど。

*1:PHPカンファレンス2007 「PHPの今とこれから 2007」:http://www.php.gr.jp/seminar/20070901/data/phpcon070901a.ppt

*2:Cycle Collectorアルゴリズムの論文: http://www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf

*3:PHPカンファレンス2007 「PHPの今とこれから 2007」:http://www.php.gr.jp/seminar/20070901/data/phpcon070901a.ppt

tracの移行作業

少し前のことですが、tracの移行作業(subversionのリポジトリ移行も含む)を行いました。

今後、同じ作業をどこかでするかもしれませんので、忘れないようにメモ。

例として、

  • trac-projというtracプロジェクト
  • svnrepというsubversionリポジトリ

を別マシンに移行する場合を考えます。tracのDBはsqliteとします。

まず、移行元のマシンでtrac-projとsvnrepのバックアップを取ります。他ユーザのアクセスとバックアップが競合しないようにhotcopyコマンドを使ってロック+バックアップします。

$ trac-admin ~/trac/trac-proj hotcopy trac-backup
$ tar cvfz trac-backup.tar.gz trac-backup

$ svnadmin hotcopy ~/svn/svnrep svn-backup
$ tar cvfz svn-backup.tar.gz svn-backup

ディレクトリ位置は適当です。自分の環境に合わせて変更すること。

移行先に両tar.gzファイルを持って行き、展開。なお、リポジトリの位置が移行元と違う場合、移行先でtrac-proj/conf/trac.iniの修正が必要。

例えば、以下のような感じ。

repository_dir = /home/user/svn/svnrep
↓
repository_dir = /var/svn/svnrep

移行先tracのバージョンが移行元より新しい場合、以下コマンドを使ってtracプロジェクトの更新をしておく。

$ trac-admin trac-proj upgrade

apacheの設定とかに関しては、以下リンク先を参照 (Trac月プロジェクト*1における移行作業の話だけど、十分役に立ちます)

http://sourceforge.jp/projects/traclight/wiki/Install

なお、apache2.2より、httpd.conf内の”AuthDigestFile”が”AuthUserFile”に変わったので注意すること。

*1:Windows上にTracに必要なパッケージ(trac, apache, subversion等)をまとめて入れるソフトウェアの開発プロジェクト

XForwardingのやり方

ついでに、ssh XForwardingのやり方も調べました。

設定方法

例として、sshdが動いているRemoteマシンと、そこへssh接続するLocalマシンがあり、RemoteマシンでXクライアント(emacsとか)を起動し、LocalマシンのXサーバで表示する場合を考えます。

Remoteマシンのsshd_configを以下のように書き換えます

X11Forwarding noX11Forwarding yes

設定を有効にするため、sshdを再起動します。

# /etc/init.d/sshd restart

あとは、Localマシンから以下のように接続します

$ ssh -X user@remote.domain

sshでRemoteマシンに接続した後、以下のような出力があればXForwardingに成功しているはず。

$ echo $DISPLAY
localhost:10.0

$ emacs     #Localマシン上にemacsのウインドウが表示される

なお、ssh接続時に、~/.Xauthorityが生成されない場合、xauthプログラムが入ってない可能性がありますので、yum install xauthとかで入れて、接続しなおしてください。

やってみた感じ、通信データ量はかなり多いみたいですね。

回線が細いと、emacsの起動をするだけで数分かかります。

また、XForwardingの場合、nohupでXアプリを起動しても、sshコネクションを終了するとXアプリも終了してしまいます。

おそらく、sshコネクション終了時にRemoteマシン上に作られた擬似Xサーバも終了してしまうからでしょう*1

環境変数DISPLAYについて

環境変数DISPLAYは、”:0.0″(通常)だったり、”localhost:10.0″(XForwarding)だったりしたんですが、値の意味が気になったので色々検索してみると、解説が見つかりました。

以下引用*2

環境変数`DISPLAY’の書式は`HOST:DISPLAY.SCREEN’です。HOSTはXウィンドウシステムのサーバーマシンの名前、DISPLAYは同じマシンの別のサーバーと読者のサーバー(X端末)を区別するために任意に割り振られた番号、SCREENは稀にしか使いませんが1つのXサーバーで複数の端末画面を制御する場合に使います。ピリオドとSCREENは省いてかまいません。指定する場合、SCREENは普通はゼロです。