Tomcat標準のHTTPエラーページ

Tomcat 5.5における404 Not Foundなどのデフォルトエラーページ出力は、org.apache.catalina.valves.ErrorReportValveクラスで実装されている。
このクラスはHostコンテナのerrorReportValveClass属性で変更可能なので、errorReportValveClass=""としてしまえば、Tomcat標準のエラーページは出力されず、HTTPステータスコードだけが返るようにできるようだ。
Apache Tomcat Configuration Reference - The Host Container

このクラスのソースを見ると出力メッセージはLocalStrings.propertiesで定義されている文字列が出力されていることがわかる。

まぁ、このクラスやプロパティファイルを置き換えるよりweb.xmlでerror-page定義したほうが楽ですけど。

ApacheがTomcatからのHTTPステータスコードにしたがってエラーページを返すようになってくれれば、Apache側で定義したErrorDocumentに統一できて楽なのではないかと思う今日この頃。

PHP CGIエラー

PHPをCGIモードで動かそうと先頭に#!/usr/bin/phpを書いて拡張子を.cgiにしたら以下のエラーになりました。

Security Alert! The PHP CGI cannot be accessed directly.
 
This PHP CGI binary was compiled with force-cgi-redirect enabled. This means that a page will only be served up if the REDIRECT_STATUS CGI variable is set, e.g. via an Apache Action directive.
 
For more information as to why this behaviour exists, see the manual page for CGI security.
 
For more information about changing this behaviour or re-enabling this webserver, consult the installation file that came with this distribution, or visit the manual page.

.phpの拡張子のままでCGIとして動かすか、php.iniでcgi.force_redirect = 0を設定すればとりあえず回避できますが…。セキュリティ上問題があるのかな。もうちょっと調べよう。

ROOT.war以外のファイル名でROOTアプリケーションを利用する

サイトのTopをTomcatで処理させたい場合、ROOTとしてウェブアプリケーションを配備すればよい、ということを書きました(サイトのTop自身もTomcatに処理させる)。

でも、アプリケーションをビルドする際にROOT.warとするのもちょっとイヤだったので、プロジェクト名.warで固めたアーカイブ(someproject.war)をROOTとして利用できる方法にチャレンジしてみました。

サイトURLはhttp://www.example.com/と仮定します。

server.xmlへの仮想ホスト設定

Hostコンテナでwww.example.comを定義します。

<Host name="www.example.com" deployXML="false"
         appBase="/var/tomcat5/sites/www.example.com"
         unpackWARs="true" autoDeploy="true" 
         xmlValidation="false"
         xmlNamespaceAware="false">
</Host>

ROOT.xmlを用意

docBaseにwarファイルへの絶対パスを指定したROOTコンテキストファイルを用意します。

<Context path="" docBase="/usr/local/webapps/someproject.war" debug="0" reloadable="true">
</Context>

warファイルの置き場所はHostコンテナのappBaseには含めないようにします。
ROOT.xmlの置き場所は$CATALINA_HOME/conf/Catalina/www.example.com/配下になります(厳密には$CATALINA_HOME/conf/[enginename]/[hostname]/以下です)。

これでTomcatを起動すると/usr/local/webapps/someproject.warが/var/tomcat5/sites/www.example.com/ROOTとして展開されて、www.example.comのサイトTopとして利用できるようになります。

ちなみにこの応用として、Context定義をROOT.xmlではなくsubdir.xmlで用意すれば、www.example.com/subdirとして配備することも可能になります。

GripやEasyTagでID3タグの日本語が化ける

EasyTagを使って日本語タイトル曲のID3タグを編集していたら保存時にエラーがでました。

You have tried to save this tag to Unicode but it was detected that your version of id3lib is bugged.
If you reload this file, some characters in the tag may be not displayed correctly...
Please, apply to id3lib the patch src/id3lib/patch_3.8.3_UTF16_writing_bag.diff available in EasyTag package sources.

確かに保存したあとリロードして再表示すると化けてしまいます。
Portageでビルドしたものなので、自分でパッチ適用してビルドしなおすのは面倒だなぁ、と思っていたのですが、利用していたid3libは3.8.3-r4で、3.8.3-r5にはあたっているパッチだったようなので、emergeでアップデートして完了。

実は以前からもGripで日本語タイトルなどを含むID3タグをUTF-8で保存しても化けちゃってたのですが、今回やっとすっきりしました Laughing out loud

docBase xxxx inside the host appBase …

HostコンテナでappBaseを指定して、conf/Catalina/[hostname]/context.xmlでのdocBaseをappBaseからの相対パスのつもりで書いたらエラーになった。

A docBase xxxx inside the host appBase has been specified, and will be ignored

appBaseの中にdocBaseがいてはダメなのだったのか。

サイトのTop自身もTomcatに処理させる

タイトル変かもしれません。
http://www.example.com/のトップレベルからTomcatに処理させたい場合。Tomcatだけでウェブサーバ公開すれば、っていう突っ込みはなしでお願いします。

Apacheでは以下のように仮想ホストを設定。

