So-net無料ブログ作成
Linux(Apache) ブログトップ
前の10件 | -

帰ってきた・たぶん難しくないApache2・挑戦!RewriteRule・活用編 ~「メンテナンス中です」ページを出してみよう~ [Linux(Apache)]

 いろいろ方法はあるんですが、RewriteRule活用のヒントとして、「メンテナンス中です」ページを出す例を紹介します。

#確か、このblogの趣旨としては「ご家庭の(ry

 シチュエーションとしてはこんな感じ。
 あるディレクトリ (ここでは 「/var/www/html/maintenance」とします)配下に、「現在メンテナンス中につきご利用いただけません」的なページを一式用意します。画像とかcssとかもね。
 そして、そのサーバにあるあらゆるリクエストについて、全て「メンテナンス中です」のページを出すようにします。

 まあ、ErrorDocumentを使う方法とかCGIで出しちゃえばいいじゃん的な方法もあるんですが、ここではあえてRewriteRuleを主役に据えて実施してみたいと思います。



① まずは「メンテナンス中です」のページを用意しましょう。

 すでに書いた通り、 /var/www/html/maintenance ディレクトリ配下にメンテナンス中ですページを一式用意しましょう。cssファイルが必要なら、cssというサブディレクトリを作成してその下に、画像ファイルが必要なら、imgというサブディレクトリを作成してその下に置くことにしましょう。
 「メンテナンス中です」ページの名前は index_maintenance.html とします。(まあ、名前は何でも良いんですがw)

② メンテナンス中ですページは誰でも見られるようにする必要があるのでそのように設定します。

 apache2.2系までならこんな感じでバッチコイ設定を入れます。
<Directory    "/var/www/html/maintenance">
    Order  Deny,Allow
    AllowOverride  None
    Options  None
<Directory>


 apache2.4系ならこんな感じです。
<Directory    "/var/www/html/maintenance">
    Require all    granted
    AllowOverride  None
    Options  None
<Directory>


 で、このディレクトリをドキュメントルートにしましょう。

DocumentRoot    "/var/www/html/maintenance"


③ で、RewriteRuleの出番です
 基本的な考え方としては、「とにかくindex_maintenance.htmlに読み替える」ことになるでしょう。
 サーバ上にはhtmlファイルの他に各種のCGIもあるでしょうし、「http://server/」とか「http://server/somdirectory/」のようにサーバ名やディレクトリ名だけで終わっている可能性もあります。このため、基本的にはありとあらゆるリクエストを読み替えることになるでしょう。ということは、まずは
RewriteRule    .*    /index_maintenance.html    [L]

 というRewriteRuleが登場すべきなのはガチという所でしょう。
 しかし、index_maintenance.htmlに貼ってある画像とかcssファイルとかまでindex_maintenance.htmlに読み替えるのはまずいので、それらは読み替えず、またindex_maintenance.html自身へのアクセスも読み替える必要は無いと言えます。
 そのような訳で、「css/配下とimg/配下へのリクエストは読み替えない」「ファイルが実在する場合は読み替えない」「index_maintenance.htmlへのリクエストは読み替えない」という感じの例外は入れたいと思います。
 RewriteCondディレクティブを用意します。
RewriteCond    %{REQUEST_URI}    !img/
RewriteCond    %{REQUEST_URI}    !css/
RewriteCond    %{REQUEST_URI}    !index_maintenance\.html$
RewriteCond    %{REQUEST_FILENAME}    !-f


 というあたりをRewriteRuleの前に書き足してやれば良いです。(多少、手抜きしてるのでアレですがw)

④ マニアックな需要のための対応
 ところで、③のRewriteRuleで対応すると、かなりそのスジな方から苦情(?)が上がる可能性があります。それは、CDNサービスのようなWebページをキャッシュするサービスを利用している場合です。
 実は③のRewruteRuleではメンテナンスページが200番応答で出力されてしまうため、そのメンテナンス中のページがキャッシュされてしまうという問題を引き起こします。ということは、メンテナンスが終了してもキャッシュされたページが出力されてしまうため、メンテが終わった後の素敵なページが閲覧出来ないという事態を引き起こす恐れがあります。

 このような場合、世間様的には500番系の応答を返してメンテナンス中ですのページを出すのが一般的…らしいです。そんな訳で、③を改良してメンテナンス中ですページを503番応答で出力させてみます。

 まず、RewriteRule本体を次のように改めます。
RewriteRule    .*    -    [L,R=503]


 そして、503番エラーが発生したときのためのエラードキュメントを設定します。
ErrorDocument    503    /index_maintenance.html


 こうすることで、応答が503になるので、多くのCDNサービスやらキャッシュサーバ等はメンテナンス中のページをキャッシュしなくなります。…なるはずです。(笑)

#Akamaiさんはキャッシュしなかったよー。

帰ってきた・たぶん難しくないApache2・挑戦!RewriteRule・その4~楽しいProxy~ [Linux(Apache)]

 本来なら、Proxyしたい場合はそれ用のディレクティブ「Proxy」等があるので、そちらを使うのがスジです。
 しかし、RewriteRuleでもProxyすることが出来たりしますし、むしろこっちの方が便利だということもあったりする訳なのです。そこで、RewriteRuleでProxyする方法を解説しておきます。



