TomcatをWindowsからLinuxへ移行する手順

WindowsEclipseで開発したTomcatのアプリをLinux環境へ配置する手順についてメモしておく。2つのサイト(仮にa-company.co.jp、a-service.jpとしておく)の動的なホームページを1台のLinuxサーバ上で利用したかったのだがVirtualHostの設定がよく分からず苦労させられた。Fedoraでは、Tomcatの環境を作ることは非常に容易だ。


> yum install tomcat6 tomcat6-webapps tomcat6-admin-webapps
を実行するだけだ。javaもOpenJDK1.6.0がFedoraには同梱されている。JDKはsun(いまはoracle)のものに置換したほうがいいというネット情報が多々あったが、よく分からないのでOpenJDKのままとしている。結果的には問題なく動作しているのでそのままだ。TomcatApache(httpd)と連携しないといけないが、Apache(httpd)は動作しているという前提で話を進める。Apache(httpd)からはmod_proxy_ajpTomcatに連携してくれる。

Windowsで開発したwebapp一式をLinux側に渡し、所定の場所に配置する。


Linux
+-- /etc/httpd/
| +-- conf/
| | +-- httpd.conf
| +-- conf.d/
| +-- proxy-ajp.conf
+-- /var/www
| +-- html
| +-- a-company/ // httpd利用の場合の静的ページ
| +-- a-service/ // httpd利用の場合の静的ページ
|
+-- /usr/share/tomcat6/
+-- bin/
+-- conf/ // --> /etc/tomcat6
| +-- context.xml
| +-- server.xml
| +-- tomcat-users.xml
| +-- web.xml
| +-- Catalina/
| +-- localhost/
| +-- ROOT.xml
| +-- a-company.xml
| +-- a-service.xml
+-- lib/
+-- logs/
+-- webapps/ // --> /var/lib/tomcat6/webapps
+-- ROOT/ // 動的ページをここに配置
+-- a-company/ // 動的ページをここに配置
+-- a-service/ // 動的ページをここに配置
いろいろと問題が生じたのでメモしておこう。

問題1: 外部ファイルが参照/保存できない。

ありがちなことだがDB以外で参照/保存しているxmlファイルやイメージファイルが読み書きできないということがあった。外部のxmlファイルを読み込んでhtmlを生成しているのだが、文字化けのおまけつきだ。WindowsではSJISで作成していたファイルが、Linuxでは文字化けするので、まとめてnkf -wを用いてutf8に変換した。xmlファイルの編集やグラフ表示のためのイメージファイルを配置するディレクトリに書き込み権限を設定していなかったという初歩的なこともあった。


> chmod 777 a-dir
> cd a-dir
> chmod 666 *.xml
> nkf -w --overwrite *.xml

問題2: Shift-JISとShift_JISを間違えていた。

ハイフンは間違いで、アンダースコアが正しいと知った。htmlやjspの中でのencoding指定で結構な箇所(というかほとんどすべて)でShift-JISと表記していた。Another HTML-lint gatewayというHTMLを診断してくれるツールで指摘されて初めて気づいた。以下のような箇所だ。


<?xml version="1.0" encoding="Shift_JIS"?><meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
実は、サイトのページではDOCTYPEを何にして開発すればいいか、かなり悩んだ。Another HTML-lint gatewayというツールは指定のDOCTYPEに従っていろいろと細かい点を指摘してくれるので、どのDOCTYPEが適切なのかを試行するのにも役立った。結果的には以下の2つを使い分けた。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
XHTML 1.0 Transitionalで統一したかったが、どうしてもtableやtdタグでheightを制御したかったので古いHTML 4.01 Transitionalも併用することにした。

問題3: $CATALINA_HOMEが/rootになっていた。

なぜだが分からないが$CATALINA_HOMEが/rootになっていた。/var/lib/tomcat6に変更した。もとから個別に設定しなければならないものだったのかもしれない。


> CATALINA_HOME=/var/lib/tomcat6
> export

問題4: /ROOTに配置したindex.htmなどが読み込まれない。