<VirtualHost *:80>
  ServerName www.example.com
  JkMount /* ajp13
</VirtualHost>

Tomcat側ではappBaseである/var/tomcat5/webapps/直下にアプリを配備したとする。
サブディレクトリがあるわけではなく、/var/tomcat5/webapps/index.jspのようになっている状態。

はじめはこれでいいのだろうと思いましたが、うまくいきません。

/var/tomcat5/webapps/ROOT/index.jspのように、ROOTというディレクトリをはさむ必要があります。
Tomcatウェブサーバのトップページと同じ構造です。

ROOT.warとしてビルドしてwebappsにおいてしまうのが一番簡単です。ROOT.war以外のファイル名にしたい場合は、ROOT.xmlのContextでdocBaseに直接warファイル名を記述するようにすればよいです。

<Context docBase="/path/to/hogehoge.war">
</Context>

Eclipseのプロジェクト名のままwarにしてROOTアプリケーションとして配備したいような場合に有用でしょう。

参考:

ColdFusionとTomcatの共存

ColdFusion自体をウェブアプリケーションとしてTomcat上にデプロイする場合はこちら。

ColdFusionとTomcatを別々に動かす場合、そのままだと*.jspの制御はColdFusionに奪われてしまい、Tomcatで処理することができない。
AddHandler jrun-handlerから.jspを外しても変わらない。
実はColdFusion側でservlet-mappingの定義変更が必要になる。

上のサイトではservlet定義とservlet-mappingの定義をすべて無効にしているが、*.jspだけに限れば、その分のservlet-mappingを無効にするだけでもよいはず。

# diff -u runtime/servers/default/SERVER-INF/default-web.xml.orig runtime/servers/default/SERVER-INF/default-web.xml
--- runtime/servers/default/SERVER-INF/default-web.xml.orig 2003-05-27 11:36:10.000000000 +0900
+++ runtime/servers/default/SERVER-INF/default-web.xml 2007-06-27 23:36:37.000000000 +0900
@@ -81,10 +81,12 @@
    <url-pattern>/</url-pattern>
  </servlet-mapping>

+ <!--
  <servlet-mapping>
    <servlet-name>JspLicenseServlet</servlet-name>
    <url-pattern>*.jsp</url-pattern>
  </servlet-mapping>
+ -->

  <servlet-mapping>
    <servlet-name>JSTServlet</servlet-name>

あとはhttpd.confで

  • AddHandler jrun-handlerから.jspを外す
  • JRunConfig Ignoresuffixmapをfalseからtrueに変更(CFMX7の場合)

をおこなえばよい。

uriworkermap.propertiesでJkMount指定を動的に変更

mod_jkを使ってApacheとTomcatを連携される際、Tomcat側で処理させるURLパスをJkMountディレクティブで指定しますが、開発環境など変更が激しい環境ではこの定義変更にApache再起動が必要になってしまうので不便なときがあります。

httpd.conf

JkMount /jsp-examples/* ajp13
JkMount /servlets-examples/* ajp13

これをApache再起動なしで変更したい場合は、uriworkermap.propertiesを使って定義を外だしにしておくと便利です。

httpd.conf

JkMountFile conf/uriworkermap.properties 
JkMountFileReload 60 

uriworkermap.properties

/jsp-examples/*=ajp13
/servlets-examples/*=ajp13

こうしておくとuriworkermap.propertiesを書き換えた60秒後には変更が反映されることになります。
JkMountFileReloadが再読み込みの間隔で、デフォルトは60秒。0を指定すると無効化できます。
mod_jk 1.2.20以降で利用できます。

本番では無用なミスを避けるためにも、JkMountを使うか、JkMountFileReload 0にしておくことをお勧めしますが Sticking out tongue

ポート番号固定 ~ NFS,FTP

以前書いたかも知れないけど。

NFSのポート番号を固定にする方法

portmap本体は固定されているし(udp/111)、nfsも事実上{tcp,udp}/2049しか使われない。
しかし、rpc.statdやrpc.mountdはportmapでころころかわるので、それを決める必要がある。

CentOS 3あたりの場合、/etc/sysconfig/nfsを作って

STATD_PORT=
STATD_OUTGOING_PORT=
MOUNTD_PORT=

を書いてあげればrpc.statdとrpc.mountdのポートを決めうちにできる。

参考

FTP passiveモードのデータポート範囲を固定にする方法

vsftpdの場合、vsftpd.confでpasv_min_portとpasv_max_portを指定すればよい。

pasv_enable=YES
pasv_min_port=3000
pasv_max_port=3009

IIS 6.0のFTPの場合は

>C:\Inetpub\AdminScripts\adsutil.vbs SET /MSFTPSVC/PassivePortRange "3000-3009"

のようにする。
PassivePortRange の IIS の構成方法

Yahoo! Site Explorerに登録してみる

このサイトをYahoo! Site Explorerに登録してみました。
Yahoo!に登録操作をおこなって認証コードを含めるhtmlファイル名がわかったあとは、以下のようにノード作成して完了です。

  • 本文に<!-- 認証コード -->を含んだノードを用意して、
  • 指定されたhtmlファイル名(y_key_****.html)をAliasとして付与し、
  • XML Sitemap settingsで"Priority override"を-1にして登録

余談ですが、XML Sitemapモジュールにはsitemap生成以外にも、Googleのウェブマスターツール利用に必要な認証用URLを登録する機能が備わってます。このサイトもGoogleウェブマスターツールには登録済みでした。

さらにXML SitemapモジュールにはYahoo! Site Explorerにもsitemapを送信する機能も備わっているのですが、Googleのように認証用URL(またはMETAタグ埋め込み)を用意するところまではできません。

Yahoo!もGoogle同様に、指定された名前のHTMLファイルを配置すればよいことになっています(中には指定されたコードをコメントで埋め込む点がちょっと異なる)。
まぁ、実ファイルを用意してもよかったのですが、よくよく考えるとそんなことをしなくてもDrupalはノードを作ってしまえば済むハナシなのでした Laughing out loud