(仮)IT技術関連中心の備忘録この広告は、90日以上更新していないブログに表示しています。今年もあっという間に終わってしまいます。お世話になった方々に心より感謝申し上げます。年末年始は故郷の北海道に帰省します。毎日更新している天気データマップは本日より一週間ほど更新をお休みします。ファイルのgzip圧縮(初級編)はじめにサイトの事前圧縮処理ではgzipを用いますが、ここではその具体的な方法について補足説明します。できるだけ初級者の方にも分かるような説明を心がけます(Unix系の開発経験者なら読む必要はありません)。gzipコマンドについてgzipは可逆圧縮アルゴリズムを用いてファイルの圧縮・展開を行うコマンドで、Unix系の環境(LinuxやMacなど)には標準でインストールされています。Windowsでgzipを利用するにはWindowsにはgzipは入っていませんが、Windows用のgzipはいくつもあります。私のお勧めはMinGWのMSYSで、これをインストールすればWindowsで(gzipを含む)Unix系基本コマンド一式が使えるようになります。http://sourceforge.net/projects/mingw/files/インストール方法は次をご覧ください。msys-baseというのがMSYSで、これを選択するとインストールされます。インストール後のパス設定(例:C:\MinGW\msys\1.0\bin)の追加も忘れずに行って下さい。http://web.plus-idea.net/2014/06/mingw-install-2014/使用法(コマンドラインオプション)ここではサイトの事前圧縮に必要な使用方法だけ説明します。オプションなしでファイル名だけ指定するとそのファイルを消去して拡張子.gzの圧縮ファイルに変換します。次の例はindex.htmlを消去してindex.html.gzを出力します。index.htmlすでにターゲットのindex.html.gzが存在する場合はプロンプトを表示して上書きするかどうか聞いてきます。index.htmlとします。圧縮ファイルを展開して元通りにするには-dを使います。次で圧縮ファイルを消去し、元の非圧縮ファイルを生成します。index.html.gz元ファイルを残して圧縮ファイルを生成する場合は-c(stdoutに出力)を使い、リダイレクトしてファイルを生成します。index.html.gz圧縮ファイルを残して元ファイルに展開する場合は-d(展開)と-c(stdoutに出力)を組み合わせ、やはり最後はリダイレクトでターゲットファイルを生成します。index.html圧縮レベルは-1から-9の間で設定できます(デフォルトは-6)。数値が大きいほど圧縮率が高くなりますが、その分処理に時間がかかります。最高の-9はデフォルトの約2倍の処理時間を要しますが、圧縮率はあまり変わりません(違いはたかだか1%程度)。特別な理由がなければデフォルト設定で十分です。ファイルの一括処理ファイル数が多くなってくると、コマンドを手動でタイプするのが困難になってきます。処理を自動化する方法はいくつもありますが、ここでは次の3通りについて簡単に説明します。findを使うシェルスクリプトを使うスクリプト言語を使う(Rubyの場合)findを使う(Unixの)findはディレクトリ内を探索し、設定条件に一致したファイルを操作するコマンドです。豊富な機能がありますが使用法はちょっと複雑です(慣れが必要です)。マニュアル(和訳)は次の通りです(しかし読むのは大変でしょう)。Windowsのfindコマンドとは全く別です。MSYSにはfindも含まれていますが、普通のパス設定ではWindowsのfind.exeが優先するため動きません。...)などの対応で利用できます。簡単な使い方の例を示します。./siteディレクトリの中にある全ての.bakファイルを探して削除します(探して表示するだけの場合は-deleteを書かない)。これを知っているだけでも十分便利です。-delete*.bakは*の部分をコマンドライン(シェル)が展開しないよう上記の通り\でエスケープするか、またはクォートで囲む必要があります("*.bak")。-execオプションを使い、条件に一致するファイルに対して任意のコマンドを実行できます。全てのhtmlファイルを検索してgzip圧縮ファイルに変換する例を示します。";"元に戻す場合は次の通りです。";"ポイントをまとめておきます。注意する点は最後の;の扱い方です。;またはクォートで囲めばOKしかしfindだけでできることには限りがあります。元のファイルを残して圧縮ファイルを生成する場合はリダイレクトを使うため、findの引数一行の中だけで表現するのは困難です。普通の方法ではできないと思いますが確認していないので「困難」という表現にしました。仮にできたとしてもシェルスクリプトやプログラミング言語を利用した方が理解しやすく管理も容易だと思います。シェルスクリプトを使うシェルスクリプトを使えばもっと複雑な処理が可能になります。Bashからfindを起動し、元ファイルを残して.gzファイルを生成する例を示します。fは「通常ファイルのみ」の意味です(ディレクトリやシンボリックリンクを除外するための対策)。fidoneスクリプト言語を使う(Rubyの場合)高級スクリプト言語を使えばさらに複雑な処理を行えます。ここではRubyの場合を説明しますが、Rubyを使うことには次のような利点があります(あくまで個人的見解)。シェルスクリプトと比較して文法が美しく洗練されている書き方を統一できる(シェルは方言が沢山あるがRubyは基本的にない)環境依存性をRubyが吸収してくれる(特にWindowsでも同じコードで動く)PerlやPythonなど別の言語が得意な人はそれに置き換えて下さい。得意言語を何か一つ持っているのは大きな武器です。それでは実際の例を示します。Rubyの標準ライブラリにはfindモジュールがあり、findコマンドと同じ手順でディレクトリ探索を行うことができます(これを使えばfindコマンドは不要です)。http://docs.ruby-lang.org/ja/2.2.0/library/find.htmlRubyで可能な機能は全て組み込むことができますが、ここではファイルの更新チェック機能を付けます。.gzファイルが存在しない(新規ファイル)か、または元ファイルより古い(ファイルが更新された)場合だけgzipを実行します。'./site'この程度までの機能ならシェルスクリプトでも組めますが、(少なくとも私の場合は)Rubyの方がはるかに楽に書けます。Windowsで同じコードがそのまま使えるのも大きなメリットです。レンタルサーバを使う場合はさらに改良して、探索時に.gzを更新(生成)したファイルを記憶しておき、更新されたファイルだけftpコマンドで自動アップロードする事もできます。これは天気データマップの毎日のメインテナンスで実際に行っていますが、非公開部分を含んでいるため割愛します(ご了承下さい)。ファイルのgzip圧縮(初級編)はじめに前回説明したmod_deflateを使う方法ではリクエストがある毎にサーバ側でgzip圧縮処理を行いますが、これはサーバ側CPUの負荷を発生します。そこでファイルを事前圧縮しておき、それを直接返すようにすればサーバ負荷を大幅に改善できます。ファイルのgzip圧縮まず圧縮効果があるタイプのファイルをgzip圧縮し、元ファイルと同じディレクトリに拡張子.gzで保存します。方法は2通りあります。元ファイルを残すかどうか今のブラウザは全てgzip圧縮対応ですから、実はブラウザからアクセスする場合は元ファイルは使われません。元ファイルが必要なのはcurlなどのコマンドツールやRuby/Pythonなどのプログラムコードからアクセスするようなケースだけです。元ファイルを消去してしまい、非圧縮ファイルを要求された場合はサーバ側で圧縮ファイルを展開処理して返すように設定することも可能です。この方法はファイル数が増えず、さらにディスク容量を大幅に削減する大きなメリットがあります。非圧縮ファイルを要求された場合に展開処理を行うためわずかなサーバ負荷が発生します。展開処理は圧縮よりはるかにサーバ負荷が少なく、さらに非圧縮で返す要求自体が今ではほとんどありません。以下両方の場合の設定方法を説明します。2.4を対象とします。最小限に単純化した文例を使って説明します。cssの3つの拡張子だけを対象としていますが、きちんと理解すれば自分でいくらでも拡張できます。text/css</FilesMatch>全体の流れを示します。Apacheサーバは次のように応答します。次の条件を全て満たす場合だけ対応(それ以外は通常処理)リクエストヘッダがgzip圧縮を受け付ける.gz生成時に指定した拡張子にマッチする事前圧縮した.gzファイルが存在する以上を全て満たす場合は次の通り応答URLの末尾に.gzを追加(bodyとして事前圧縮した.gzファイルを返す)ファイルタイプを強制的に.gzなしのタイプに設定するApacheではこれをmod_rewriteモジュールを利用して設定します。http://httpd.apache.org/docs/current/ja/mod/mod_rewrite.htmlmod_rewriteを有効にする初期状態ではmod_rewriteの機能はoffになっています。これを次の一行でonにします。次にレスポンスヘッダ書き換え処理を行う条件をRewriteCondディレクティブで設定しますが、書式はとても難解です。全部読んでいるとそれだけで日が暮れそうなので要点を順番に説明します。http://httpd.apache.org/docs/current/ja/mod/mod_rewrite.html#rewritecondまず一行の書式は次の通りで、TestStringの部分が条件を設定する対象、CondPatternがマッチさせる条件(通常は正規表現)です。複数のRewriteCond行はand結合し、全て満たす場合が書き換え対象となります。CondPattern今回はTestStringとしてリファレンスに書かれているServer-variablesを設定します。これらは%{NAME_OF_VARIABLE}の形式で記述します。リファレンスにはNAME_OF_VARIABLEの一覧(四角で囲まれた部分)がありますが、これだけではありません。リファレンスのずっと先の部分(箇条書きの4)に%{HTTP:header}という書式があり、headerにはリクエストヘッダの任意の項目を指定できます。これを最初に用い、Accept-Encodingの値にgzipが含まれているか判定します。gzip次のREQUEST_URIはURLから(もしあれば)クエリ部分を除いたものです。これで拡張子を判定します。クエリはQUERY_STRINGで取得できます。次のREQUEST_FILENAMEはURLに対応するローカル側ファイルシステムのフルパスで、これに.gzを付けて事前圧縮したファイルが存在するかチェックします。判定は(正規表現は使えないので)-sフラグ(通常ファイルなら真)を使います。以上の条件を全て満たす場合のレスポンスヘッダ書き換え処理をRewriteRuleディレクティブで設定します(こちらもリファレンスは複雑怪奇です)。http://httpd.apache.org/docs/current/ja/mod/mod_rewrite.html#rewriterule書式は次の通りです。[flags]各項の意味は次の通りで、ここでのURL-pathはURLからスキームとホスト名を除いたものです(http://example.com/path/file.htmlの場合は/path/file.html)。各種設定と制御(後述)今回は次のように設定します(意味は後で説明します)。Patternには.*(全てにマッチ)を指定します。次のSubstitutionでURLをどう置換するかを記述します。ここではRewriteCondで用いたServer-variablesの書式%{REQUEST_URI}でURLを参照し、その最後に.gzを追加します。最後のフラグは[L]のように角括弧の中に書きます。[L]は[last]の略で、置換処理をこれで終了することを意味します。複数の置換処理を組み合わせることも可能です。デフォルト(フラグなしは)次のルールを(無条件で)評価します。条件のand結合は[C](chain)です。最後に[L]を指定して終了を認識させます。ファイルタイプの書き換え以上で圧縮ファイルが存在する場合はパスに.gzを追加して事前圧縮ファイルを返すところまではできました。このままではファイルタイプ(Content-Type)が.gz(application/gzipまたはapplication/x-gzip)に設定されます。最後にファイルタイプを書き換える処理が必要です。FilesMatchディレクティブで書き換えが必要なファイル拡張子を検出します。http://httpd.apache.org/docs/current/ja/mod/core.html#filesmatchそして検出した拡張子別にファイルタイプをForceTypeで強制的に付け替えます。http://httpd.apache.org/docs/current/ja/mod/core.html#forcetype以上まとめると次のようになります(htmlの場合)。拡張子別にファイルタイプが異なりますから、他の拡張子も同じ要領で記述して対応します。...>を利用してひとつにまとめることも可能ですが、かえって分かりにくくなると思います。元ファイルを残す場合は以上です。次は残さない場合の設定方法を説明します。元ファイルを残さない場合Apacheにはコンテントネゴシエーションのサポート機能があり、これを利用して非圧縮コンテンツを返すよう要求された場合にgzip圧縮ファイルを展開して返すことができます。コンテントネゴシエーションとはリクエストヘッダを読み、それに最も適したコンテンツを提供する機能です。具体的にはAccept-から始まるヘッダ行の値を読み、そこから応答するページ(ファイル)を選択することができます。http://httpd.apache.org/docs/current/ja/content-negotiation.html(典型例として)Accept-Languageの値から応答する言語を切り替える場合はindex.html.enやindex.html.jaのように拡張子の末尾に言語コードを付けたファイルを用意し、ヘッダの値により応答するファイルを選択します。http://httpd.apache.org/docs/current/ja/content-negotiation.html#namingこのバリエーションとしてAccept-Encodingの判定機能があり、gzipを含む場合は拡張子の末尾が.gzのファイルを返すように設定できます。非圧縮コンテンツを要求された場合は.gzファイルを探し、それを自動展開して返します。設定例は次の通りです。以下、他のファイルタイプも同様(略)設定方法はtype-mapファイル(httpd.conf専用)とMultiViewsオプションの2通りありますが、ディレクトリ別の設定や.htaccessに記述する場合はMultiViewsを用います。MultiViewsは初期状態では無効に設定されているので、次で有効にします。+MultiViews次にMultiViewsを適用する拡張子を設定します。ここで設定しているAnyは無条件に全て受け付ける事を表します。Any設定にはmod_filterを用います。mod_deflateという今回の目的そのものの文例があります。http://httpd.apache.org/docs/current/ja/mod/mod_filter.htmlmod_gzipはバージョン1.X時代のモジュール名です(現在は代わりにmod_rewriteを用います)。今回はこれをそのまま頂くことにします(詳細調査は略)。gzipが設定されていない場合だけinflate処理が実行されます。gzipなおFilterProviderの書式にはバリエーションがあります。次は関数のreqを使った例です(動作確認済み)。先頭の!とマッチ部の=~の組み合わせで「マッチしなければ」という条件になりますが、この短縮形が上で用いている!~です。2.2以前は書式が異なります(ただし私は動作確認していません)。!$gzipリファレンスの記述は以上ですが、この状態で動作確認するとやはり圧縮対応時のContent-Typeが全てgzipの設定になります(元ファイルを残す場合の動作と同様)。そこでForceTypeで拡張子別にファイルタイプを設定します(以下は.htmlの設定例)。text/html</FilesMatch>運用例この方法で天気データマップのサイト設定を行いました。サーバ内部の設定は(バックアップの意味も兼ねて)次のURLで公開しています。http://higuma.boo.jp/tenki-data-map-files/実サイトの.htaccessはhtaccess_exampleというファイル名にしています。data/hourly/内のファイルはサイズ、ファイル数とも膨大なので.tar.gzアーカイブで保存しています(バックアップ用)。まとめApacheをこんなに詳しく勉強したのは始めての経験でしたが、書式が非常に難解でかなり苦労しました。私は(多少のサイト管理はできますが)基本的にはプログラマーで、どちらかと言えばAPI仕様を作る側に近い人間です。大昔に作られたソフトのAPIを長年機能拡張すると最後はここまで複雑になってしまうのかというのを思い知りました。これは仕方ない事だと思います。あまりにもメジャーなソフトなので後方互換性を考慮した仕様変更しかできません。そのような足し算の変更が積み重なると必然的にこうなるのはよく分かります。過去のしがらみがない後発サーバはもっとシンプルです。Nginxは専用設計されたgzip最適化機能があり、設定方法も簡単です。次の解説を読めばそれだけで十分理解できます。http://qiita.com/cubicdaiya/items/2763ba2240476ab1d9ddしかしApacheは長年に渡る抜群の実績があります。今後も使われるでしょうし、今でもApacheと.htaccessでがんばっているサイト管理者は多いと思います。本解説が皆さんのお役に立てたら幸いです。WHR-G301Nは5年ほど前の製品ですが今でも使っている人は多いようです。ところが掃除中に配線整理のため電源を抜き差ししていたら突然壊れてしまいました。今回の故障ではLEDが高速点滅するという特有の現象がありますが、検索すると同様の症例がたくさん見つかります(同じ目にあった人が何と多いことか...)。次のブログ記事を見つけて解決できました。症状と解決方法は秀さんのブログに写真付きで詳しく書かれています。http://m-syuuta.wp.tcp-ip.or.jp/?p=3487実はACアダプターの故障です(本体は壊れていません)。推定原因はACアダプターの整流平滑素子の劣化で、LEDの高速点滅と同じ(かなり高速の)周期で電源が乱高下してルータが起動できなくなっていると考えられます。5年も使っていますが機能は全く文句ありません(よい製品です)。ACアダプターがやや安物で劣化が早いようです。検索すると電源抜き差しを頻繁に行うと劣化が早まる傾向が見られます。テスターを持っている人はACアダプターの電圧を測定すれば12V前後で針がふらふら揺れるのを確認できます。高速変動なのでデジタルテスターでの確認は難しいでしょう。今回使ったのはアナログで、デジタルより針の反応がよいので揺れを検出できました。オシロスコープがあればベストですが持っている人はなかなかいないと思います。交換アダプターの購入ACアダプターの交換だけで簡単に直ります。これも秀さんが調べてブログに購入先URLも全て貼ってくれていますのでそちらをご覧下さい(同じURLですがもう一度)。http://m-syuuta.wp.tcp-ip.or.jp/?p=3487ちなみに私はマルツからSW-1212Eを購入して解決しました(税、送料込みでちょうど¥1,900)。Amazon経由でも買えますが¥200ほど高くなりますのでマルツからの直接購入がお勧めです(対応も完璧でした)。WHR-G301N)のトラブルシューティングTweet広告を非表示にするもっと読むコメントを書く2015-11-29天気データマップ復旧しました11/25から更新が止まっていましたが、本日よりまた毎日更新できるようになりましたのでお知らせします。http://higuma.boo.jp/tenki-data-map/ついでなので最新データを紹介します。11/24,25に北海道(私の故郷です)に大雪が降りました。雪は止んでいますが積雪は残っています。昨日深夜の積雪分布マップを貼っておきます。札幌には40cm以上も積もりましたが、もう半分以上解けています。根雪にはならないと思います。15:18天気データマップ復旧しましたTweet広告を非表示にするもっと読むコメントを書く2015-11-27天気データマップに関するお知らせ(データ更新の一時停止)(私の自宅で)昨日発生したネットワークトラブル(ルータ故障)により天気データマップのデータ更新が止まった状態になっています(現在の最新データは11/24)。現在は詳しい原因の調査中で、復旧にはまだ数日を要する見込みです。再開できましたらこの場でお知らせします。ファイルのgzip圧縮(初級編)サーバの対応方法サーバがファイルをgzip圧縮して返信する場合の対応方法は2種類あります。要求を受信したサーバがその場でgzip圧縮を行い返信するあらかじめgzip圧縮しておき、それを返信する設定は1の方が簡単です。サーバが要求を受信するたびに毎回gzip圧縮処理を行うためサーバに負荷が発生します。2はファイルをgzip圧縮しておく事前準備が必要です。運用時にgzip圧縮処理によるサーバ負荷は発生しません。手間は掛かりますがこの方法が最も効率的に処理できます。具体的な設定方法はサーバソフトウエアの種類によって異なりますが、ここでは今回設定したApacheの場合を解説します。Apacheの設定Apacheではサーバの各種設定をhttpd.conf、.htaccessの2種類のファイルで記述します。https://murashun.jp/blog/20141229-01.htmlメインの設定ファイルは通常httpd.confという名前で、多くの場合は/etc/httpd/conf/httpd.confなどの場所にあります。ファイル名と場所(パス)はApacheのインストール(またはビルド)時に自由に設定できます。ディレクトリ個別に設定する場合は.htaccessを用います。このファイルは任意の場所に複数置くことができ、その位置から先のディレクトツリー全体に対して作用します。httpd.confと.htaccessで同じ項目で異なる設定をしている場合は.htaccessが優先(オーバーライド)します.htaccessが複数ある場合は内側が外側の設定をオーバーライドしますレンタルサーバの場合は通常http.confは業者側で管理しており、自分では設定できません。業者側のメイン設定は通常非公開ですが、多くの設定は.htaccessでオーバーライドして修正できます。mod_deflateによるサーバサイド圧縮Apacheにはmod_deflateモジュールを使ってサーバ側で圧縮処理を行う機能があり、.htaccess(またはhttpd.conf)に記述すれば対応できます。次のリファレンスの冒頭部から読むのが分かりやすいでしょう。https://httpd.apache.org/docs/current/ja/mod/mod_deflate.htmlApacheではmod_で始まる名前は拡張モジュールを表します。これらはもともと拡張機能扱いだったものですが、今では大部分が標準的なディストリビューションに最初から含まれています。http://httpd.apache.org/docs/current/ja/mod/特定のタイプだけ簡単に圧縮したい場合は最初の文例をまねて書けばそれで十分です。必要に応じてtext/cssなど自分で追加すれば機能します。text/xmlもっと詳しい設定は次の「画像以外全て圧縮する」コード例がよい参考になりますが、これは大昔(少なくとも15年以上前)のブラウザに対応するためのコードです。ブラウザ別処理の部分は今はもう省略していいと思います。ここではリファレンスの例を最小限まで簡略化したものを示します。Apacheの専用書式で記述しますが、やはり#から行末まではコメントです(念のため)。実質たった2行ですが正確に把握するにはリファレンスを隅々まで確認する必要があります。no-gzipまずApacheでは送受信データに対する処理をフィルタといい、出力のフィルタはSetOutputFilterで設定します。http://httpd.apache.org/docs/current/ja/mod/core.html#setoutputfilterApacheの出力用フィルタはINCLUDESとDEFLATEの2種類あります。DEFLATEはmod_deflateモジュールの機能を使いファイルをgzip圧縮します。DEFLATEこれだけだと全てのファイルタイプを圧縮することになります。特定の拡張子を除外する設定が必要ですが、この部分のメカニズムがApacheはやや複雑です。Apacheでは操作の各種制御に環境変数という名前付き変数を用います(OSの環境変数とは無関係)。no-gzipはgzip圧縮を制御するための特別な環境変数で、設定するとDEFLATEフィルタをOFFにします。http://httpd.apache.org/docs/current/env.html#special特定の拡張子を検出して環境変数を設定するにはSetEnvIfを用います。http://httpd.apache.org/docs/current/ja/mod/mod_setenvif.html#setenvifここではRequest_URI(URLのスキームから後ろ全て)に正規表現マッチを用い、末尾の拡張子を検出して判定しています。no-gzip正規表現の(?:A|B|...)はキャプチャなしのグループ化です。マッチ条件は(A|B|...)と同じですが、キャプチャをしない分だけ若干効率が向上します。SetEnvIfNoCaseはSetEnvIfのバリエーションで、大文字と小文字を同一と見なして処理すること以外は同じです。これで大文字の.GIFや.MP3なども除外対象とすることができます。http://httpd.apache.org/docs/current/ja/mod/mod_setenvif.html#setenvifnocase説明は以上です。自前でApacheサーバを立てる場合はこれをhttpd.confに記述するのが一般的な方法です。レンタルサーバの場合は自分が管理する起点のディレクトリに.htaccessで記述すれば設定できます。レンタルサーバの場合なおレンタルサーバでは業者側(httpd.conf)であらかじめ基本的なファイルタイプに対して設定してくれているケースが多いようです。txtに対して設定されているのを確認しています(2015年11月現在)。他のタイプは確認していませんので必要な場合は自分で行って下さい。必要な設定がされていれば何もする必要はありませんが、詳細は業者で当然異なりますから実際にブラウザで確認することをお勧めします。ファイルをアップロードしてブラウザで読み込み確認し、必要なファイルタイプを.htaccessで追加設定する手順で対応できます。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。