7月27日はシステム管理者の日らしい(公式?サイト)。
普段ハードに働いているシステム管理者に感謝しましょうって感じ。こういうのがもっと増えるとシステム管理者もちょっとは救われるかも?
7月27日はシステム管理者の日らしい(公式?サイト)。
普段ハードに働いているシステム管理者に感謝しましょうって感じ。こういうのがもっと増えるとシステム管理者もちょっとは救われるかも?
XOOPSを使ってたサイト、かなーり長い間放置していたらスパムの投稿が2000件以上あった。ちょっと探したけどユーザーインターフェースから20個とか100個とかまとめて消す機能がなかったのでDBを直接いじって削除した。
で、今後は少し対策しようと思って色々ネットを探した。簡単に情報が見つかるかと思ったけど、意外に情報が分散してたり不十分だったりして、思った情報を見つけるのに丸1日位かかった気がするので、まとめてみる。
○Protectorのインストール
Protectorというモジュールは名前の通り色々な攻撃からXOOPSを保護してくれるもの。
・xoops_trust_pathの設定
Protectorをインストールする前に、xoops_trust_pathというものを設定しなければいけない。これはドキュメントルートとは独立していないといけない。詳しい設定方法はこちら。
・ファイルのアップロード
このページからProtectorというモジュールをダウンロード。
Protectorのパッケージを解凍するとhtmlとxoops_trust_pathの2つのディレクトリがある。
xoops_trust_path内のディレクトリを先ほど設定したxoops_trust_pathに入れる。
html以下のディレクトリは通常のモジュールと同じ場所に入れる。
通常のモジュールのインストールの仕方については、こちらのページが分かりやすかった。
・インストール
後はいつもと同じように、管理画面からモジュール管理に進んで、通常通りインストール。分からない人は先ほどのページを参考に。
後はmainfile.phpを修正。詳しくはこちら。バージョンによって若干違うかもしれないけど。
・RBLで弾く、2バイト文字が無い場合は弾く
ここまでやっただけでもそれなりに効果はあったんだけど、何かイマイチものたりない。ブラックリストとかを使用したいけど…とか思ってたら、Protectorのパッケージに入ってた。単にデフォルトでは無効になってるだけ。
xoops_trust_path\modules\protector\filter_disabled 内に入っている2つのファイルを filter_enabled に移動するだけで、これらの2つのモジュールが有効になる。
自分用メモ
sprintfの書式指定の引数(って呼ぶのかな?)、%d, %sとかいっぱいある。基本的な書き方は覚えてるけど、細かい事は覚えてない。man sprintfでもいいけど若干分かりにくいのでこのページを良く参考にしてる。
サッカーのアジアカップ、オーストラリア戦は1-1のまま決着が付かずPK戦で日本勝利!
これに関してはスポーツニュース等などでも色々報じられているので、試合についてはここでは特に書かない。
○オーストラリアのAFC移籍
サッカーに詳しくない人にとっては
「なんでオセアニアのはずのオーストラリアがアジア杯に参加するの?」
っていう疑問が当然あるのでちょっと書くと、オーストラリアはオセアニアサッカー連盟(OFC)を「脱退」して、去年からアジアサッカー連盟(AFC)に加盟している。
なんでオーストラリアがアジア?その理由は主に2つ(?)
・W杯に出場しやすくなる
・オセアニアに比べてレベルの高いアジアで自国のレベルアップを図る
W杯に出場しやすくなるってのは、今まではオセアニア予選で1位のチームは南米の5位とプレーオフを戦わなければいけなく、南米5位は結構な強豪が出てくるので、プレーオフ敗退でW杯出場を逃すってケースが過去に多かった。
2番目の理由に関しては、オセアニアではオーストラリアが実力で抜けていて、そこから少し離れてニュージーランド、残りは小国ばかりという状況で、地理的に離れているという点からも強豪国との強化試合がなかなか組めないという事。
・その他の移籍例
1992年にイスラエルがAFCからUEFA(ヨーロッパサッカー連盟)に移籍した。理由はアラブ諸国(AFC加盟)との政治的関係悪化。
その他、旧ソ連解体後、中央アジア諸国はAFCかそれともソ連が加盟していたUEFAか、どちらに加盟するか選択出来たが、全てAFCに加盟。ただ、その後カザフスタンはUEFAに移籍。
移籍とは違うけど、地理的にはアジア(とヨーロッパの境)に位置するトルコは文化的にも地理的にもヨーロッパとの繋がりが強い、レベルの高いところで自国を強化したいという意図から、昔からUEFA加盟。
○オーストラリアがアジアに入る事で
2006年W杯に出場した4カ国(日本、韓国、イラン、サウジアラビア)にオーストラリアを加えた5カ国が今後しばらくはアジアのサッカーの覇権を競っていく事になりそう。
日本とは地理的に離れている中東諸国に対して、日本のサッカーファンは特に特別な思い入れはなく、韓国がサッカーでは唯一最大のライバル。ただ、その韓国もW杯4強以降はぱっとした成績を残せていなく、停滞している感は否めない。最近では日本の方が若干先を行っているようにも思える。
そんな中、2006年W杯で日本を破ったオーストラリアは日本のサッカーファンにも記憶に残っているし、国としても貿易等で繋がりが強いので、そうした国がAFCに入る事で新たなライバルが増える事になり、日本の強化にもつながるだろうし、何よりファンにとって楽しみが増える気がする。
人によって色々必要なものは違うと思うけど、自分の場合基本的な文法とかはある程度分かっているので、メール書いたりする時に辞書と活用が分かれば大体文章が書けるし、読む場合も辞書があれば何とかって感じ。
辞書はここ。英仏、仏英両方あるので便利。単語数はそれ程多くないけど。
最近のWebサイト・システムではとにかくとにかく「ダイナミック」で、画像・テキストなど至る所にイベントハンドラーが登録されている。
ごく原始的なやり方だと
<img src="foo.jpg" id="img1" onclick="somefunc()">
Event.observeだと
Event.observe('img1','click','somefunc()')答えは内側の要素に設定されたイベントハンドラーが先に呼ばれるんだけど、第4の引数useCaptureをtrueにするとちょっと違った動作に。とまぁその辺りをコントロールする引数。このページが分かりやすい説明だった。
例えば以下のような製品名、サイズ、値段と最終更新日を入力するテーブルを考える。データはINSERTするのみ。同じ製品でもサイズが違えば値段は違うものとする。
| PRODUCT | SIZE | UPDATED | PRICE |
| シャツ1 | L | 2007-01-01 | 2900 |
| シャツ1 | S | 2007-01-01 | 2900 |
| シャツ1 | L | 2007-02-01 | 1900 |
| シャツ2 | S | 2007-01-01 | 4900 |
| シャツ2 | S | 2007-02-01 | 3900 |
こっから各製品の現在の値段を一覧を知りたい。PRODUCTとSIZEでGROUP BYして、各グループからUPDATEDが最大の列を選べばいい。
ま、結論から書くとこんな感じ。MySQLの場合だけど、他のDBMSでも大体一緒かと。SELECT T.* FROM TABLE1 T INNER JOIN ( SELECT MAX(UPDATED) AS LAST_UPDATED FROM TABLE1 GROUP BY PRODUCT, SIZE ) AS T2 ON ( T1.PRODUCT=T2.PRODUCT AND T1.SIZE=T2.SIZE AND T1.UPDATED = LAST_UPDATED)
ON句に注目って感じ
ちなみにMySQLの場合、上の例でのAS T2をサブクエリーの中のFROM TABLE1の後に付けると、以下のようなエラーになった。
Every derived table must have its own alias参考にしたのは、このページの5-2の直前に書いてあるSQL。
随分前だけど、スキーに行った時に人にぶつかって肋骨を痛めた。多分骨にヒビが入ってたんだと思う。外国で病気とか怪我をするって何かと不安なもの。とりあえず基本的な情報を書いてみる。
ケベック州モントリオールの場合だから、他の市や州では事情が違うかもしれない。
自分の場合
・近くにCLSC(後述)に行った
・CLSCで紹介された別のクリニックに行った
・クリニックで紹介された、レントゲンの撮れる施設に行った
・レントゲンを撮っておしまい
CLSCはケベック州立のクリニックみたいな感じ。最寄りのCLSCはケベック州のページから検索出来る。何か困ったらそこにとりあえず行くのが良いみたい。
あと、ホームドクター(以前ちょっと書いたエントリ)の制度も面倒というか何というか。
一昨年車にはねられた時に総合病院みたいな所に行ったけど、5時間位待たされたし、緊急の時以外は総合病院には行かないシステムなのかもしれない...(不明)
Medicareカード(健康保険証みたいなもの)があれば無料なのはありがたいけど、医療の質はあまりいい話は聞かない。
ちなみに医者だから英語は話せるだろうっていう甘い期待は2件目のクリニックで打ち破られた。ESLレベルの英語しか喋れない先生で、正直困った。
最近は動画の再生でFLVを使ってる事が多いけど、半年位前にWindowsメディアを使った(簡易)ストリーミングのページを作ったので、ちょっとメモ。
昔はストリーミングなんてスゴい特別な感じがしたし専用のサーバーとか用意したりとか色々面倒だったけど、とりあえず動画を流したいだけならWebサーバーに動画ファイルを置いてちょっとだけ設定すれば、後はクライアント側で勝手にストリーミング再生してくれる。
○基本
大ざっぱに言うと動画本体(*.wmvファイル)に対して、ストリーミング情報を書き込んだasxファイル(中身はXMLみたいな感じ)というのを用意して、クライアントがそのasxファイルを読み込むと、あとはブラウザが勝手に判断してくれる。
asxファイルの基本的な書き方はこのページを参照。
○MIMEタイプ
Webサーバー側でMIMEタイプを正しく設定されてないと、上手くいかないかもしれない。
MicrosoftのページでWindows Media関連のMIMEタイプの一覧が載ってる(それ以外の情報も色々と)ので、それを設定する。
英語のこっちのページの方が記載されているMIMEタイプが1つ多いのはなぜだろ?
○プログラムから
自分が関わったページは、プログラムでコンテンツの管理をするので、WebサーバーにMIMEタイプの設定をするのではなく、サーブレットでHTTPヘッダーに適切なcontenTtypeを出力するようにした。
○やりたいこと
仕事でTomcatを使ってる。同じマシン上で複数のTomcatを動かしたいっていうのは良くあると思う。VMWareとか使えば?ってのは無しの方向性で。
○基本:違うポートで動作させる
まず必要なことはTomcatのフォルダをもう1つ用意して、設定ファイルserver.xmlを修正して違うポートで動作するようにするというもの。
○環境変数を変えたい
インスタンス毎に環境変数を変えたいって事もあると思う。システム独自の環境変数であったり、JNIを使ってる場合にはPATH変数を変更してdllの読み込み先を変更したりというのが考えられる。
・バッチファイル or シェルスクリプト
UNIX系の場合、起動スクリプト /etc/init.d/tomcat とかをインスタンス毎に用意して、その中で環境変数を設定すれば良いだけ。
Windowsの場合、バッチファイル(startup.bat)から起動している場合、catalina.batを修正すればそれでいいと思う。
○複数のWindowsサービスをインストール
Windowsサービスを複数インストールする場合は、それぞれ名前を変えなければいけない。
実はやり方は簡単で、service.batで引数を追加するだけ
service.bat install TomcatFoo
Windowsサービスを設定する場合、tomcat5w.exeを使うけど、デフォルト名でないTomcatのサービスの設定を変更する場合にはtomcat5w.exeにオプションを渡さなければいけない。
tomcat5w.exe //ES//TomcatFoo
このページに詳しく書いてあった。他にも色んなページがあるけど。
○複数のWindowsサービス+個別の環境変数
では各Windowsサービス毎に個別の環境変数で実行したい場合は?というと、service.batを修正する必要があるみたい。
この行を
"%EXECUTABLE%" //IS//%SERVICE_NAME% --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams start --StopParams stop
以下のように変更
"%EXECUTABLE%" //IS//%SERVICE_NAME% --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams start --StopParams stop --Environment "CUSTOM_ENV=bar"
○環境
Tomcat 5.5.23
(Java初心者向け?)
Javaは1.2位まで触っていて、その後かなりブランクが空いて1.4の最後の方で再び使うようになった。その間に色々と便利になっていた反面、色々と覚えることがあって最初はちょっと大変だった。
そのうちの一つがコレクションクラスや配列に関するもの。
Javaでは複数の値を扱うクラスが複数ある。
・普通の配列(例 String ary[] = new String[10]; )
・Vectorクラス(例Vector
・ArrayListクラス(例ArrayList
(他にもあるけど)
初心者ならこれらの違いは何だろうって絶対思うはず。
基本的な方針としてはこんな感じ
・ArrayList → 要素を後から追加したり削除したりする場合
・配列 → 要素数があらかじめ分かっている場合
・Vector → 下位互換のために残されていると言ってもいいので、基本的には使わない
@ITやスタックアスタリスクに分かりやすい説明が出てた。
また、それらの要素に対するループの書き方も微妙に違って、最初は戸惑うはず。ITmediaのこのページが結構分かりやすかった。
随分前だけど、Java + DBのシステムに本格的に携わり始めた時、JDBCでのトランザクションの使い方が分からなかった。けど、分かっちゃえば簡単だった。
Connectionオブジェクトに対してsetAutoCommit(false)を実行して、最後にcommit()メソッドを呼ぶ以外は通常のDBに対する処理と一緒。
こんな簡単な情報を探すのに結構時間がかかった気がする。随分前の話だったからかな。今は簡単な解説ページ(こんなページとか)がいくらでも見つかるのに。
詳しくはSunのこのページとか英語だけどサンプルコードとかは参考になると思う。日本語のドキュメントはどこだろ?
JMX(Java Management eXtensions)はJ2SE 5.0で取り入れられた新機能で、外部からJVMの監視・管理を行うことが出来る仕組み。
今やってるプロジェクトでは独自のDBコネクションプーリングクラスを使ってるので、コネクションの使用状況などを監視できればいいなぁというのがそもそものきっかけ。
JMX自体についての詳しい説明はGoogleで検索すれば情報は出て来ると思うので、ここでは具体的な使い方とかをメモ程度に。とは言え基本的な事を全く書かないのも何なのでちょっとだけ。
○JMXの仕組み(超簡単に)
その名の通りJavaを管理(manage)するための仕組みで、管理対象のJavaオブジェクト(今回の例ではコネクションプーリングクラス)に対してMBeanという管理用のオブジェクトを作り、クライアント(※1)はMBeanサーバーを経由でMBeanにアクセスして、管理対象のオブジェクトを管理する。
クライアント → MBeanサーバー → MBean → 管理対象のJavaオブジェクト
という感じ。このページの図2が分かりやすかった
新たに作る必要があるのはMBean(といくつかの設定変更)のみ。MBeanサーバーは独自のを作ることも可能だけど、普通は「プラットフォーム MBean サーバー」と言うJVMに組み込まれたものを使用する。
あと当たり前と言えば当たり前だけど、MBeanは作成しただけじゃダメで、MBeanサーバーに登録する必要がある。
(※1)クライアントにあたるのは一般的には管理・監視ソフトで、JMXの仕組みに沿ったものなら何でもok。
○環境
Tomcat 5.5.23
J2SE 1.5.0
Windows XP SP2
○Tomcatの設定
・JMXを有効に
起動時のオプションでJMXを有効にするため、以下のオプションを追加する。
-Dcom.sun.management.jmxremote
その他関連するオプションについてはこの辺りを参考に。
・Tomcatの管理画面へアクセスできるユーザーを設定(必須ではないけど)
CATALINA_HOME/conf/tomcat-users.xml
<tomcat-users> <role rolename="manager"/> <user username="admin" password="foobar" roles="manager"/> </tomcat-users>
○MBeanの作成
MBeanにはいくつか種類があるけど、今回は一番手っ取り早い標準MBeanというのを作成。
・MBeansのインターフェースを作成
今回は現在使用されているコネクション数を返すメソッドをとりあえず作ってみる。特に難しいことはない。
package tv.kazu.test.mbeans
public interface DBStatusMBean {
public int getUsedConnections();
}
・MBeansのインターフェースを実装したクラスを作成
これも特別変わったことはしてない
package tv.kazu.test.mbeans
public class DBStatus {
public DBStatus() {
}
public int getUsedConnections() {
// MYDBConnPoolはどっかで実装されている事とする
return MyDBConnPool.getUsedConnections();
}
}
全然難しいことはない。
○MBeanの登録
・登録用ユーティリティクラスを作成
前述の通り、MBeanはMBeanサーバーに登録する必要がある。少しだけ難しくなるけど、大したこと無い。
MBeanのコンストラクタとかで自分自身を登録してもいいし、別のクラスから(複数のMBeanがある場合には一括)登録してもいいけど、いずれにしてもユーティリティクラスがあると便利。
ちょっと端折ったけどこんなクラスを作成した。例外処理を除くとスゴいシンプルってのが分かると思う。
public class JMXUtils {
private static MBeanServer mbeanServer = null;
static public void registerAll() {
mbeanServer = getMbeanServer();
//複数のMBeanがある場合はここで全て登録
DBStatus bean = new DBStatus();
registerMBean(bean, "tv.kazu.test.mbean:type=DBStatus");
}
//MBeanの登録
static public void registerMBean(Object mbean, String nameStr) {
mbeanServer = getMbeanServer();
ObjectName objectName = null;
try {
objectName = new ObjectName(nameStr);
} catch (MalformedObjectNameException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
try {
mbeanServer.registerMBean(mbean, objectName);
} catch (InstanceAlreadyExistsException e) {
e.printStackTrace();
} catch (MBeanRegistrationException e) {
e.printStackTrace();
} catch (NotCompliantMBeanException e) {
e.printStackTrace();
}
}
//MBeanサーバーの取得
static public MBeanServer getMbeanServer() {
if (mbeanServer == null) {
mbeanServer = ManagementFactory.getPlatformMBeanServer();
}
return mbeanServer;
}
}
JMXUtils.registerAll()を呼べばMBeanが登録されるのが分かったと思うけど、じゃそれをどこで呼び出すかというのが次の話。
・ContextListnerを実装
詳細は省くけど、ContextListnerってのを作ってちゃんと設定しておくとTomcatの起動時にそれが呼ばれるのでそこでMBeanの登録をする(すごい適当な説明...)。
public final class ContextListener
implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
}
public void contextInitialized(ServletContextEvent arg0) {
try {
System.out.println("ContextListnerが呼ばれてます。");
JMXUtils.registerAll();
} catch (IOException e) {
e.printStackTrace();
}
}
}
あとはweb.xmlにContextListenerのエントリを記述。
<listener> <listener-class>tv.kazu.test.jmx.ContextListener</listener-class> </listener>
○最後にTomcatの設定をもうちょい
・mbeans-descriptor.xml
後はTomcatに対して、「こんなMBeanを使いますよ」と伝えてあげればいい。その設定にはmbeans-descriptor.xmlというファイルを作成する。
<?xml version="1.0"?>
<mbeans-descriptors>
<mbean name="DBStatus"
className="org.apache.catalina.mbeans.ClassNameMBean"
description="DB status"
domain="Catalina"
type="tv.kazu.test.mbean.DBStatus">
<attribute name="className"
description="Fully qualified class name of the managed object"
type="java.lang.String"
writeable="false"/>
<attribute name="debug"
description="The debugging detail level for this component"
type="int"/>
<operation name="getUsedConnections"
description="Returns the number of the connections."
impact="ACTION"
return="int">
</operation>
</mbean>
</mbeans-descriptors>
・デプロイ
MBeanインターフェースクラスとmbeans-descriptor.xmlをJARファイルにして
CATALINA_HOME\common\lib
に置くか、テスト用途とかでJARをいちいち作るのが面倒な場合はファイルを個別に
CATALINA_HOME\common\classes
に置く。
mbeans-descriptor.xmlはルート(CATALINA_HOME\common\classes)に、クラスファイルはパッケージの階層構造のままコピー。今回の例では以下のフォルダに。
CATALINA_HOME\common\classes\tv\kazu\test\mbean
・server.xmlの修正
server.xmlにmbeans-descriptor.xmlに関する記述を追加。
以下の行を
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListner" />
このように変更
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListner" debug="0" descriptors="/mbeans-descriptor.xml" />
後はTomcatを再起動。
○動作確認
動作確認にはjconsoleとかを使う。詳細はまたの機会に。
SunのJVM(Java Virtual Machine)にはJava HotSpot Server VM (サーバ VM) とJava HotSpot Client VM (クライアント VM)の2種類があり、デフォルトではクライアントVMが起動される。詳しくはSunのページ参照
詳細は省くけど、Tomcat等のサーバー用途の場合はサーバーVMを使用した方がいい。
■Windowsでの設定方法
TomcatをWindowsサービスとしてインストールした場合、tomcat5wを実行して以下の画面で設定する。
Java Virtual Machineを選ぶところで
%JAVA_HOME%\jre\bin\server\jvm.dll
を選択する(通常は自動的に選択されるっぽい)
■Linuxでの設定方法(起動スクリプトを少し修正するだけ)。
○環境
Tomcat 5.5.23
CentOS 4.4
JRE 1.5.0_06-b05
○起動スクリプトの修正
Tomcatはjsvc経由で起動。
/usr/local/tomcat/bin/jsvc-src/native/Tomcat5.sh
を修正して/etc/init.d/tomcatにコピー。
CATALINA_OPTSにオプションを付け加えるだけ。
CATALINA_OPTS="-jvm server"
○参考にしたサイトなど
JVMに関するSunのページ
藤澤さんという方のページ(Tomcatの設定方法など)
Ajaxが一般的になってきたけど、構築中のシステムでIEのXMLHttpRequestに関するバグ(あるいは控えめに言っても問題点)に悩まされた。
問題の概要はここのページに簡潔に書かれているけど、一応書いてみる。
前提として、IEのデフォルトではHTTPの同時接続数が2。
1.あるページがwindow.openで子ウィンドウを開く。
2.子ウィンドウがXMLHttpRequestでサーバーに問い合わせ。(HTTPの接続数のカウンタが+1)
3.サーバーから返答が返ってくる前に子ウィンドウを閉じる。(HTTPの接続数のカウンタが減らない)
4.1~3を繰り返すとHTTPの同時接続数の上限(2)に達し、それ以降のAjaxリクエストを行わなくなる。
解決策
・親ウィンドウも含め、全てのIEのウィンドウを閉じれば、次からは問題なし(消極的な解決策)
・レジストリで同時接続数を増やす(推奨されてない→MSのページ)
・サイトの構成を見直す(子ウィンドウからAjaxを使用しない等)
子ウィンドウのoncloseで、abort()メソッドを呼び出すというのを試した人もいるけど、問題は解決しなかったみたい。英語だけどこのページ。
IE+Ajaxに関する注意事項を集めたページ(英語)