タグ「Apache」が付けられているもの

今回は、analogの設定をした際の俺専用メモです( ̄∇ ̄)ノ♪(ぇ?(笑)

# apt-get install analog
apt-getを使ってanalogをインストール

# vi /etc/analog.cfg
テキストエディタでanalogの設定ファイル(analog.cfg)を以下の様に編集:

LOGFORMAT combined
LOGFILE /var/log/apache2/access.log
LOGFILE /var/log/apache2/access.log.*
↑の設定にすることで、ログローテーションされてgz(GZIP)圧縮されたログも含めて解析してくれる(≧∇≦)

OUTFILE /var/www/axsanalyze/result.html
解析結果の出力先を設定する

INTSEARCHQUERY OFF
INTSEARCHQUERYをONからOFFにしないと、cron実行時に以下の様な警告が発生する:
/usr/bin/analog: analog version 5.32/Unix
/usr/bin/analog: Warning R: Turning off empty Internal Search Query Report
(For help on all errors and warnings, see /usr/share/doc/analog/errors.html)

それ以外のanalog.cfgの設定は割愛(ぇ?


# perl -MCPAN -e shell
cpan > install Jcode
Jcodeのインストール

Graffiti - analog関連より、analogurldecode.plをダウンロードし、analog解析結果出力先(今回は/var/www/axsanalyze/直下)に設置

# cd /var/www/axsanalyze/
# chmod 644 analogurldecode.pl
パーミッションを設定

# cd /usr/local/bin/
# touch analog.sh
# chmod 755 analog.sh
cron用のスクリプト(analog.sh)を作成し、パーミッションを設定

# vi analog.sh
テキストエディタでanalog.shを以下の様に編集:

#!/bin/bash

/usr/bin/analog

cd /var/www/axsanalyze/

perl analogurldecode.pl result.html > result_jp.html


$ crontab -e
cronを使用し、毎日10時15分にanalogを起動する様に設定:

15 10 * * * /usr/local/bin/analog.sh
※cronで正常に動作するかのテストをする場合、現在の時刻+2分で設定し、保存すること。現在の時刻+1分だとcronのリロードが間に合わず、起動に失敗することがある。


crontabで上記の設定をしたら、Ctrl + Xキー→Yキーで保存し、作業終了(≧∇≦)

その後、Apache 2で/var/www/axsanalyze/のresult_jp.htmlにあたるページにアクセスすると、日本語キーワードがエンコードされて表示された解析結果が表示される。
ただし、検索結果のURLを直接参照したい場合にはresult.htmlからアクセスすると良い。


・今回の記事を書くにあたり参照したページ:
Linux で自宅サーバ - Apache ログ解析 Analog の導入
Graffiti - analog関連
Linuxべんりな動作情報 ナレッジベース:環境設定 - cron の設定ガイド
定番Linuxフリーウェアまとめ - crontabで一分後に実行設定したが動かない

Apache Tomcatでアクセスログを出力する

Apache TomcatではWebページへのアクセスログが出力はできません。つまりどのファイルにアクセスされたとか、404エラーが発生しているパスとかの調査はできません。

...ってそう思っていた時代が俺にもありました。
マジで、かれこれ4年間本当にそう思っていましたorz

JSP & Servletコンテナだから仕方ないと思っていたのですが、最近、アクセスログ用いて調査しなくてはいけない懸案が発生したので、Google大先生に聞いてみました。
そしたら普通にあるじゃんorz

"(Tomcatのインストールフォルダ)\conf\"に存在するserver.xmlを開きます。

現在、私がインストールしているバージョンでは、341行目〜345行目に以下のような記述がされています。

<!-- <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/> -->

ご覧の通り、デフォルトではコメントアウトされていますのでコメントアウト部分の「<!--」と「-->」をさくっと削除してしまいましょう。

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>

すっきり!(某番組風)

このように設定した後、Tomcatを再起動すれば、"(Tomcatのインストールフォルダ)\logs"に「localhost_access_log.2008-06-21.txt」のようなファイルが出力されるようになります。

めでたしめでたし。

Apache Tomcatで動作したWebアプリケーションをOracle Application Server(OAS)で動作させようとしたら正常に動作しなかった問題とその解決法について紹介します。

事の発端は以下の通り:
Eclipse+Tomcatで製作したWebアプリケーションを、一度、WARファイルに固めました。
そして、OASに配置して動作試験を行いました。
しかし、EL(Expression Language)を使用しているページで式言語がそのままの文字で出力されてしまう問題が発生しました。

JSPでEL式が使えない場合の対策で書いたことを疑いましたが、そもそもWARファイルに固めているのでライブラリも含まれています。

なんだかんだで必死に原因を調べたのですが、思わぬところに理由がありました。

@ITのJ2EE 1.4に対応したweb.xmlを記述するの記事に、J2EE 1.3とJ2EE 1.4の場合のweb.xmlが書かれています。

J2EE 1.3の場合のweb.xmlは

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  ...中略...
</web-app>

J2EE 1.4の場合のweb.xmlは

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

  ...中略...
</web-app>

となっています。

問題のWebアプリのweb.xmlは以下のようになっていました:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

  ...中略...
</web-app>

もうお分かりですね、J2EE 1.3の設定とJ2EE 1.4の設定が混ざっていたんですorz

今回の原因を考察してみました。
今回Apache TomcatはVer5.0.24を使用しておりJ2EE 1.4に準拠すること前提で製作されているため元々EL式を読み込むようになっているようです。対して、OASの方はWebサーバこそApache Web Serverのソースを流用していますが、Servletコンテナはそうではないようです。そのため、Apache Tomcatより厳密にweb.xmlを解釈しているものと思われます。
<web-app>タグより前に存在するDOCTYPE宣言を見た上で、J2EE 1.3のアプリケーションと認識してしまったようですね。

説明し忘れましたが、EL式(式言語)がデフォルトで対応になったのはJ2EE 1.4からです。それ以前のバージョンはJSTL(JSP Standard Tag Library)のライブラリとweb.xmlの設定をして初めて対応になります。

OASではELは動作する情報しか出てこない中、OASの情報がそもそも少ないので今回の原因調査には何日も掛かってしまいましたorz
それでも解決できて何よりでした。

Apache Tomcat 5.0.28+Strutsを使用しているとちょっと困った症状に出会いました。

StrutsのActionサーブレットでHttpServletRequest#getSession(false)のメソッドを用いても、新しいセッションを取得してしまうようです。ちょっとググってみると、Strutsでではないのですが、同様の問題で悩んでいる人がSeasarのMLでもいる模様です。

例えば、

HttpSession session = reqest.getSession(false);
if(session == null) {
// セッションタイムアウトのときの処理
}
を期待して、コーディングするとセッション切れのときは新しいセッションが作られてしまいセッションタイムアウトのときの処理が実行されません。

これを回避するには、あらかじめsessionに何かのオブジェクトを格納しておく方法をとると良さそうです。

例えば、ログインのActionServletにおいて

HttpSession session = req.getSession(true);
session.setAttribute("hoge","何かの文字列");
としておき、ログイン以外のServletにおいては、
HttpSession session = req.getSession(false);
if( (session == null) || (session.getAttribute("hoge") == null) ) {
// セッションタイムアウトのときの処理
}
とすると、新しいセッションが作成されたときに、HttpSession#getAttribute("hoge")がnullにならないのはログイン用のサーブレットを実行し、セッションタイムアウトしていない場合に限定されるので、うまく動作してくれます。

でも、状況的にApache Tomcat 5.0.28のバグの可能性が高そうだなぁ...


Strutsとセッションの話題をしたので、ついでにもう一つ良さそうな話題を紹介します。

@IT - 第4回 安全なセッション管理を実現するために
ここで公開されている内容は、Strutsのログインシステムを作る上で結構役に立ちそうです。
あるユーザでログイン後、セッションが切れる前にブラウザのログインページに戻って別のユーザでログインすると、前のユーザのログイン情報が残って危険な場合も考えられます。そのような問題も防げそうですね。
向こうの記事で十分説明されているので、敢えてこちらは講評だけにしておきます。

WebサーバにApacheを使用していないこのサーバにとっては関係ない話ではありますが、この対策は必要だなと感じていたので記事として紹介しておきます。

@IT - 第1回 たった2行でできるWebサーバ防御の「心理戦」

ちょっとHTTPやTCP/IPの仕組みに詳しい人ならご存じなのですが、HTTPのレスポンスヘッダという箇所にそのサーバで使用しているWebサーバやそのバージョンが分かるのです。
Netcraftというサイトで検索してみると、あのサーバがあのWebサーバやあのOSを使ってるんだ〜(*//▽//*)ということが簡単に分かります(何)

しかし、Webサーバはときに脆弱性を持っているバージョンがあります。当然、脆弱性があるバージョンを使用しない、使用しているWebサーバのバージョンに脆弱性が発見されたらバージョンアップするという作業は必要です。しかし、このような情報をむやみに公開しないというのも、クラックされにくいWebサーバにするちょっとした作業なのです。

上記のページで公開されている手法は「HTTPリプライヘッダの抑制方法」と「エラーページのフッタの抑制方法」です。
それ以外にもセキュリティ強化のための小さなコツつぉいうのはいっぱいあるのでしょうけど、それに関してはApache関係のブログの偉い人に任せます(ぇ?

そんなわけで、Webサーバのセキュリティには注意しましょ〜( ̄∇ ̄)ノ♪

StrutsからServletContextクラスを取得するには

MVCモデルで知られているJSP&ServletのStrutsフレームワークですが、Contorollerの部分にあたるActionを作成しているときにちと困ったことになりました。
普通のサーブレットの場合、サーブレットの中でServletContextを呼び出すには、

ServletContext sc = getServletContext();

で良いわけですが、Strutsの場合は上記のような構文をexecuteメソッドの中に記述しても動きません。
せっかくStrutsのプラグインを用いてあるクラスをアプリケーションスコープに格納したのに取得できないなんてかなりorzな訳ですが。

ググってみたところ、上記のコードにもうひと味付けることで解決できました。

ServletContext sc = getServlet().getServletContext();
Foo bar = (Foo)sc.getAttribute("bar");

例えば、上記のコードのようにすれば、StrutsのActionサーブレットにおいてもApplicationスコープから値を取得できます。

めでたし。めでたし。

JSPでEL式が使えない場合の対策

久々のblogネタを投稿してみる。

最近、JSPをよくいじっているわけですが、JSPにはJSTL(JSP Standard Tag Library)の標準タグライブラリとEL(Expression Language)式が使えると便利かなと思いました。

JSTLとは、JSPで使えるカスタムタグライブラリの一つで、JakartaプロジェクトによりJSPで便利なタグをひとまとめにしたライブラリです。
その中でよく使われるのがCoreタグライブラリとEL式です。

JSTLに関する詳しい解説はKishida's SITE 〜 Java入門講座 - JSTL(標準タグライブラリ)Javaの道(Java入門・リファレンス) - Javaの道:Taglibs(2.Standard Taglibsの概要)に丸投げしますが、今回はそのEL式が使えない場合のお話。

JSTLを使うには、JakartaプロジェクトのページからJSTLのファイルをダウンロードし、サーブレットコンテナ(Tomcat)のWEB-INF\libに「standard.jar」と「jstl.jar」を設置してやることで完了です
...って思ってたんですよ。

ええ、これだけでも<c:out>や<c:forEach>などのタグライブラリは動くんです。
でもね、でもね。
これだとEL式が動いてくれなかったんですねorz

${true}がそのまま「${true}」って表示されちゃうんです( ̄□ ̄;)!!

そこで色々ググってみたところ、似たような問題で悩んでいる方はいました。

wakasa.org - ●Tomcat5.5でtaglib内でEL式が動かない

ただ、俺の場合これだけじゃありませんでした。
「standard.jar」や「jstl.jar」を「WEB-INF\lib」に設置するだけではなく、「web.xml」にの設定も追加しましょう。

Tomcat5の新機能第2回:EL式とタグファイルに書かれていますが、

<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/tld/c.tld</taglib-location>
</taglib>

を忘れると、JSTLが使えるのにEL式が使えないという不思議な体験ができます。
結局のところ俺がきちんと説明書見てなかったからこんな事態になっただけなんですけどねorz

というわけで、自分の備忘録とともに同じ問題で苦しんでいる人の助けになれば良いかなと思います。

久々にblogを書く機会がバグへの対処とはorz

2006年08月27日に投稿した「sendRedirectで日本語文字のURLが入っている場合の対処」の記事の方法だとURLによりExceptionが発生してしまうようです。
URL中に半角スペースを含むURLの場合RFC2396に違反するため、エスケープしなければいけません。
実はJ2SDK 1.4までは半角スペースを含むURLであってもURIクラス等でインスタンスを作成可能でしたが、JDK 5.0からはRFC2396に従いあらかじめエスケープしなければいけなくなったようです。

String strUrl = "http://traincat.net/blog/neko/電車猫の blog/日本語 ファイル名.doc".replace(" ","%20");
URI uri = new URI(strUrl);
response.sendRedirect(uri.toASCIIString());

この様にすれば、半角スペースが「%20」と変換されるのでURISyntaxExceptionやMalformedURLExceptionなしにURIクラスのインスタンスを作成できそうです。

めでたしめでたし。


・参考文献:
SMG-Java トラブルシューティング
 + JDK1.3で動作していたプログラムをJDK1.4で実行したところ、Naming.bind()で例外が発生しました。