webapps/ROOTやwebapps/a-companyに配置したindex.htmが読み込まれず、tomcatのデフォルトのindex.htmlが開く。index.htmlは配置していないのにURLに http://www.a-company.co.jp/ のように指定してファイル名を省略すると、通常そのルートパスにあるindex.htm,index.html,index.jspなどが勝手に検出されるはずだが、tomcatのデフォルトに飛んでいってしまう。ファイル名を省略せずに http://www.a-company.co.jp/index.htm を指定すると問題ないのにだ。


/usr/share/tomcat6/
+-- conf/ // --> /etc/tomcat6
+-- Catalina/
+-- localhost/
+-- ROOT.xml
+-- a-company.xml
+-- a-service.xml
にROOT.xmlやa-company.xmlを作成し、以下のように記述しておくといいと分かった。


ネット情報によるとconf/context.xmlでの指定ではダメで、アプリごとに上記のようにxmlファイルを作成しておく必要があるらしかった。この指定がないとtomcatのデフォルトのindex.htmlに飛ばされる。

問題5: VirtualHostの設定がうまくいかない。

これが最大の問題で、実はいまだに期待した状況にはなっていない。なんとか騙し騙し動作しているに過ぎない。VirtualHostの指定とmod_proxy_ajpの指定が正確に理解できていないこともあり、うまくいかない。1つのサイトをmod_proxy_ajpを使ってtomcatと連携するのは容易なのだが、2つのサイトを連携するにはVirtualHostを利用するばずだ。現在は、httpd.confに以下のように記述している。proxy_ajp.confは作成したが中身はすべてコメントとしている。httpd.confのVirtualHost指定でProxyPassの指定も兼ねられそうだからだ。


NameVirtualHost www.a-company.co.jp:80
NameVirtualHost a-service.jp:80

DocumentRoot "/var/lib/tomcat6/webapps/a-company"
ServerName www.a-company.co.jp
ErrorLog logs/a-company-error_log
CustomLog logs/a-company-access_log common
ProxyPass /a-company ajp://localhost:8009/a-company/
ProxyPass / ajp://localhost:8009/a-company/
ProxyPassReverse / ajp://localhost:8009/a-company/


DocumentRoot "/var/lib/tomcat6/webapps/a-service"
ServerName www.a-service.jp
ErrorLog logs/a-service-error_log
CustomLog logs/a-service-access_log common
ProxyPass /a-service ajp://localhost:8009/a-service/
ProxyPass / ajp://localhost:8009/a-service/
ProxyPassReverse / ajp://localhost:8009/a-service/

この記述により、http://www.a-company.co.jp/ でアクセスされたときはa-companyのサイトへ、http://a-service.jp/やhttp://www.a-service.jp/ でアクセスされたときはa-serviceのサイトへ誘導できる。
しかし、問題なのは、strutsで画面遷移を各アプリのルートパス(webapps/a-companyなど)からの相対パスで指定しているとき、1階層上のwebappsからの相対パスに置換されてしまう事態が起きるのだ。
たとえば、webapps/a-company/profile/index.htm に遷移したいのに、webapps/a-company/a-company/profile/index.htm に遷移しようとする。a-companyが1つ余計だ。ajp://localhost:8009/ に配置した場合、つまりtomcatではwebapps/ROOT に配置することになるが、この場合には問題とならない。特定のサブディレクトリであるwebapps/a-companyなどを ajp://localhost:8009/a-company/ のように指定した場合に生じることが分かっている。仕方がないので

ProxyPass /a-company ajp://localhost:8009/a-company/   #(1)
ProxyPass / ajp://localhost:8009/a-company/ #(2)
のように2つ並べて動作上は回避できている。しかしこの場合、webapps/a-company/profile/index.jsp にアクセスしようとすると、http://www.a-company.co.jp/profile/index.jsp となってくれず、http://www.a-company.co.jp/a-company/profile/index.jsp と表示されてしまうのだ。本来は(2)だけにしたいのだが(1)のProxyPass宣言がないと、webapps/a-company/a-company/profile/index.jsp というファイルを参照しようとしてNot foundとなる。(1)(2)の両方を指定しておくとなんとか動作は正常なのだが、ルートパス名a-companyがブラウザのURLに露出してしまうのだ。strutsの設定や利用方法がおかしいのか、tomcatの設定がおかしいのか、httpd.confの設定がおかしいのか、まだ判断できていない。