技術メモの最近のブログ記事
東京に打ち合わせに行ったついでに、念願のプログラマーズカフェに顔を出してきました。
モバイラーズオアシスに関して有益な助言をいっぱいいただいてホクホクです。
で、それとは関係があるようなないようなで、HTML5とかiPhoneのWEB作成について聞かれました。
おおよそのことはジュンヤさんがお話しされていたし、僕の知っていることはwebteko#11Html5で作るiPhoneアプリケーション2010に書いたとおりなのですが、 HTML5のアプリケーションキャッシュに関して書いてなかったことに気がついたので、軽くまとめてみます。
正直、自分は使いこなせなくて立ち止まっている状態なので、遠慮なく屍を踏み越えていってくださいませ。
HTML5のアプリケーションキャッシュとは
オフラインキャッシュとも呼ばれるみたいです。マニフェストファイルというのを書いておくことで、画像とかHTML,CSSなどをキャッシュに保存しておき、次回以降ネットワークにつながっていなくても該当サイトを表示することを可能にします。iPhoneでつかうと、起動が早くなるので、まるでiPhoneアプリのような動作をさせることもできます。
マニフェストファイルの書き方については、
W3C-OfflineWebApplications日本語訳-HTML5.JPを見ればばっちりわかります。というかファイルを列挙すれば終わりです。
ただ、安直にキャッシュすると、じゃあそのファイルをどうやって更新するんだ、というところで困ります。自分一人ならブラウザキャッシュをクリアすればいいですけど、お客さんにそんなこと言えませんので。
その点については、この記事が詳しい。
- 【特集】詳解!HTML5と関連APIの最新動向-Webアプリ開発編(1)本特集の趣旨|エンタープライズ|マイコミジャーナル
- iPhone用Webページのcheatsheet-memo.xight.org
あと、iPhoneでキャッシュを使うと、Geolocation APIが失敗するようになりました。原因を突き止められなくて、現在はキャッシュを使うのをあきらめている状態です。
なんだか中途半端にしかわかっていないことばかりのような気もしますが、何かのお役に立てば幸いです。自分が書いたものながら、じつはとても心配なことが一つあったのです。
このサイト、検索できるの?
GoogleやYahooで「栄ゐ田」を検索した時、ちゃんと引っかかってくれるの?栄ゐ田さんがテレビで取り上げられて、名前を検索した人は、ちゃんとこのサイトにたどり着くことが出来るの?
ソースを見ていただくとわかるのですが、縦書きの文字列でも、ソースコード上はちゃんと普通のテキストとして書かれています。

W3Cの規格上もvalidなHTMLソースコードですから、理屈の上では、大丈夫なはずで。そうはいっても、こればかりはやってみないとわかりません。新しいサイトが検索結果に反映されるにはちょっと時間がかかるので、じつは内心ドキドキしつつ待っていたのですが。

栄ゐ田のだしまき - Google 検索