その1:反則技編 ~とにかくProxyする~

 まずはいきなり反則技から行きたいと思います。
 とにかくProxyします。このような場合、本当なら「Proxy」ディレクティブを使うのがスジです。RewriteRuleを使うべきではありません。しかし、解説としてはこれが一番判りやすいのでコレから先に解説したいと思います。
 なお、セキュリティ上の問題を多分に孕んでいますので、これで事故が起こったとしても当方は一切関知しませんので念のため。

 RewriteRule ^/(.*) http://otherserver/$1 [P]

 こんだけ。
 Proxyディレクティブを使う場合はもうちょっと指定が必要になるんですが、RewriteRuleディレクティブでやる場合はたったこんだけで終了です。これで、このサーバにきた全てのリクエストが、別のサーバ「otherserver」に中継されます。リダイレクトじゃありません。中継です。大事なことなので(ry

 ポイントになるのはRewriteRuleディレクティブの第3パラメータである[P]です。こいつが「Proxy」を意味しています。ここが[R]の場合はリダイレクトされます。つまり、ブラウザがotherserverにアクセスしなおすことになるんですが、今回はここが[P]なので、このサーバがotherserverにアクセスを中継してデータを取得するということをします。



その2:アレはProxyする。コレはProxyしない。

 RewriteRuleディレクティブを使ってProxyする最大の意義は、RewriteCondディレクティブやRewriteMapディレクティブといった機能を組み合わせてProxyする・しないを制御出来ること、あるいはProxy先を自在に書き換えることが出来ることです。

 たとえば、RewriteCondと組み合わせて、「自サーバにファイルがあればそれをクライアントに返し、なければProxyとしてotherserverに取りに行く」みたいなシナリオを想定してみます。するとこんな感じに。

 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^/?(.*) http://otherserver/$1 [P}

 RewriteCondが今まで説明しなかったような記述なんで説明します。
 サーバ上にその名前のファイルがあるかどうかを判定する場合、-fという記述ができます。これに「!」を付けた場合には否定の意味を持ちますので、「REQUEST_FILENAME」に指定されているファイルが無い場合にRewroteCondが成立することになります。
 ファイルが存在する場合は続くRewriteRuleは実行されませんので、他に無ければ自サーバ上にあるファイルをそのままクライアントに返します。ファイルが無ければRewriteRuleが実行されますから、otherserverにファイルを取得しにいくことになります。

 また、User-Agentに応じてproxy先を変更するなんてこともRewriteRuleならお手の物です。

 RewriteCond %{HTTP_USER_AGENT} iPhone
 RewriteRule ^/?(.*) http://otherserver/iphone/$1 [P]
 RewriteRule ^/?(.*) http://otherserver/$1 [P]

 とかやっておけば、(判定がちょっと雑ですがw)iPhoneとそれ以外のUAとでProxy先を変更することも出来ます。


その3:そもそもproxy先をひん曲げたい

 CGIが動作するサーバを直接インターネットに曝すなんてとんでもない!というしごく真っ当なサーバ管理者なら、CGIサーバの前にリバースProxyサーバを立ててそこからCGIにアクセスするようにしたいなんていう需要もあるでしょうね。当然、静的なhtmlページや画像ファイルはそのままWebサーバから配信し、プログラムが必要な所ではCGIサーバに代理アクセスをしてクライアントのその結果だけ返すなんてことをしたくなるわけです。
 ひとまず、単純に、「ファイルがあればそれを返し、ファイルが無ければURL部分をパラメータ化してCGIに処理を渡す」なんてことを表現するならこんな感じでしょうか。

RewriteCond    %{REQUEST_FILENAME}    !-f
RewriteRule    ^/?(.*)    http://cgi-server/program.cgi?param=$1    [P]


 このような場合、例えばhttp://myserver/index.html というファイルが存在すればそのファイルをクライアントに返します。しかし、http://myserver/shop/item/54 みたいなリクエストが来た時にそのようなファイルが存在しないときは、CGIサーバにリクエストを中継します。その時のURIは http://cgi-server/program.cgi?param=shop/item/54 という具合になります。CGIが出力する結果は自サーバを経由してクライアントに送信される…ということになります。

帰ってきた・たぶん難しくないApache2・挑戦!RewriteRule・その3~RewriteMapを使う~ [Linux(Apache)]

 そうか…。もう6年とか経過していたのか…。
 何もかもが懐かしい…。(遠い目


 URLの読み替えをしたい場合にRewriteRuleを使う…という話をしてましたが、ファイルが決め打ちできるとか、正規表現で一定のルールに従って読み替えができる…というようなケースでは割と簡単にお役に立ってくれました。
 ところが…。
 たまに有りませんか?

 サイトのデザインを一新したんだけど、ページにリンクされている画像ファイルとかバナーとかも全部差し替えたい。でも、他のサイトで直リンクしているバナーもあるようなんだけどもう把握出来ていないので、古いバナーについては新しいバナーにサーバ側で読み替えて欲しいんですけど。

 …みたいな話。で、『あ…。シンボリックリンクを張っておくかRewriteRuleで読み替えちゃえばいいかな…』なんて考えていたら読み替えるべきファイル名が数百個もあった件について…みたいな事例。
 しかも、正規表現で美しく読み替えようにもそんなこと出来ませんよセンセイ…みたいな事例。

 …え?ない?
 …ソウデスカ…アリマセンカ…orz

 ここでは、「あー。あるある!」と大人の対応をした人に向けて、「RewriteMap」を簡単に使って解決する方法を書いておきたいと思います。


 例えば、たった一つのファイルを読み替えたいときはどうするか?を考えます。
 img/fileA.jpg を、img/fileB.jpg に読み替えるとしましょう。この場合はチョー簡単です。

 RewriteRule img/fileA.jpg img/fileB.jpg [L]

 とかやっておけば事足ります。ところが、これを何百個も書きたくない訳です。このような場合には、「RewriteMap」ディレクティブを使います。手順としてはこんな感じです。

手順①:旧ファイル名 → 新ファイル名の読み替え一覧をテキストファイルで作成する
手順②:手順①で作成したテキストファイルをdbm型式に変換する
手順③:手順②のファイルを、「RewriteMap」ディレクティブで読み込み、条件を設定してRewriteRuleで読み替える


手順①:旧ファイル名 → 新ファイル名の読み替え一覧をテキストファイルで作成する

 まず、新旧ファイル名の読み替えをする一覧をテキストファイルに作成します。フォーマットは、「旧ファイル名」と「新ファイル名」とを1行に記述します。半角スペースやタブで区切ります。

img/fileA.jpg    img/fileB.jpg
img/fileC.jpg    img/fileX.jpg
img/fileD.jpg    img/fileY.jpg
img/fileE.jpg    img/fileZ.jpg


 なお、半角「#」がコメントとして使用可能です。


手順②:手順①で作成したテキストファイルをdbm型式に変換する
 次に、手順①で作成したテキストファイルをdbm型式に変換します。実のところ、変換しなくてもいけるんですが、読み替えるべきファイルが多い場合は変換した方がサーバ負荷が下がってオススメです。
 コマンドとしては、httxt2dbmコマンドを使用します。

 httxt2dbm -i (入力ファイル名) -o (出力ファイル名)

 です。入力ファイルには手順①で作成したファイル名を指定します。出力ファイル名にはdbm型式のファイル名をそれっぽい名前で指定すればよいでしょう。
 このコマンドを実行すると、拡張子「.dir」というファイルと「.pag」というファイルが作成されます。


手順③:手順②のファイルを、「RewriteMap」ディレクティブで読み込み、条件を設定してRewriteRuleで読み替える

 次に、httpd.confを調製します。
 まず、手順②で指定したdbm型式のファイルをRewriteMapディレクティブで読み込みます。

 RewriteMap imgurl dbm:/usr/local/apache2/conf/yomikaelist

 imgurlは単なる識別子です。次のRewriteRuleディレクティブで使用しますが名前は何でも構いません。
 dbm:/usr/local/apache2/conf/yomikaelistは、「dbm:」に続いて手順②で作成したファイル名を指定します。拡張子は必要ありません。

 で、これをRewriteRuleディレクティブで実際に読み替えます。

 RewruteRule ^/?(img/.*\.(gif|jpe?g)) /${imgurl:$1|$1} [L]

 これくらいの正規表現はちゃっちゃと読めないとねー。(笑)
 まず、RewruteRuleディレクティブの最初のパラメータ^/?(img/.*\.(gif|jpe?g))は、「img/」ディレクトリの下にある「ナントカ.gif」「ナントカ.jpg」「ナントカ.jpeg」を読み替えたいのでこのような記述をしています。ここで、丸括弧が2組出ているのが「なんじゃこりゃ」の原因になっていると思いますので解説しておきます。
 RewriteRuleの過去の記事にもしれっと記述してたりするんですが、丸括弧で囲んだ範囲はRewriteRuleディレクティブの内部的な「変数」に格納することが出来ます。(img/.*\.(gif|jpe?g))の外側の部分はそのための丸括弧で、丸括弧の中身は「$1」という変数に格納されます。
 内側の丸括弧部分(gif|jpe?g)/font>は拡張子「gif」または「jpe?g」のどちらかという記号「|」の範囲を特定するための物です。

 で、この正規表現によって、次のようなリクエストがあったなら、赤文字の部分が変数$1に格納されることとなります。

 http://server/img/fileA.jpg

 さて。この赤文字部分。そういえば手順①で作成したファイルの中にありましたよね?

img/fileA.jpg    img/fileB.jpg
img/fileC.jpg    img/fileX.jpg
img/fileD.jpg    img/fileY.jpg
img/fileE.jpg    img/fileZ.jpg


 この変数$1の内容をRewriteMapディレクティブで読み込んだアレに渡すと、見事img/fileB.jpgに化けて出てくる…という処理をしているのが、RewriteRuleディレクティブの二つ目の引数である /${imgurl:$1|$1} です。

 ${(RewriteMapの識別子名):(読み替え前の名前)}

 としておくと、読み替え前の名前を読み替えた後の名前が取得できます。つまり、

 ${imgurl:img/fileA.jpg}

 という指定をすれば、この変数は結果的にimg/fileB.jpgという値になって機能するということなのです。

 ただし、ここで一つ注意すべきポイントがあります。それは…

 読み替え「前」の名前が無い場合は、空っぽの値が返ってくる

 という点です。つまり、

 ${imgurl:img/fileAHO.jpg}

 という指定をした場合、この結果は「」という状態になってしまいます。このため、RewriteMapで読み込んだファイルの中に記述が無い場合は、RewriteRuleが「」に読み替えようとしてしまいますので非常に都合が悪いのです。

#そもそも、「読み替えたいファイルの一覧」があるということは、
#その中に「無い」ファイルは「読み替えて欲しくない
#と解釈すべきでしょ?

 と言うわけで、imgurlに値が「ない」場合の振る舞いも一緒に指定しておく必要があります。そのための記述が、「|$1」の部分なのです。

 ${imgurl:img/fileAHO.jpg|img/fileAHO.jpg}

 という指定をすると、imgurlに「img/fileAHO.jpg」があれば、読み替えたその文字列を返す。(「|」の前の部分)
 しかし、imgurlで読み替えた結果が「空っぽ」だった場合は「img/fileAHO.jpg」を返す。(「|」の後ろの部分)

 という処理を行うことになります。
 実際には、RewriteRuleで使用している変数「$1」の中身に応じて読み替えをしたいので、結果的に/${imgurl:$1|$1}という指定になっている訳です。



 これで、ファイルが読み替えるべき対象であるならファイル名を読み替え、そうでない(リストに無い)場合はそのままの名前でアクセスを通す…という事が出来るようになります。

apache2で--with-mpm=worker付けてコンパイルできないとお嘆きのアナタ [Linux(Apache)]

 やらかす人が結構いるようですが。。。

 apache2をビルドしていて、MPMオプションを付けないで(または--with-mpm=preforkを付けて)configureしてmakeした後で--with-mpm=workerオプションを付けて再度ビルドしようとすると、環境によっては
/usr/local/src/httpd-2.2.17/server/mpm/worker/worker.c:1203: undefined reference to `ap_thread_stacksize'
collect2: ld returned 1 exit status
make[1]: *** [httpd] エラー 1
make[1]: ディレクトリ `/usr/local/src/httpd-2.2.17' から出ます
make: *** [all-recursive] エラー 1

 こんなことになることが。

 こんなエラーにお嘆きのアナタ!

 make clean

 で驚きの白さに!!(チガウ
 一挙解決!この後にconfigureしてmakeしてmake installしてやってください。







 というか、ビルドしなおすときにmake cleanするのは基本だよー。(笑)
 某SIerから来ている人がコレに延々と悩んでいて萎えた。

apacheのチューニングの基本 [Linux(Apache)]

 apacheのチューニングは、サイトの特性によっていろいろ変わってくるので、一概に「これがいいよ!」という設定値が存在しない。まあ、「ab」を使って値を注意深く分析しなさい。という一文で終わってしまいがちだね。(笑)

 ただ、そうはいっても「基本的にはこうしたほうが良い結果が得られることが多いよ」というポイントも存在するので、それらを紹介しておく。

原則1:ログの出力処理は「重い」ということを忘れない
 apacheが絶えず行う処理の中で、「重い」処理の部類に入るのが、実は「ログの出力」である。これ、結構忘れがちになってしまうが、
  ・あとでアクセス解析とかしたいから
  ・セキュリティ上チェックを欠かせないから
  ・よく判らないけどとりあえずログとっとけ
 みたいな理由で、大きなログを取得して(そしてそのまま放置されて)いることが少なくない。確かに、ログが無きゃ無いであとで困ったことになることもあるから、保険の意味もこめてログを取得することは実際問題として重要な意味を持つ。が、ログにも「取り方」ってものがあるんですよ。(笑)

 ログは、
  1-1.必要な分だけログを取る
  1-2.後で細工できる部分はあとでやる
  1-3.どうしても必要なログは可能なら高速に書き込める領域で

 という方針を堅持したい。

 1-1.必要な分だけログを取る
 例えば、「ナントカ.html」とか「ナントカ,cgi」とか「ナントカ.php」とか、そういうリソースへのアクセスについてだけログを取得するようにし、画像ファイルへのアクセスはログを取らない…という方法を考えてみる。
 画像への直リンクをされても一向に構わないよという場合はそれでも必要十分であることが少なくない。
 例えば、どこかの企業サイト等を想定してみよう。
 アクセス解析という観点でログを採取するなら、「どのページをみたか」「どこから来たか」というような情報がほしいはずであって、個々の画像ファイルについてはあまり意に介さないことがほとんどではないだろうか。たまに、何か勘違いしたようなサイトなどでは、1つのhtmlページに数十・数百の画像ファイルが貼り付けてあることもしばしばあるが、それを全部ログ出力していたら、書き込みにどんだけサーバ負荷を奪われるのか想像に難くない。
 また、セキュリティの観点でログを採取するとしても、画像単体をクラックしにくるよりは、何がしかのCGIとかSSIとかhtmlに埋め込まれたフォームとかが対象にされることだろうから、画像ファイルへのログは採取する必要性に乏しいといえる。よって、画像ファイルへのアクセスについてはログ出力をあきらめてもさしたる問題にならないかもしれない。

 このような割りきりが可能であれば、さっそくhttpd.confに以下のような設定を追加するとよいかもしれない。
SetEnvIf Request_URI "\.(gif|jpe?g|png)" nolog
CustomLog "logs/access_log" ????? env!=nolog

 「?????」の部分は、LogFormatデレクティブでログの書式を定義している際に付与した名前を入れる。
 リクエストされたファイルの拡張子が「gif」とか「jpg」とかであった場合、環境変数「nolog」が定義される。これが定義された場合はログを出力しないように振舞う定義を行っている。


 1-2.後で細工できる部分は後でやる
 要するに、「DNS逆引きはやるな」ということ。(笑)
 具体的には
UseCanonicalName Off
HostNameLookups Off

 を入れとけってことね。
 というのも、デフォルトのままではログファイルにアクセス元のアドレスを出力する際に、IPアドレスではなくDNSを逆引きした結果の「名前」が入るようになっている。ということは、ログを1件1件出力するたびにDNS検索が走ることとなるので、余計な処理・トラフィックがログの1件ごとに発生することとなる。
 どうせ、後からログをチェックするなら、チェックするタイミングでnslookupをすれば済むだけの話なので、ログには生のIPアドレスを書くだけにしておけ!

 …ということ。


 1-3.どうしても必要なログは可能なら高速に書き込める領域で
 ログの出力…つまり、ファイルへの書き込みは「重たい」部類の処理に入ることはすでに説明した。「1-1.」でそもそも出力する対象とすべきログの量を削減すべきことを説明したが、それでも一般に公開しているようなサーバは結構な量のログを出力することとなるだろう。
 そのような場合はなるべく高速に書き込める領域へのログ保存を行うことを推奨する。

 具体的には
 可能性1:シリコンディスク(RAMディスク等)への保存
 可能性2:RAID0(RAID10でもいいし)領域への保存
 可能性3:別コントローラ・別ディスク領域への保存
 可能性4:同一コントローラ・別ディスク領域への保存
 可能性5:せめて別パーティションへの保存

 ということであり、
 禁止事項:NFSやCIFS領域への保存
 できれば避けたい事項:OSと同じ領域への保存

 ということになろう。

 可能性1について
 別に、高価なシリコンディスクオプションを買って来いといっているわけではない。
 いまどきのPC・サーバならメモリがとても安く手に入ることだろうし、最初から潤沢なメモリを搭載しているかもしれない。とすると、Linuxインストール時に標準的に確保される領域「tmpfs」を使うという手がある。
 これは仮想RAMディスクではあり、サーバに搭載されているメモリ量の最大で1/2までをストレージ領域として用いることができる。標準状態では/dev/shmとかにマウントされているので、これを適切な場所にマウントしてそこにapacheのログを吐かせれば、うそみたいにログ出力処理が軽くなる。
 まあ、その分メモリを食いつぶすことになるので、これを使ったばかりにswapを触るようになってしまっては本末転倒もはなはだしいが。

 可能性2について
 RAMディスクがダメなら、RAID0でディスクに対するスループットを上げる方法も考えられる。
 最近はハードディスクもアホみたいに安くなってきており、小さめのディスクを数本用意してストライピングを構成すれば、圧倒的な書き込み性能を確保することだって可能だ。
 さらに、Webサーバをロードバランサの下に複数台数展開しているような商用環境等では、1Uサーバでもディスクを2本とか入れてRAID1(ミラーリング)でOS領域を確保しているというところもあるかもしれない。そんな場合は、【思い切って】その2本のディスクをRAID1でなくRAID0にしてしまおう。

 「はぁ!?ディスク飛んだらどうすんの!?」

 という懸念もあるかもしれない。が、よくよく考えてほしい。なんのためにロードバランサがあって、何のためにWebサーバが複数いるのかということを。Webサーバが1台くらい飛んでも大丈夫なように、ロードバランサがあり、Webサーバの複数展開をしているはずではないか?
 それなら、その過剰な冗長性を一部解除して、スループット上昇に転用してもよいのではないだろうか。

 なお、OS領域もRAID0におかれるようになると、サーバ全体の動作がほんのりと機敏になるので個人的にはお勧めしたいのだけども。(笑)
 まあ、サーバが1台しかなくて、ディスクが飛んだら困る…みたいな場合はさすがにお勧めしないけども。

 可能性3~5と、「できれば避けたい事項」について
 RAID0が無理なら、せめてOSの領域とはまったく別の世界にログをおいてね!ということ。

 SCSI(SAS)などを使用しているなら、SCSIコントローラから別の「バス」に置いたディスクにログを保管したい。SATAなどではせめて別のディスクに保管したい。というのも、OSが入っているディスクはたとえ何もしていなくてもある程度のIOが日常的に発生してしまうものである。だからそこへさらにログ出力のためのIOを上乗せするようでは、ログ出力のための性能劣化がより明らかに出てしまうこととなるだろう。
 だから、よくを言えば「別のバス・別のディスク」だが、それが無理なら「別のディスク」に保存したい。
 また、1Uサーバでディスク1本しか入らないの!  みたいな残念なケースであれば、せめて/bootや/以外にログ専用のパーティションを作成してそこに記録するようにしたい。

 「禁止事項」について
 これはもう説明不要だろう。たまにあるのだが、「複数のWebサーバからログを集めてくるのが面倒くさいので、NFSの領域にログを吐き出せば…」というアイディアを本当にやっちゃた例が。(大笑)
 あー。きっとこれやった人は「ナイスなアイディアじゃん!」とか思ったんだろーなー。(笑)

 NFSとかCIFSとかやってる領域へのログ保存はご法度。
 ローテート済みのログならいざ知らず、今まさに出力中というようなログは絶対に置いちゃダメ。絶対。

原則2:絶対にswapしない!させない!頼らない!
 「swap3ない運動」を徹底しましょう。(笑)

 swapを触っていいことなんて何もありません。このためには、
 可能性1:必要のないモジュールは読み込まない・組み込まない
 可能性2:プロセス起動本数の調整は細やかに
 可能性3:メモリ増設・サーバ増設も否定しないで
 可能性4:サーバアプリケーション開発スタッフの「手抜き」に目を光らせよう

 可能性1について
 DSOでモジュールを組み込む場合、全く必要の無いモジュールもバンバン読み込んでしまうことがある。例えば、「BASIC認証なんか使わない」のに、認証系のモジュールを組み込んでいる場合とか。「WebDAVなんか使わない」のに、WebDAVのモジュールを組み込んでいる場合とか。
 httpd.confにLodeModuleディレクティブを大量に記述していると、httpdプロセスが消費するメモリ量がどんどん増加することになるので、「必要の無いものは読み込まない」という意識を徹底したほうが良い。

 必要なモジュールが少なければ、
  利点1:httpdが消費するメモリ量が少なくて済むので、その分プロセスを大量に起動できる(≒より多くのリクエストに対応できる)ようになる
  利点2:読み込むモジュール・確保するメモリが少なくなるので、そのためにかかる時間(オーバーヘッド)が短くて済む

 ということに。

 可能性2について
 プロセス数をてきとーにバーンと確保してしまうと、プロセスが大量に起動してメモリを食いつぶしてしまいパフォーマンスダウンを招くだけでなく、逆に「メモリが有り余ってるのにプロセス数が足りず、処理待ちになってしまうリクエストが発生する」なんてこともある。

 また、アイドル状態(リクエスト待ち状態)のプロセスについては「最大」と「最小」と両方設定するディレクティブがあるが、それぞれ適切な数値に設定しなければ、プロセスの上げ下げにCPU時間を消耗することもあれば、プロセス最大数の設定値にかかってリクエスト待ちになっちゃったり、swap触ったりすることも発生してしまう。
 この設定値として適切な値を探し出すツールとして「ab」を使うことになるのだが、基本的なセオリーとして

  アプローチ1:プロセスの最大数はhttpdやCGI(PHPなど)が必要するメモリ量との相談ということになるが、サーバオペレーションのために必要なメモリもある程度は残しておくこと
  アプローチ2:MinSpareServersはあまり大きすぎる値にしない。apacheはhttpdの数がこの設定値を下回ると、「使わないかもしれない」httpdであってもわざわざ起動して待機状態に置こうとするので、この設定値は小さいほうがよい。
  アプローチ3:MaxSpareServersは逆に、小さすぎる値にしないこと。メモリに余裕があるなら、むしろある程度大きくしておき、プロセスの上げ下げを抑止したほうが全体のスループット確保には有利に働くことが多い。(絶対そうかと聞かれると、NOというケースもあるんだけどね)
  アプローチ4:MaxRequiestPerChildを使うなら、ある程度大きな数値にすべき。デフォルト値では10000という大きな数値に設定されている。たまに「200」とか「500」とかに絞る人を見かけるが、小さな画像をいっぱい張っているようなサイトではプロセスの上げ下げが頻発することとなるので、小さな数値にすることは全く推奨できない。ただし、「メモリリークを起こしまくるような素敵なCGI」を動かしているような場合は、小さな数値にすることが良いとされている。もっとも、値を小さくする前にその「メモリリーク」というバグを直せ!というのがスジであると思うのだが。(大笑)
  アプローチ5:mem_preforkでなく、mpm_workerを使うようにできないか検討すべき。いちいちプロセスを起動するよりは、LWPの方が処理としては軽い。しかし、「残念なCGI」の場合にはスレッドセーフでないことが多いので、mem_preforkを使ってくれという要求が出てくることもあろう。CGIとか使わないサーバであれば、mpm_preforkを使う理由は全く無いだろう。

 可能性3について
 そりゃ、メモリもサーバも潤沢にあればよいにこしたことは無いよね。(笑)

 可能性4について
 サーバ・ネットワークエンジニアが、つめの先に火をともすようなカツカツのチューニングをしても、一部の(…いや、もっと多いかもしれない)アプリケーション開発エンジニアがリソースを湯水のように使ってわれわれの苦労を台無しにしてくれるなんてことも少なくない。(笑)
 かつて、財務大臣を務めた「塩爺」こと塩川正十郎氏が「母屋でおかゆをすすっているときに、離れですき焼きを食べている」なんて発言をしたことがあるが、まさにそんな心境が理解できる気がするよね。(笑)

 申し訳ないが、こういう「リソース」という観点から見た場合、アプリ開発エンジニアは無能な連中が多い(無能というか無関心というか無理解というか…)ので、放置しておくとブックブクのメタボリックCGIが平然とリリースされたりするので、注意が必要だ。

 だいたい、連中はメモリリークなんて「あって当たり前」だと思っているんだからもう…(ブツクサ

 そんな訳で、「貴重なメモリ資源」を食いつぶすダメアプリには目を光らせておきましょう。

原則3:意外と重たい「FollowSymLinks」とさらに重たい「SymLinksIfOwnerMatch」
 Optionsディレクティブに、FollowSymLinksやSymLinksIfOwnerMatchを記述(allも含めて)している場合、それを削る方向で考えよう。

 ディレクトリの構成上、例えば画像ファイルとかを置いているディレクトリをシンボリックリンクであっちこっち使いまわしてみたりすることもある。が、それは良くないので避ける方向で考えるべき。
 というのも、例えば
DocumentRoot  /var/www/http
<Directory />
  Options FollowSymLinks
</Directory>

 なんてやって、http://servre/foo/bar/index.html とかリクエストが来た日には、
  ・/
  ・/var
  ・/var/www
  ・/var/www/http
  ・/var/www/http/foo
  ・/var/www/http/foo/bar
  ・/var/www/http/foo/bar/index.html
 ↑これら全部が、シンボリックリンクかどうか全てチェックされた上で、さらにシンボリックリンクの状態を確認しようとしてしまう。つまりそれだけ無駄なシステムコールがバシバシ発生してしまうということになる。さらに悪いことに、このシステムコールは【必ずディスクアクセスを発生させる】ということ。メモリ上にキャッシュされた情報を使わずにチェックを必ずディスクにしにいくということなので、手軽に使えるからといってシンボリックリンクを多様すると、パフォーマンス的に痛い目を見ることになる。
 また、実際にシンボリックリンクを使っていなくても、Optionsにこれらの設定を有効化しただけでこれらの処理が行われてしまうので、

  「シンボリックリンクは使わない」

 という方針を真っ先に固めておくべき。
 なお、「SymLinksIfOwnerMatch」はさらに重たい処理を発生させてしまうのでさらに使うべきではない。

原則4:「.htaccess」はなるべく使わない
 「.htaccess」を多様したサイト構築をしている、アレな人を時折見かける。認証のために必要かもしれないだろうし、PHP等に何かパラメータを渡したいということもあるかもしれない。

 が、それは「使いたいディレクトリ」だけで「.htaccess」を許可(具体的にはAllowOverrideを許可)するようにすべきで、用の無いところでは使わないようにすべき。

 というのも、「AllowOverride」で何らかの情報を上書きするように設定されているディレクトリの下では、「.htaccess」というファイルがあるかどうか必ずチェックするようになる。よって、「.htaccess」が必要なくて設置もしてないディレクトリでは、必ず無駄なファイルアクセスが発生することとなる。これはありとあらゆるファイルアクセスでも発生するので、結構馬鹿にならないのである。
 また、「.htaccess」が必要ないとわかっていても、実際にファイルチェックを行わないと各ディレクティブの設定や変更が完結しないということになるので、サーバからのレスポンスがそれだけ遅延することとなるのである。これはもったいない。

 そんな訳で、「AllowOverride」は必要のある場所だけで、許可するようにDirectoryディレクティブ等で設定すべき。間違っても、ドキュメントルートからいきなり許可とか絶対やらないこと。(笑)

原則5:「DirectoryIndex」ディレクティブにワイルドカードが使わない(絶対)、必要のあるものだけ書く(なるべく)
 地味に効いてくるのが、この「DirectoryIndex」ディレクティブ。

 このディレクティブに、用も無いのにたくさんのファイル名を列挙したがる人がいる。例えば…
DirectoryIndex index.cgi index.php index.pl index.shtml index.html

 こんな状態。で、http://server/ とかリクエストされて、そこには「index.html」しか無かったりすると…

  ・index.cgiがあるかな…?   無いや。
  ・index.phpがあるかな…?   無いや。
  ・index.plがあるかな…?   無いや。
  ・index.shtmlがあるかな…?   無いや。
  ・index.htmlがあるかな…?   あ、有った。よし。これを使おう!

 ということになる。
 「このページをブックマークしてね!」みたいなことをやってて、そこがこんな状態だと、「http://server/」あるいは「http://server」でリクエストしてきた人が現れるたびに毎回こんな状態になってしまうのである。

 必要の無い、あるいは最初から無いと判っているファイル名は記述しないこと。これを徹底するように。


 まとめてしまうと、
  ・面倒くさがらないこと
  ・注意深く観察すること
  ・アプリ開発スタッフは信用しないこと(笑)
 という3点につきますな。(笑)ま、3点目は30%くらい冗談だけどね。(笑)

Directory、Files、Locationの各ディレクティブの処理される順番 [Linux(Apache)]

 ほとんど備忘録ですが。

 Apache2のhttpd.confに、
 <Directory> ~ </Directory>ディレクティブのブロック
 <DirectoryMatch> ~ </DirectoryMatch>ディレクティブのブロック
 <Files> ~ </Files>ディレクティブのブロック
 <FilesMatch> ~ </FilesMatch>ディレクティブのブロック
 <Location> ~ </Location>ディレクティブのブロック
 <LocationMatch> ~ </LocationMatch>ディレクティブのブロック

 がそれぞれ登場した場合に、どのブロックから処理されていくか…という順序のルール。

 あとから処理されたほうが優先される。(同じファイルやディレクトリが指定されたことによって設定が上書きされることがある。最も最後に上書きされた設定が有効になる)

処理順番 1:まずは、正規表現を含まない<Directory> ~ </Directory>ディレクティブのブロック
 たとえば<Directory /> ~ </Directory>ディレクティブというように、正規表現を含まないDirectoryディレクティブブロックが最初に処理される。
 ただし、Directoryディレクティブブロック同士の処理順についてはさらに細かいルールがあり

 ルール① 正規表現を含まないディレクティブ同士が複数記述されている場合、それは浅いディレクトリ深いディレクトリの順に処理される。

 ルール② <VirtualHost>ディレクティブブロックで、同じディレクトリに対して記述があり、かつその<VirtualHost>ディレクティブブロックが適用される場合、VirtualHostのVirtualHostのの順に処理される。

 ルール③ <VirtualHost>ディレクティブブロックの外同士、または中同士で同一のディレクトリに対する指定が複数回登場した場合は、httpd.confの登場順(上→下)に処理される。矛盾する指定があった場合(たとえばAllow from All としたあとに Deny from All とかした場合)は、一番最後の記述が有効ということになる。

 ルール④ <Directory />ディレクティブブロックの中で、.htaccessファイルによる定義の上書きを許可している場合、<Directory />ディレクティブブロックの設定が完了したに.htaccessによる設定上書きが実施される。(そして、次へ進む)

 そんな訳で、(記述があれば)絶対に最初に処理されるディレクティブは
<Directory />
Deny from All
</Directory>
 ということになるか。

処理順番 2:<DirectoryMatch> ~ </DirectoryMatch>ディレクティブのブロック と、正規表現を含む<Directory> ~ </Directory>ディレクティブのブロックが処理される。

 続けて、正規表現を含むDirectoryディレクティブブロックやDirectoryMatchディレクティブブロックが処理される。
 この処理順についても、Directoryディレクティブブロックと同様に、

 ルール①:浅い→深い
 ルール②:VirtualHostの外→中
 ルール③:VirtualHostの外同士/中同士で同一のディレクトリが複数回記述されていれば上→下

 と、なる。なお、正規表現を含むDirectoryディレクティブブロックでは、.htaccessが使えないため、これによる設定の上書きは行われない。

処理順番 3:<Files> ~ </Files>ディレクティブのブロック と <FilesMatch> ~ </FilesMatch>ディレクティブのブロック とが処理される

 Filesディレクティブブロックと、FilesMatchディレクティブブロックは全てのディレクトリに対する処理が行われた後に適用される。

 なお、Filesディレクティブ、FilesMatchディレクティブは正規表現の有無、長さなどに一切関わりなく処理が行われる。つまり、Directoryディレクティブブロック・DirectoryMatchディレクティブブロックの詳細なルールにあった「①」は存在しないことになる。よって、

 ルール②:VirtualHostの外→中
 ルール③:VirtualHostの外同士/中同士で同一のファイルが複数回記述されていれば上→下

 が適用される。

処理順番 4:<Location> ~ </Location>ディレクティブのブロック と <LocationMatch> ~ </LocationMatch>ディレクティブのブロック

 ディレクトリ、ファイル双方への処理を実施したあとで、ロケーションの処理が行われる。
 こちらの処理も、ファイルと同様にhttpd.confへの登場順の処理を基本とする。

 ルール②:VirtualHostの外→中
 ルール③:VirtualHostの外同士/中同士で同一のロケーションが複数回記述されていれば上→下

 ということに。
 ロケーションはdirectoryディレクティブみたいな浅い→深いは関係ない模様。


 なお、上記の処理が行われた後で、aliasとかDocumentRootとかの処理が行われる…と。

たぶん難しくないApache2・挑戦!RewriteRule・その2~基礎編:さらに条件を組み合わせる~ [Linux(Apache)]

 基礎編ではあるが、ちょっとややこしくなってくるので気合入れて読むように。(笑)

 さて。RewriteRuleの本領はここから発揮されるのであった。
 CGIを自作したことがある人なら知っていると思うが、Apache2をはじめとするWebサーバは、CGIに対して”環境変数”を通じて様々な情報を通知する機能を有している。
 たとえば、「HTTP_USER_AGENT」は、そのCGIにアクセスしてきたクライアントのブラウザに関する情報を通知する変数であるし、「HTTP_REFERER」は、そのCGIへのリンクが張られていたページのURLを通知する変数である。
 こうした環境変数を評価してRewriteRuleを実行する/しないの制御を行うことも可能なのであった。そのためのディレクティブを紹介する。
RewriteCond 評価対象 評価パターン

 このRewriteCondディレクティブは、RewriteRuleディレクティブの前に1個以上記述する。すると、RewriteCondの評価内容をチェックし、当てはまらない場合には、このRewriteCondに続く最初に遭遇したRewriteRuleディレクティブの実行をキャンセルするようになる。

 言葉だけで書いているとなんか判りづらいので、実例を挙げてみよう。

RewriteEngine on
RewriteCond %{HTTP_HOST} class-3.\.ryoou-gakuen\.ac\.jp
RewriteRule ^/lucky-star/(.*) /graduate/$1 [R]

RewriteRule ^/washimiya-jinja/(.*) http://www.washimiya-jinja.org/$1 [R]

 こんな設定があったとしよう。この例で示したRewriteCondディレクティブは、ホスト名をチェックしている。変数「HTTP_HOST」の内容が、class-3.\.ryoou-gakuen\.ac\.jpとマッチするかしないかを判定しているが、マッチした場合には、URLの「/luck-star/」を「/graduate/」に書き換えるRewriteRuleが実行される。しかし、マッチしなかった場合はそのRewriteRuleの書き換えは実行されない。
 しかし、「/washimiya-jinja/」を「http://www.washimiya-jinja.org/」にリダイレクトするRewriteRuleは、RewriteCondの判定結果にかかわらず必ず実行されるのであった。

 つまり。
 http://class-3b.ryoou-gakuen.ac.jp/lucky-star/hoge.html
 ↓
 http://class-3b.ryoougakuen.ac.jp/graduate/hoge.html
 という書き換えが発生するが、

 http://class-1d.ryoou-gakuen.ac.jp/lucky-star/hoge.html
 ↓
 http://class-1d.ryoou-gakuen.ac.jp/lucky-star/hoge.html
 と、このように変換されずにもともとのURLのままアクセスされる結果となる。

 一方で、
 http://class-3b.ryoou-gakuen.ac.jp/washimiya-jinja/hoge.html
 ↓
 http://www.washimiya-jinja.org/hoge.html
 という書き換えは実行され、

 http://class-1d.ryoou-gakuen.ac.jp/washimiya-jinja/hoge.html
 ↓
 http://www.washimiya-jinja.org/hoge.html
 こちらもこの書き換えが実行される。

 1個目のRewriteRuleはRewriteCondの制御対象になっているが、2個目のRewriteRuleはRewriteCondの制御対象になっていないため、このような書き換えが行われるのである。

 RewriteCondを複数列挙した場合、1個でも評価を満たさない場合、続くWriteRuleの実行がキャンセルされることとなる。

 例を示そう。

RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} (^DoCoMo/|.*UP\.Browser|^J-PHONE/|^Vodafone/|^SoftBank/|^MOT-[CV]980)
RewriteCond %{HTTP_HOST} teachers-room\.ryoou-gakuen\.ac\.jp
RewriteRule (.*) /mobile_contents/$1 [R]

 たとえば上記のような設定があったとする。
 RewriteCondが2個あるが、この2個のRewriteCondの評価結果が共にマッチした場合だけ、RewriteRuleによるURLの書き換えが実行される。
 1個目のRewriteCondでは、クライアントのブラウザが何であるかをチェックしている。具体的には携帯電話のブラウザ(フルブラウザじゃない)かどうかをチェックしている。
 2個目のRewriteCondでは、サーバ名に「teachers-room.ryoou-gakuen-ac.jp」が指定されているかどうかをチェックしている。

 つまり…携帯電話のブラウザでhttp://teachers-room.ryoou-gakuen.ac.jpにアクセスしてきた場合にRewriteRuleの書き換えが実行され、/mobile_contents/配下のコンテンツにアクセスするようにリダイレクトされている。

 さて。RewriteCondの評価パターンには正規表現を記述するので、「マッチしなかった場合」という記述も可能である。
 たとえば、「teachers-room.ryoou-gakuen.ac.jp」以外のURLを一斉にリダイレクトしたい…という場合なら

RewriteCond %{HTTP_HOST} !teachers-room\.ryoou-gakuen\.ac\.jp

 というようになる。

たぶん難しくないApache2・挑戦!RewriteRule・その1~基礎編:リダイレクトしてみる~ [Linux(Apache)]

 私的にWebサーバを立てているような人の中でどの程度、RewriteRuleのお世話になる人がいるのか、とっても疑問ではあるものの、会社内の部門サーバとかそういうところではある程度の需要はあるんじゃないかと思ったりもするので(笑)、ここで紹介してみたいと思う。

 で、「RewriteRule」ってそもそもなんなのよ?   という話からはじまるのでありました。

 簡単に言ってしまうと、決められた法則にしたがって、URLを書き換えるという機能であると理解してもらって、ほぼ差し支えない。
 たとえば、URLに記述されているパス名をCGIの引数に書き換える(読み替える)とか、URLに記述されているパス名から、適用されるバーチャルサーバを変更するとか、アクセスしてきたクライアントのアドレスやFQDN、ブラウザ等の情報に応じて見せるコンテンツ(URL)を変更するとか、とにかくいろいろ出来てしまうのである。
 ただ、「いろいろ出来てしまう」故にぱっと見に難解な印象を持たれてしまって損をしているというところもあるかもしれない。(笑)

 RewriteRuleの使用には、正規表現に対する深く正しい理解が欠かせない。ところが、この「正規表現」もどちらかというと避けられがちなアイテムであったりするので余計にRewriteRuleの敷居を高くしてしまっているフシがあるのもまた事実。悲しいことだけども。(笑)

 ここではまず、RewriteRuleの簡単な使い方等を紹介しつつ、余裕があれば(笑)そのほかのバリエーションなども説明してみたいと思う。

 それではまず、ここで登場するディレクティブを紹介する。2つある。まず一つは
RewriteEngine on … RewriteRuleの機能を有効にする。「on」の部分を「off」にすればRewriteRuleの機能を無効にする。「off」はRewriteRuleのデバッグの時に使うかな…程度だと思う。

 2つ目はメインディッシュである。
RewriteRule 置換前のパターン 置換後の文字列 フラグ
 実際にURLの書き換えを行うディレクティブ。最大で3つの引数を取るが、最後の「フラグ」は省略可能である。(でもあまり省略しない気がする…)

 「置換前のパターン」とは、入力されたURLが、このパターンに一致するかどうかチェックが行われる。たとえば、このパターンに「^/ryoou-gakuen/」と指定されていた場合、URLが「http://server/ryoou-gakuen/hogehoge.html」とかいうケースではこのRewriteRuleが適用されるが、「http://server/washimiya-jinja/hogehoge.html」だった場合には適用されないことになる。

 「置換後の文字列」とは、上記のチェックに一致した場合に書き換えるURLの文字列(パターン)を記述する。細かいことは追って解説することにしよう。

 「フラグ」とは、RewriteRuleによってURLの書き換えを行った後の振る舞いをどうするか…というような指定を行う。この項目の存在によって、RewriteRuleが多様な処理を行うことが出来るようになっているが、逆にこの項目の存在がRewriteRuleを難解に感じさせてしまっているようにも思う。フラグについても追って解説することにする。

 では、とにかくお手軽なRewriteRuleの例から。「serverA」のhttpd.confにこう記述したとする。

RewriteEngine on
RewriteRule (.*) http://serverB/$1 [R]

 serverAにあったコンテンツが丸ごとごっそりとserverBに引っ越しました…という場合でも想定してもらえばよいだろうか。serverAの中にあるありとあらゆるコンテンツに対するリクエストを、serverBの同じパス位置にリダイレクトしている。

 「置換前のパターン」の位置にくるのは、サーバ名を除いたパス名の部分がチェックされる対象となる。たとえば、「http://serverA/ryoou-gakuen/hogehoge.html」というURLの場合は、「/ryoou-gakuen/hogehoge.html」がパターンの検査対象になっているということ。
 上記のRewriteRuleディレクティブでは、「(.*)」と指定されていることから、0文字以上の任意の文字列がマッチすれば、RewriteRuleが実行される…ということになる。カッコで囲まれているが、これには意味がある。詳しくは正規表現の解説書等を読んでもらいたい(笑)が、カッコで囲まれた部分はRewriteRuleディレクティブの「置換後の文字列」の部分で再利用が出来るようになるイメージ。上記の例では、「http://serverB/$1」と記述しているが、この「$1」の部分に、カッコで囲まれた正規表現にマッチした内容が代入されるのである。

 http://serverA/ryoou-gakuen/hoge.htmlのアンダーラインの部分が「(.*)」の「.*」にマッチする。このマッチした部分がカッコで囲まれているので、変数「$1」に保存される。
 ↓
 置換後の文字列で、http://serverB/$1としているので、変数$1が展開され、http://serverB/ryoou-gakuen/hoge.htmlとなる…という寸法。

 わかったかな??

 では、http://serverA/ryoou-gakuen/ と、http://serverA/washimiya-jinja/ というディレクトリがあったとして、「/ryoou-gakuen/」の配下だけserverBに移転しました…という場合はどうすればよいか。

RewriteEngine on
RewriteRule ^(/ryoou-gakuen/.*) http://serverB/$1 [R]

 こういうことになる。

 では、「ディレクトリが移転しました」という場合。
 このような場合はaliasディレクティブを使っても良いのだけども、RewriteRuleで対応するなら、基本パターンとしては…

RewriteEngine on
RewriteRule ^/旧ディレクトリ/(.*) /新ディレクトリ/$1 [R]

 というパターンになるだろうか。ディレクトリの深さも変更することが出来る。たとえば、/ryoou-gakuen/ディレクトリを、/lucky-star/の下に配置した場合(結果的に「/lucky-star/ryoou-gakuen/」ということになる)

RewriteEngine on
RewriteRule ^(/ryoou-gakuen/.*) /lucky-star/$1 [R]

 という具合。

 ここで、ちょっと注意が必要。RewriteRuleディレクティブに渡す最初のパターンは、grepコマンドのパターン指定と同じ感覚でマッチングが行われる。このため

RewriteRule /ryoou-gakuen/(.*) /lucky-star/$1 [R]

 このように記述した場合は、URLに
 http://server/ryoou-gakuen/hogehoge.html
 http://server/lucky-star/ryoou-gakuen/hogehoge.html
 http://server/otherDirectory/ryoou-gakuen/hogehoge.html
 上記のいずれも置換の対象になってしまうので注意が必要。その理由が判らない人はもう一度grepコマンドの勉強をしてくるように!!

たぶん難しくないApache2・Webサーバでファイルサーバ?の補足編~WebDAV+ダイジェスト認証~ [Linux(Apache)]

 続いて、WebDAVでセキュリティ的な問題をどうにかしたいと思う。
 前アーティクルの設定ではWebDAVでファイルを読み書きするために特に認証や制限をかけていないので、誰でも使えるスペースを提供するようになっていた。が、実際にそんな状態でサーバを運用することは無いと思う。そこで、WebDAVでアクセスさせる領域には何らかのアクセス制限をかけるべきであろう。認証については以前のアーティクルですでに紹介しているので、それを組み合わせるだけなんだけども、実例を兼ねて紹介してみる。

 WebDAVでアクセスする領域に対する設定の基本形として

<Directory /var/www/html/dav>
Dav ON
</Directory>

 としていたところに、たとえばIPアドレスで制限をかけるとすれば、
<Directory /var/www/html/dav>
Order Allow,Deny
Allow from 192.168.0.
Deny from All
Dav ON
</Directory>
 たとえばこんな具合かな。192.168.0.???のアドレスからのアクセスはWebDAVアクセスを許容する感じになる。

 また、ダイジェスト認証と組み合わせると
<Directory /var/www/html/dav>
Dav ON
AuthType Digest
AuthDigestProvider file
AuthUserFile auth/userdigest
AuthName "WebDAV Auth"
Require valid-user
</Directory>
 という具合になる。ここではもちろん、htdigestコマンドでアクセスを許可されたアカウントとパスワードの組を作成しておく必要がある。

たぶん難しくないApache2・Webサーバでファイルサーバ?~一番簡単なWebDAV編~ [Linux(Apache)]

 さて。今度は「WebDAV」に挑戦してみよう。なお、ここではまずはじめにWebDAVの設定について一番簡単な設定を紹介するが、セキュリティ上非常に問題があるので、このまま外部へ公開してしまわないように!!!

 まず、「WebDAV」とはなんぞや?というところから。詳しいことはWikipediaを見てもらうとして(ちなみに該当ページへのリンクはこちら)、要するに、httpによってWebサーバ上あるファイルを管理できるようにする(≒Webサーバをファイルサーバにできる)機能だということ。
 Windowsのファイル共有やsambaのファイル共有、NFSもそうかな…と似ているように見えるが、WebDAVは既存のプロトコル「HTTP 1.1」の上に実装されているので、とりあえず80番ポートだけ開いていればルータとかファイヤーウォールとかを越えてファイルを受け渡しできるという特徴が大きい。また、WebサーバにWebDAVの機能を用いてファイルをアップロードした場合、それをすぐさまブラウザ等で閲覧できることから、コンテンツの更新にも便利…というタテマエがあったりする。

 もっとも、うっかり無防備な状態でWebDAVサーバを外部に公開しようものなら、たちまち違法なファイルとかウィルスとかワームとかの巣窟になってナントカ県警サイバーナントカ課の人があなたの家の玄関をノックする事態になるかもしれないので、WebDAVサーバをシロウトが外部公開することはオススメしない。
 会社の中のイントラネット等において、ファイルを公開する(文書ファイルとか、社内で開発しているソースコードやライブラリ、モジュール等)用途などにおいては便利に使える局面もあるかと思うが。

 それでは、WebDAVの設定について解説する。

 ここで登場するディレクティブはたったの2個。「Dav」ディレクティブと、「DavLockDB」ディレクティブ。なんだかごちゃごちゃ書いてある解説サイトもあるけども、とりあえずWebDAVを機能させるだけならコレだけでよい。もちろん、セキュリティ的なことを考えるともっと必要になるのだが。

 それでは、WebDAVを使用可能にするための手順から。
手順1:WebDAVでファイル管理の対象とするディレクトリを作成する(≒ファイル置き場を作る)
手順2:httpd.confにWebDAVのための設定を記述する

 これだけ。なお、WebDAVで管理される領域にあるファイルをクライアントから操作する場合は、クライアント側にも準備が必要となることを付け加えておく。

手順1:WebDAVでファイル管理の対象とするディレクトリを作成する(≒ファイル置き場を作る)

 ドキュメントルートディレクトリの下に、WebDAVで管理する領域を作成する。これまで散々使用しているhttpd.confのサンプルが、ドキュメントルートとして「/var/www/html」を指定しているので、とりあえずここでは「/var/www/html/dav」をWebDAVで管理するディレクトリにする。

 mkdir /var/www/html/dav
 …と、これでディレクトリを作成した。
 ただしここで一点注意事項が。クライアントからのリクエストに基づいてhttpdがファイルを書いたり読んだり消したりするため、httpdが動作しているユーザー・グループでそのディレクトリの中にアクセスできる必要がある。サンプルのhttpd.confの場合はUserもGroupも「apache」という名前になっているので、このユーザーで読み書きできなければならない。
 chown apache:apache /var/www/html/dav
 …と実行しておき、ディレクトリオーナーを変更することにする。

手順2:httpd.confにWebDAVのための設定を記述する

 ではいよいよhttpd.confの中にWebDAVの設定を導入する。
 ドキュメントルートの中でも、特に「/var/www/html/dav」に対してのみWebDAVの操作を許可することになるので、「Directoryディレクティブ」を用いて、このディレクトリに対するWebDAVの許可を指定することとなる。そして、WebDAVの使用を許可するディレクティブには、「Dav On」ディレクティブを用いる。
 ということは…

<Directory /var/www/html/dav>
Dav On
</Directory>

 という記述を追加することになる。

 で、WebDAVがファイルの排他制御を管理するために使用する、「ロックファイル」を指定するディレクティブが別途必要になるので、これをさらに追記する。「DavLockDB (ロックファイルのパス名)」である。ひとまずここでは、ロックファイルとして「/tmp/LockFile_WebDAV」と指定することにする。

DavLockDB /tmp/LockFile_WebDAV
<Directory /var/www/html/dav>
Dav On
</Directory>

 と、この4行を書き加えるだけで終了する。(笑)
 あ、モジュールの読み込みもあるね。

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so

 この2行も必要ということに。
 これまでで完成したhttpd.confの例を以下に示すと…
ServerRoot      "/etc/httpd"
PidFile         run/httpd.pid
Listen          80
User            apache
Group           apache

ServerName      kagami.hiiragi.com:80

DocumentRoot    "/var/www/html"

LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_default_module modules/mod_authz_default.so
LoadModule dir_module modules/mod_dir.so
LoadModule mime_magic_module modules/mod_mime_magic.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so

<Directory      />
        Order   Allow,Deny
        Deny from       All
</Directory>

<Directory      /var/www/html>
        Order   Deny,Allow
        Allow from      All
</Directory>

<Files  ~       "^\.ht">
        Deny from       All
</Files>

DavLockDB       /tmp/LockFile_WebDAV
<Directory      /var/www/html/dav>
        Dav     On
</Directory>

TypesConfig     /etc/mime.types
DirectoryIndex  index.html
AddDefaultCharset       off
MimeMagicFile   conf/magic

 こういうことになる。これでservice httpd startと実行する。

 なお、WebDAVでファイル管理をする場合は、WebDAVクライアントが必要になるが、Windows98以降ならWindowsに組み込まれている(Windows Vista 64bit版は例外らしい!?)ので、特にクライアントソフトを用意しなくて良いらしい。
 Windows XPの場合は以下のとおり。

1.「マイ ネットワーク」アイコンをダブルクリックする
2.「ネットワークプレースの追加」アイコンをダブルクリックする
3.「ネットワークプレースの追加ウィザードの開始」というウィンドウが表示されうので「次へ」ボタンをクリック
4.「別のネットワークの場所を選択 Webサイト、ネットワークの場所、またはFTPサイトのアドレスを指定してください。」というアイコンをクリックして選択した状態で「次へ」ボタンをクリック
5.「インターネットまたはネットワークのアドレス」に、「http://(server)/dav/」と入力して「次へ」ボタンをクリック
6.「このネットワークプレースの名前を入力してください」にはお好みで好きな名前をつけて「次へ」ボタンをクリック
7.「完了」ボタンをクリック

 これでウィンドウが開くと思われるので、そこにファイルをコピーするなり移動するなりしてやればよい。
 日本語のファイル名も大丈夫…のはず。(今試してみたが大丈夫だった…。環境によるかもしれないが。)

 http://(server)/dav/file.txt

 とかブラウザでアクセスすれば、フォルダにコピーしたデータがブラウザ上で閲覧できることを確認しておいてもらいたい。

 なお、繰り返しになるが、くれぐれも、このままの状態でWebサーバを外部に公開したりしないように!!!
前の10件 | - Linux(Apache) ブログトップ
メッセージを送る