Yahoo!検索 - 栄ゐ田のだしまき
キター!━━━━━━(゚∀゚)━━━━━━ !!!!!
というわけで、縦書きしてあっても、SEO上特に不利にはなりません(有利にもなりませんけどw)。
ウェブテコ第7回では、懇親会をこの栄ゐ田さんで行なうそうです。4500円でこのお店だったらかなりお得だと思うので、興味のある方はぜひお越しくださいませ。
サーバの移行を検討しています。
今使っているのが、さくらの専用サーバ。月額7800円で、完全に一台貸していただけるサービスです。
スペックも使い勝手もいいので満足しているのですけど、先日の悲劇をかんがえると、
やはり開発用と本番運用のサービスは分けておきたいな、と。
今よりサーバ代が高くなるのは経営的にナシですが、最近だと、仮想化を利用して、root権限付きでも安価なサービスが増えて来つつあります。うまく使ったら二台借りても今より安くなるかも。
試してみたのはこの二つ。
linode
Linode.com - Xen VPS Hostingにちゃんねるとかで評判の、自由度の高いVPSサービスです。月額$20なので、一台借りて試してみました。
WEBからの管理画面がすごくて、サーバの再起動はもちろん、(ブラウザ上で)コンソールに接続したりすることもできます。
これはすごい。サーバのリブートを人力でやる必要あるのかなぁ?と思っていたのですが、ここまでできるとは。
でもね...
あきらかに応答速度が遅いのです。WEBはそうでもないのですけど、SSHでつないだ時の応答がもっさり。
ping打ってみたら、国内のサーバの3倍くらいかかっているから、そりゃあ遅いですよね。
絶対ダメかというとダメでもないのですが、この辺が遅いと、あきらかに開発時のモチベーションに響いてくるので、これはいったんパスです。
CPI VPSスケーラブルプラン
KDDI子会社の KDDI Web CommunicationsさんがやっているVPSサービスです。国内の会社でありながら、一年契約すると1890円/月!テストサーバーを用意していただけたので使ってみました。
たぶんこのサービスを調査したほとんどの人が気にしているこのエントリですが。
VPS環境で、メモリ不足でgemが使えない? (Segmentation fault) Kawa.netブログ(川崎有亮)/ウェブリブログ
その後、設定の改善が行われたそうで。
メモリ設定の改善について - VPSスケーラブルプラン 開発者ブログ
実際、ボクがやった範囲では、普通にgemをつかってrailsをインストールして、webrickサーバにアクセスすることができました。
そういうわけで、メモリに関しては、言われているほどギリギリではないかなぁ、という印象。たぶん最近の改善が利いているのでしょう。
そういう改善をしていただけるサービスなら前途有望だし、いっそ乗り換えちゃおうか、と考えたのですが。
- 初期費用9800円!
- DNSサーバを提供していただけないので、自分でbindあげないといけません。メモリ問題が更に加速!
メモリ使い切った時にスワップせずに落ちるというのは、やっぱり大きな問題で。そのことを気にしながらサービスを全部移転させるとなると、相当の(時間的精神的な)コストがかかります。
うう~ん、と悩んだ末に、当分棚上げすることに決めました。
さくらインターネットさんで同様のサービスはじめていただけたら、気持ち的にはずいぶん乗り換えやすくなるのですけど。内部ではきっと検討しているだろうと思うので、楽しみにお待ちしております。
参考資料
- Amazon Web Services
- AWS Management Console(β版)
- Elasticfox Firefox Extension for Amazon EC2
- Amazon S3 Firefox Organizer(S3Fox)
- 流行りのクラウドサービスを操ってみよう!Amazon EC2/S3環境構築のすべて:CodeZine(コードジン)
- はじめてのAmazon EC2&S3 ~これからの新サービスの公開の形~
- flashcast:フリーで働くITエンジニア集団のブログ
- Amazon EC2/S3を使ってみた- まとめ(目次) - RX-7乗りの適当な日々
- [24時間365日] サーバ/インフラを支える技術~スケーラビリティ、ハイパフォーマンス、省力運用(WEB+DB PRESS plusシリーズ)
実際に使おうと思ったら、自動化のためにコマンドラインツールも必要になるとは思うのですが、とりあえず使い始めるのにJava入れなくてもいいのはなかなか便利だなぁ、と思いました。
linuxにはcronという、決まった時間になったら○○をしてね、と登録できるシステムがあって。crontab -e と入力すると、編集画面が起動するようになっています。
あるタスクを追加しようとして、
$ crontab -r
あ、間違えた。
$ crontab -e
no crontab for daisuke - using an empty one
・・・・using an empty one?空っぽのファイルをつかいます???
あーっ!
crontab -eと一文字違いのcrontab -rは、crontabの設定ファイルを消去するコマンドです。
となりのキーにそんな危険なコマンド当てるなよ....確認もなしにファイルを消すなよ...
こういう時のために作業ログが取られているので、そこから古いファイルの内容を拾ってきて復元できたわけですが。
これは心臓に悪いなぁ。
たいていこういうサービスは、メールを受け取ったら、中身がなんであろうと気にせずに決まった内容を返信するように作られていて。だから、「~(メールアドレス)まで空メールを送ってね!」というメールアドレスに「俺は返信してほしくないぜ!」という内容のメールを送っても、たぶん自動的に返信が帰ってきます。
そうじゃなくて、メールの本文を見て、内容が空だった時だけ特別な処理をしようとすると、これは意外と難しいです。
なぜかというと、ユーザーさんに「空メールを送ってね!」といっても、ユーザーさんが空メールを送ってくるとは限らなくて。
ありがちな例
・「入会希望」
・「資料送って」
・「よろしくお願いします」
・ -----
KEIKO ゜★・。・。☆・゜・。 ...
最後のは、携帯電話の設定で自動的にフッタがつくようになっていて、そのままメールを送ってしまったパターン。
こういうのを空メールじゃないといってしまうと、初心者の方に優しくないサービスになってしまうので、どうにかして救済しようと思うと、けっきょく、届いたメールの中身がなんであろうと空メール扱いするしか無くて。
何が言いたいかというと、メールアプリケーションで、空メールの時だけ○○、それ以外の時は○○、という処理の分け方は難しいので、そんな仕様は作らない方がいいです、という話です。
rails上で自分のドメイン名をつかってナンヤカンヤしたい時というのがあって。ENV['HOSTNAME']
これは論外っぽい。[default] ENV
[default] :{"HOSTNAME"=>"xxxx.mogya.com",
仮想ドメインの設定を無視してホスト名を返してくれます。HOST_NAMEという値ですから、当たり前か。
request.env:['SERVER_NAME']
request.env:{"SERVER_NAME"=>"maidmail.jp",
ねらい通り、ドメイン名を返してくれます。ただ、このヘッダも、あとrequest.env['HTTP_HOST']も、ちょっとしたことで簡単に偽装されてしまうので、迂闊につかえません。
request.domain
[default] request.domain:maidmail.jp
こっちを見ると、request.env:['SERVER_NAME']が偽装されてしまうような場面でも、正しいドメイン名がとれました。
ソースを見ると、HTTP_X_FORWARDED_HOSTというヘッダを使うみたいです。
# File vendor/rails/actionpack/lib/action_controller/request.rb
318: def domain(tld_length = 1) 319: return nil unless named_host?(host) 320: 321: host.split('.').last(1 + tld_length).join('.') 322: end 280: def host 281: raw_host_with_port.sub(/:\d+$/, '') 282: end 271: def raw_host_with_port 272: if forwarded = env["HTTP_X_FORWARDED_HOST"] 273: forwarded.split(/,\s?/).last 274: else 275: env['HTTP_HOST'] || env['SERVER_NAME'] || "#{env['SERVER_ADDR']}:#{env['SERVER_PORT']}" 276: end 277: end
HTTP_X_FORWARDED_HOSTがとれなかった場合に限り、env['HTTP_HOST']やenv['SERVER_NAME']を見てくれるので、HTTP_X_FORWARDED_HOST非対応のサーバでも、request.domainを見ておけば悪いようにはしない実装になっているみたいです。
HTTP_X_FORWARDED_HOSTのうまい説明が見つけきれなかったのですが、これってどういう環境変数なのかなぁ?どれくらい信用のおける値なのでしょう?
先日公開したmextractr_webapi.rbが、gem経由でインストールできるようになりました。
こんな具合にして使うことが出来ます。
[daisuke@snares ~]$ sudo gem install mextractr_webapi
Bulk updating Gem source index for: http://gems.rubyforge.org
Successfully installed mextractr_webapi-0.0.1
1 gem installed
[daisuke@snares /var/maidmail]$ script/server
>> require "mextractr_webapi"
>> mextractr = MextractrWebApi.new(API_KEY)
>> res = mextractr.parse("11/29(土) 京都で紅葉を楽しむオフ会を開催します。秋深い京都を撮り歩きましょう。 ")
>> pp res
{"id"=>"20081202_0001",
"where"=>
[{"georss:point"=>nil, "valueString"=>"京都"},
{"georss:point"=>nil, "valueString"=>"京都"}],
"what"=>[{"valueString"=>"オフ会"}],
"when"=>[{"valueString"=>"11/29(土)", "startTime"=>"2008-11-29"}],
"updated"=>"2008-12-02T12:16:50+09:00"
"content"=>
"11/29(土) 京都で紅葉を楽しむオフ会を開催します。秋深い京都を撮り歩きましょう。 ",
"response"=>
"\n\n Mextractr WebAPI results \n 2008-12-02T12:16:50+09:00 \n \n Mextractr \n \n 20081202_0001 \n \n \n 20081202_0001 \n extracted event metadata \n \n Mextractr WebAPI \n \n 2008-12-02T12:16:50+09:00 \n 11/29(土) 京都で紅葉を楽しむオフ会を開催します。秋深い京都を撮り歩きましょう。 \n \n \n \n \n \n \n",
}
enjoy!
メイドめーるでは日本語のメールを送信するために、
ヽ( ・∀・)ノくまくまー(07-31[長年日記])で書いていただいている、Iso2022jpMailerを使っています。
クラスを継承するだけでつかえるとてもいいアイデアだったのですが、たった一つ問題が。
「~」が文字化けするのです。普通のアプリケーションだったら、まあ横棒でいいか、とか言えるし、実際メイドめーるも今日までそうやってごまかしてきたのですけど。萌え萌えなメイドさんがメールをくれるアプリケーションにおいて「~」がつかえないと言うことは、「おはようございます~」がつかえないことになってしまいます。
「おはようございますー」と「おはようございます~」は断じて違うのです!
とまあそんなわけで、技術的に追求した結果、一応「~」が出せるようになりましたのでご報告です。
やり方としては、Iso2022jpMailer の
@mail.body = NKF::nkf('-j', @mail.body)
の部分を
@mail.body = NKF::nkf('-Wxm0 --oc=ISO-2022-JP-1', @mail.body)
に置き換えます。ついでに、タイトルとかに「~」がはいることもあるだろうから、
text = NKF.nkf('-j -m0', text)
も、
text = NKF.nkf('-Wxm0 --oc=ISO-2022-JP-1', text)
にしちゃいました。
技術的な話
正直に言うと、なんでこれで化けないのか、最終的な理由は理解できていません。
ただ、あれこれやっているうちに、化ける時と化けない時があって、比較するとこうなっていることが分りました。
上がうまくいく場合で、下が駄目な場合です。日本語メールなのでJISコードでエンコードしてあります。
OKな時は1B 24 42で始まっていて、駄目な時は1B 24 48で始まる...、つまり、JIS X 0208-1983でエンコードしてあればOKで、JIS X 0212-1990だと駄目なことが分ります。
NKFのコマンド詳細を見ながら、irbでいろいろやってみると。
>> NKF::nkf('-jWxm0', "~").each_byte{|b| print b.to_s(16)+","};print "\n"
1b,24,28,44,22,37,1b,28,42,
=> nil
>>NKF::nkf('-Wxm0 --oc=ISO-2022-JP', "~").each_byte{|b| print b.to_s(16)+","};print "\n"
1b,24,28,44,22,37,1b,28,42,
=> nil
>> NKF::nkf('-Wxm0 --oc=ISO-2022-JP-1', "~").each_byte{|b| print b.to_s(16)+","};print "\n"
1b,24,42,21,41,1b,28,42,
=> nil
>> NKF::nkf('-Wxm0 --oc=ISO-2022-JP-3', "~").each_byte{|b| print b.to_s(16)+","};print "\n"
1b,24,28,50,28,37,1b,28,42,
=> nil
--oc=ISO-2022-JP-1の時だけ、ねらい通りの変換をしてくれるようです。ということで、Iso2022jpMailerにも、同じ引数を渡してあげると、「~」が出るようになった次第。「ISO-2022-JP-1」って、JIS X 0212に対応させるための引数で。むしろ逆のような気がするし、なんでISO-2022-JP-3で駄目なのかも謎です。
こういうエラーが出るようになった。mysql> FLUSH PRIVILEGES; ERROR 1146 (42S02): Table 'mysql.procs_priv' doesn't exist
たぶんmysqlを4→5にアップグレードしちゃったことが原因。yum一発アップグレードは怖いなぁ。
ともあれ、Table 'mysql.procs_priv' doesn't existでググったら、
MySQL Bugs: #9934: DROP USER fails if mysql.procs_priv doesn't exists というのが出てきて、冷たいことを言われた末に、
If you encounter this after an update, run mysql_upgrade_shell command: it will create the missing table.ということになっている。
(アップグレード後にこのエラーが出たんだったら、mysql_upgrade_shellコマンドを走らせろ。それで欠けてるテーブルが作成されるから)
(当然バックアップをとってから)やってみた。
REPAIR TABLEする必要があるらしい。[furukawa@www ~]$ sudo mysql_upgrade_shell --verbose --datadir=/var/lib/mysql --user=root --password=**** Running /usr/bin/mysqlcheck --password=**** --check-upgrade --all-databases --auto-repair --user=root expressionengine.exp_actions error : Table upgrade required. Please do "REPAIR TABLE `exp_actions`" to fix it! expressionengine.exp_captcha error : Table upgrade required. Please do "REPAIR TABLE `exp_captcha`" to fix it! expressionengine.exp_categories error : Table upgrade required. Please do "REPAIR TABLE `exp_categories`" to fix it! expressionengine.exp_category_field_data :(略) mysql.time_zone_transition_type OK mysql.user OK This script updates all the mysql privilege tables to be usable by the current version of MySQL done
以下、この調子でテーブルを片っ端からREPAIRしていく。[furukawa@www ~]$ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 82 Server version: 5.0.68 Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use expressionengine; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> REPAIR TABLE `exp_actions`; +---------------------------------+--------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------------------------------+--------+----------+----------+ | expressionengine.exp_actions | repair | status | OK | +---------------------------------+--------+----------+----------+ 1 row in set (0.00 sec) :(略)
columns_priv以降のテーブルはmysqlデータベースに入っている。
mysql> use mysql Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> REPAIR TABLE `columns_priv`; +--------------------+--------+----------+----------+ | Table | Op | Msg_type | Msg_text | +--------------------+--------+----------+----------+ | mysql.columns_priv | repair | status | OK | +--------------------+--------+----------+----------+ 1 row in set (0.00 sec) :(略) mysql> exit Bye
これでいいらしい。あんまり自信がないのだけれど、エラーメッセージでググった時に日本語の情報が出てこなかったので、とりあえずブログにあげておきます。[furukawa@www ~]$ sudo mysql_upgrade_shell --verbose --datadir=/var/lib/mysql --user=root --password=**** mysql_upgrade already done for this version This script updates all the mysql privilege tables to be usable by the current version of MySQL done [furukawa@www ~]$ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 84 Server version: 5.0.68 Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec)