<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>さくらたんどっとびーず &#187; MySQL</title>
	<atom:link href="http://sakuratan.biz/archives/tag/mysql/feed" rel="self" type="application/rss+xml" />
	<link>http://sakuratan.biz</link>
	<description>モロモロ工事中です</description>
	<lastBuildDate>Sun, 25 Jun 2023 12:51:51 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>mysqlのibdataが原因でディスクフルになったときに復旧方法</title>
		<link>http://sakuratan.biz/archives/4536</link>
		<comments>http://sakuratan.biz/archives/4536#comments</comments>
		<pubDate>Sat, 27 Aug 2011 08:32:11 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[開発環境]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=4536</guid>
		<description><![CDATA[さっきまで落ちてたsakuratan.bizです。どーもすみません。 原因は MySQL の InnoDB が使用する ibdata ファイルがディスクを食いつぶしてディスクフルになってたためでした。 ibdata はテーブルスペースを保存するファイルで、CentOS ですとデフォルトで /var/lib/mysql/ibdata1 に作成されます。MySQL のデフォルトでは ibdata が自... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/4536">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>さっきまで落ちてたsakuratan.bizです。どーもすみません。</p>
<p>原因は MySQL の InnoDB が使用する ibdata ファイルがディスクを食いつぶしてディスクフルになってたためでした。</p>
<p>ibdata はテーブルスペースを保存するファイルで、CentOS ですとデフォルトで /var/lib/mysql/ibdata1 に作成されます。MySQL のデフォルトでは ibdata が自動で拡張されていく設定になっていますので、放っておくとどんどんファイルサイズがでかくなって、さくらの VPS とかですと結構あっさりディスクフルになりました。</p>
<p>とりあえず復旧できたんで手順とか残しときます。同じようにトラブった方は参考程度にどうぞ。</p>
<p style="margin-top:3em">まず ibdata1 がディスクを食いつぶしているので、復旧するにはこれを消すとかファイルを小さく必要があります。</p>
<p> ファイルサイズを小さくする方法は調べたらいっぱいでてきますので（<a href="http://dev.mysql.com/doc/refman/5.1/ja/adding-and-removing.html">13.5.7 InnoDB データとログ ファイルの追加と削除</a> とか <a href="http://bitwalker.dtiblog.com/blog-entry-162.html">ibdata1 のサイズを減らす手順</a> とか <a href="http://d.hatena.ne.jp/masayuki14/20100308/1268039336">ibdata1のサイズを減らす方法</a>とか）、概要だけ引用しますと、</p>
<blockquote>
<ol>
<li>全ての InnoDB テーブルをダンプする為に mysqldump を利用してください。</li>
<li>サーバを停止してください。</li>
<li>全ての存在するテーブルスペース ファイルを削除してください。</li>
<li>新しいテーブルスペースを設定してください。</li>
<li>サーバを再起動してください。</li>
<li>ダンプ ファイルをインポートしてください。</li>
</ol>
<p><cite><a href="http://dev.mysql.com/doc/refman/5.1/ja/adding-and-removing.html">MySQL :: MySQL 5.1 リファレンスマニュアル :: 13.5.7 InnoDB データとログ ファイルの追加と削除</a></cite>
</ol>
</blockquote>
<p>という感じだったりします。要はバックアップ取ってテーブルスペースを作り直せということのようです。</p>
<p>ただまあディスクフルしてるんでサーバ上に mysqldump のダンプファイルなんか置けないので、ssh 経由で mysqldump を実行することにしました。↓のように ssh を起動することで、ネットワーク越しにコマンドを実行して mysqldump の出力をローカルに直接保存できます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">ssh</span> <span style="color: #c20cb9; font-weight: bold;">who</span><span style="color: #000000; font-weight: bold;">@</span>domain \<br />
mysqldump <span style="color: #660033;">-v</span> <span style="color: #660033;">-u</span> DBUSER \<br />
<span style="color: #660033;">--default-character-set</span>=binary <span style="color: #660033;">-p</span> DBNAME \<br />
TABLE1 TABLE2 ... &nbsp;<span style="color: #000000; font-weight: bold;">|</span> \<br />
<span style="color: #c20cb9; font-weight: bold;">gzip</span> <span style="color: #000000; font-weight: bold;">&gt;</span> mysql.dump</div></div>
<p>それとコマンドを実行する前にサーバ上のサービスをできるだけ止めてある程度作業用のメモリの確保して、ついでに不要なファイルをできるだけ削除しておいた方が良いと思います。メモリかスワップか何が原因か調べてる暇も無かったので詳細は不明ですが、リソースが足らないと mysqldump がテーブル構造を読み込む際にエラーを出します。</p>
<p>今回はリストアする必要が無いテーブルが何個かありましたのでダンプする対象をテーブル単位で指定していますが、全部リストアする場合はデータベース単位で指定してもらえばよろしいかと思います。運用形態によっては mysqldump に &#8211;single-transaction オプションを指定してもらった方が良いかもしれません（とりあえずウチんとこでは不要だったので指定してませんが）。</p>
<p style="margin-top:2em">ダンプできたら mysql を止めてから ibdata1 と ib_logfile0 と ib_logfile1 を消します。他のサイトだとリネームした方が良いとか書いてますがそんな余裕無いのでいきなりマジ削除しました。最悪データ全部豚でもいーや、の覚悟でどうぞw</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>mysql<br />
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-f</span> ibdata1 ib_logfile<span style="color: #7a0874; font-weight: bold;">&#91;</span>01<span style="color: #7a0874; font-weight: bold;">&#93;</span></div></div>
<p>/etc/my.cnf に ibdata1 のサイズ制限と innodb_file_per_table を加えてからmysqld を再起動して回復しましたよ、という感じです。</p>
<div class="codecolorer-container sql dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">innodb_data_file_path<span style="color: #66cc66;">=</span>ibdata1:10M:autoextend:<span style="color: #993333; font-weight: bold;">MAX</span>:100M<br />
innodb_file_per_table</div></div>
<p>innodb_file_per_table を指定すると、各テーブルの中身は共有テーブルスペースでは無く個別のファイルに保存されるようになるのですが、こっちのファイルも放置しておくと大きくなっていきますので、定期的に ALTER TABLE を実行してデフラグする必要があります。（詳しくは <a href="http://dev.mysql.com/doc/refman/5.1/ja/innodb-file-defragmenting.html">13.5.14.3 テーブルのデフラグメント化</a> とか <a href="http://cl.pocari.org/2006-07-07-2.html">拡張され続ける InnoDB のデータファイルのサイズを小さくする方法</a> とかをご覧ください。）</p>
<div class="codecolorer-container sql dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> table1 ENGINE<span style="color: #66cc66;">=</span>InnoDB;</div></div>
<p style="margin-top:3em">個別に ALTER TABLE 実行するのも面倒なので、全ての InnoDB テーブルに対して ALTER TABLE を実行するスクリプトも書いてみました。よろしければどうぞ。</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">import</span> MySQLdb<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; conn <span style="color: #66cc66;">=</span> MySQLdb.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">user</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'root'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; cur <span style="color: #66cc66;">=</span> conn.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; cur.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'SHOW DATABASES'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; databases <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>database <span style="color: #ff7700;font-weight:bold;">for</span> database<span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> cur <span style="color: #ff7700;font-weight:bold;">if</span> database <span style="color: #66cc66;">!=</span> <span style="color: #483d8b;">'mysql'</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; cur.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; conn.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> database <span style="color: #ff7700;font-weight:bold;">in</span> databases:<br />
&nbsp; &nbsp; &nbsp; &nbsp; conn <span style="color: #66cc66;">=</span> MySQLdb.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">user</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'root'</span><span style="color: #66cc66;">,</span> db<span style="color: #66cc66;">=</span>database<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cur1 <span style="color: #66cc66;">=</span> conn.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cur1.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'SHOW TABLE STATUS'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> t <span style="color: #ff7700;font-weight:bold;">in</span> cur1:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tablename <span style="color: #66cc66;">=</span> t<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; engine <span style="color: #66cc66;">=</span> t<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> engine <span style="color: #ff7700;font-weight:bold;">and</span> engine.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'innodb'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Defrag %s.%s'</span> % <span style="color: black;">&#40;</span>database<span style="color: #66cc66;">,</span> tablename<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cur2 <span style="color: #66cc66;">=</span> conn.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cur2.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ALTER TABLE %s ENGINE=INNODB'</span> % tablename<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cur2.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; cur1.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; conn.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:<br />
&nbsp; &nbsp; main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
<p>MySQL にパスワード無しで root ログインできる前提でスクリプト書いてますので、その辺の設定変えている方は適当に改造して使ってください。</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/4536/feed</wfw:commentRss>
		<slash:comments>204</slash:comments>
		</item>
		<item>
		<title>node.jsとMySQLで割と普通のデータベースウェブアプリを作ってみるチュートリアル</title>
		<link>http://sakuratan.biz/archives/3101</link>
		<comments>http://sakuratan.biz/archives/3101#comments</comments>
		<pubDate>Sun, 16 Jan 2011 15:52:14 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ejs]]></category>
		<category><![CDATA[express]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[node.js]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=3101</guid>
		<description><![CDATA[2011年はサーバサイド JavaScript の年！ サーバサイド JavaScript の本命は node.js！ ということで割と普通のウェブアプリケーションを node.js で作るためのチュートリアルを書いてみました。WebSocket とか新しめの話題は結構見ますが、PHP とかで普通のウェブアプリ作ってる人向けのチュートリアルとかあんま見ないような気がしたので、って感じです。 チュー... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/3101">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>2011年はサーバサイド JavaScript の年！<br />
サーバサイド JavaScript の本命は node.js！</p>
<p><a href="http://nodejs.org/"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/logo.png" alt="node.js" title="node.js" width="420" height="111" class="aligncenter size-full wp-image-3315" style="background-color:#22252A"/></a></p>
<p>ということで割と普通のウェブアプリケーションを node.js で作るためのチュートリアルを書いてみました。WebSocket とか新しめの話題は結構見ますが、PHP とかで普通のウェブアプリ作ってる人向けのチュートリアルとかあんま見ないような気がしたので、って感じです。</p>
<p>チュートリアルの内容ですが、コード量が少なめで機能的にも分かりやすそうなモノということで、短縮 URL ウェブアプリケーションを作ってみることにしました。bit.ly とか t.co とか nico.ms みたいなアレです。短縮 URL のデータは MySQL に保存します。</p>
<p>結構長文になっちゃったので、先に目次置いときます。</p>
<ol>
<li>node.js のインストール</li>
<li>npm (Node Package Manager) のインストール</li>
<li>express フレームワークの簡単な使い方</li>
<li>ejs テンプレートエンジンを express フレームワークで使う方法</li>
<li>node.js 用 MySQL モジュールの使用例</li>
<li>自作モジュールの作成例</li>
</ol>
<p>チュートリアルを一通り試せば簡単なウェブアプリなら作れるようになるかもしんないので、お暇な方はどうぞ。</p>
<p>あとチュートリアルで作ったソースを固めた ZIP も置いときますので、ソース見た方がはえーって人は ZIP からどうぞ。</p>
<blockquote><p>
<a href='http://sakuratan.biz/blog/wp-content/uploads/2011/01/nodejs-urlshortener.zip'>nodejs-urlshortener.zip</a>
</p></blockquote>
<p>（2011/1/18 21:20）ちろっと正規表現が変だったようで一ヶ所直して ZIP をうpり直しました。<br />
×　/^\/([0-9A-Z]{5,}$)$/<br />
○　/^\/([0-9A-Z]{5,})$/<br />
修正前の正規表現でもちゃんと動いてるので機能的にバグってる訳ではないようですが、Typo ですし $)$ は変な感じです(*´・ω・)(・ω・｀*)ﾈｰ</p>
<h3>node.js のインストール</h3>
<p>とりあえず node.js が無ければ話が始まらないのでとっととインスコしていきます。</p>
<p>node.js のアーカイブは<a href="http://nodejs.org/">公式サイト</a>の<a href="http://nodejs.org/#download">ダウンロード</a>から配布されています。2011年1月10日時点では安定版としてバージョン 0.2.6、開発版としてバージョン 0.3.4 のアーカイブが配布されています。</p>
<p>今んところ開発中の機能が使いたい訳でも無いので安定版をインストールすることにしました。開発版を使う場合はアーカイブのソースを使うよりも、github の <a href="https://github.com/ry/node">node.js のリポジトリ</a>からソースを持ってきた方が良いと思います。</p>
<p>node.js が動く環境ですが<a href="http://nodejs.org/">公式サイト</a>によると Linux、Macintosh、Solaris でテストされているということです。また Windows/Cygwin、FreeBSD、OpenBSD でもだいたい動くとのことです。</p>
<p>さくらの VPS の CentOS と MacBook にインスコしてみたのですが、どちらもインストール作業自体はあっさり簡単に終わりました。インストールする前に必要になるライブラリとかが若干違いますので OS 別にインストール方法を説明します。</p>
<h4>CentOS の場合</h4>
<p>CentOS の場合、node.js をインストールする前に OpenSSL と Python が必要になります。Python を yum 以外の方法でインストールする場合はバージョン 2.4 以降をインストールしてください。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">yum install</span> openssl-devel<br />
$ <span style="color: #c20cb9; font-weight: bold;">yum install</span> python</div></div>
<p>OpenSSL と Python がインストールできたら <a href="http://nodejs.org/#build">ビルド方法の説明</a> に従って node.js をインストールします。make install は root で実行してください。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">tar</span> xvzf node-v0.2.6.tar.gz<br />
$ <span style="color: #7a0874; font-weight: bold;">cd</span> node-v0.2.6<br />
$ .<span style="color: #000000; font-weight: bold;">/</span>configure<br />
$ <span style="color: #c20cb9; font-weight: bold;">make</span><br />
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></div></div>
<p>ビルド／インストールはすぐ終わると思います。</p>
<p>インストールが完了すると /usr/local/bin/node に node.js のバイナリがインストールされます。インストール先を変更したい場合は configure 実行時に &#8211;prefix=DIR オプションを指定してください。その他のビルド／インストールオプションについては、configure &#8211;help で参照してください。</p>
<h4>Mac OS X の場合</h4>
<p>Mac OS X の場合、コンパイルするのに GNU C コンパイラ (GCC) が必要になります。GCC は Xcode からインストールするのが良いと思います。Xcode のインストール方法は <a href="http://osksn2.hep.sci.osaka-u.ac.jp/~taku/osx/install_xcode.html">このページ</a>等を参考にしてください。（ポックンの MacBook、iPhone の SDK 入れたときに Xcode 入れちゃったので、インストール手順覚えとらんので説明できんとです。サーセン）</p>
<p>Mac OS X には Python は元からインストールされていますので Xcode 以外のインストールは不要です。</p>
<p>node.js のビルド／インストールは、CentOS の場合と同じように configure / make で行います。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">tar</span> xvzf node-v0.2.6.tar.gz<br />
$ <span style="color: #7a0874; font-weight: bold;">cd</span> node-v0.2.6<br />
$ .<span style="color: #000000; font-weight: bold;">/</span>configure<br />
$ <span style="color: #c20cb9; font-weight: bold;">make</span><br />
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></div></div>
<p>node.js には Mac OS X 用パッケージを作るためのスクリプトが tools/osx-dist.sh に用意されているのですが、後述する npm と設定が一致していないため使わない方が良いと思います。</p>
<h3>npm (Node Package Manager) のインストール</h3>
<p>npm (Node Package Manager) は node.js の CPAN みたいなもので外部モジュールのインストールに使います。</p>
<p>npm のインストール用スクリプトが http://npmjs.org/install.sh にありますので、ダウンロードして実行します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>curl http:<span style="color: #000000; font-weight: bold;">//</span>npmjs.org<span style="color: #000000; font-weight: bold;">/</span>install.sh <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sh</span></div></div>
<p>ただまあこれ、そのまま一般ユーザーで動かすとディレクトリにパーミッションが無いエラーで異常終了します。</p>
<p>node.js と同じ /usr/local 以下にファイルを置こうとしてるので当然と言えば当然ですが、<a href="https://github.com/isaacs/npm/issues/issue/294">npm 自体がこの辺の仕様を固めきっていないみたい</a>ですのでアレコレ…</p>
<p>どこから説明したら良いものか悩みますが、<a href="https://github.com/isaacs/npm/blob/master/doc/developers.md#readme">npm のリポジトリには誰でもパッケージをアップロードできる</a>ので、root で npm をインストールする環境だとセキュリティホールになるようなパッケージもアップロードできたりしちゃうのですが、npm の作者さん的には誰でもパッケージメンテナになれる状態を保っておきたいので、npm 自体や npm パッケージを root 権限でインストールしない方がいいよ、ということらしいです。自分で書いてて変な日本語ww</p>
<p><a href="https://github.com/isaacs/npm">isaacs / npm</a> に root 権限なしでインストールする方法が何個か説明されてますが、ポックン的にはリスクは把握しましたし、Your own risk とか *NIX だと割と当たり前なんで sudo でインスコすることにしました。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>curl http:<span style="color: #000000; font-weight: bold;">//</span>npmjs.org<span style="color: #000000; font-weight: bold;">/</span>install.sh <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">sh</span></div></div>
<p>心配な人は <a href="https://github.com/isaacs/npm">isaacs / npm</a> に従って root 権限なしでインスコするか、<a href="https://gist.github.com/579814">https://gist.github.com/579814</a> の説明に従って ~/local とかに npm をインスコするのが良いと思います。</p>
<p>なお npm を sudo でインスコした場合、npm でパッケージをインスコする際も root で実行する必要があります。root でパッケージをインスコすると npm がワーニングを出しますがとりあえず無視です。</p>
<p>あとこの辺は、もうじき仕組みが変わる予定だそうです。変わった後でこのブログ見た人は上の説明を無視してください。</p>
<blockquote><p>
It is on the roadmap to make npm do a bunch of chown/setuid stuff when sudoed, so eventually it&#8217;ll actually be safer to run as root than as a user account, but that&#8217;s a refactor that is slowly progressing.<br />
<cite><a href="https://github.com/isaacs/npm">https://github.com/isaacs/npm</a></cite>
</p></blockquote>
<h4>モジュールのインストール</h4>
<p>npm がインスコできたらモジュールをインスコしていきます。</p>
<p>今回のチュートリアルでは、<a href="https://github.com/felixge/node-mysql">node-mysql</a> (MySQL)、<a href="http://expressjs.com/">express</a> (express フレームワーク)、<a href="https://github.com/visionmedia/ejs">ejs</a> (テンプレートエンジン) を使います。</p>
<p>モジュールのインストールは npm install コマンドで行います。npm を sudo でインスコした場合は、npm install は root で実行してください。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ npm <span style="color: #c20cb9; font-weight: bold;">install</span> mysql<br />
$ npm <span style="color: #c20cb9; font-weight: bold;">install</span> express<br />
$ npm <span style="color: #c20cb9; font-weight: bold;">install</span> ejs</div></div>
<p>あと mysql モジュールをインストールする前に MySQL 本体をインスコしておいてください。本筋と関係無いので MySQL のインスコ方法は省略します。</p>
<h3>node.js を試してみる</h3>
<p>インストールが終わったら早速 node.js を動かしてみます。</p>
<p>最初は <a href="http://nodejs.org/">node.js 公式サイト</a>のサンプルコードを動かしてみます。このサンプルはウェブサーバを起動し、HTTP 経由のアクセスに対して Hello World を返します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// モジュールの読み込み</span><br />
<span style="color: #003366; font-weight: bold;">var</span> http <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'http'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// サーバを起動する</span><br />
http.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">writeHead</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">200</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">'Content-Type'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'text/plain'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Hello World<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8124</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;127.0.0.1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Server running at http://127.0.0.1:8124/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>↑のソースをコピペして適当なディレクトリに example.js として保存します。ターミナルから node コマンドを実行して node.js を起動します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ node example.js<br />
Server running at http:<span style="color: #000000; font-weight: bold;">//</span>127.0.0.1:<span style="color: #000000;">8124</span></div></div>
<p>Server running &#8230; メッセージが出力されていれば起動に成功しています。ブラウザや wget / curl 等で http://127.0.0.1:8124 にアクセスすると HTTP レスポンスが返されます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ curl http:<span style="color: #000000; font-weight: bold;">//</span>127.0.0.1:<span style="color: #000000;">8124</span><br />
Hello World</div></div>
<h3>ファイルを読み込んで表示</h3>
<p>上の Node.js のサンプルではプログラムから直接コンテンツを出力していましたが、メンテとかめんどそうなのでファイルからコンテンツを読み込んで出力するように改造します。</p>
<p>ファイル入出力には fs モジュールを使います。fs モジュールは Node.js 本体に含まれています。</p>
<p>fs.readFile 関数を使い index.html を読み込み出力するように改造した example.js です。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// fsモジュールも読み込む</span><br />
<span style="color: #003366; font-weight: bold;">var</span> http <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'http'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; fs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
http.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// index.html を読み込んで表示</span><br />
&nbsp; &nbsp; fs.<span style="color: #660066;">readFile</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.html'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> content<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">writeHead</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">200</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">'Content-Type'</span><span style="color: #339933;">:</span><span style="color: #3366CC;">'text/html; charset=utf-8'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span>content<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8192</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'127.0.0.1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>index.html の中身はこんな感じで、JavaScript と同じディレクトリに置きます。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;!doctype HTML&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;UTF-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>URL shortener by Node.js<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>URL shortener by Node.js<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;POST&quot;</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; Enter URL: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;url&quot;</span> <span style="color: #000066;">size</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;50&quot;</span> <span style="color: #000066;">maxlength</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;256&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Submit&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>両方できたら先ほどと同じようにサーバを起動します。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>node example.js</div></div>
<h4>非同期 I/O</h4>
<p>node.js でプログラムを書く場合、入出力は基本的に非同期 I/O を使います。上の例では fs.readFile を使用していますが、readFile はファイルの読み込みを完了するとエラーとファイルの中身を引数にコールバック関数を呼び出します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">fs.<span style="color: #660066;">readFile</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.html'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> content<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// 読み込み完了時に呼び出される</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>コールバック関数の引数には、読み込み成功時は null と読み込んだコンテンツが、失敗時はそのまま例外送出可能なエラーオブジェクトが渡されます。</p>
<p>非同期 I/O とは I/O 関数呼び出し時にブロッキングしないことを意味します。上と似たようなコードを PHP で書くと以下のようになりますが、file_get_contents はコンテンツの読み込みが完了するまでプロセスの実行をブロッキングします。</p>
<div class="codecolorer-container php dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'index.html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Apache などのマルチプロセス（マルチスレッド）サーバでは、複数のプロセスでリクエスト応答を行います。サーバプロセス上で実行されるスクリプトでブロッキングが発生すると、そのプロセスの実行は単純に中断されます。中断中は他のサーバプロセスが他のリクエストの応答を行います。</p>
<p>一方 node.js はシングルプロセスウェブサーバですので、I/O 要求等によるブロッキングが発生するとサーバ全体の動作が中断してしまいます。もちろんそれではサーバとして用を成さないので、非同期 I/O を使って I/O 要求を発生時に別の実行可能な処理へサーバの処理を切り替えます。</p>
<p>Apache 上で普通の（同期 I/O を使った）スクリプトを書く方が簡単そうですが（実際に簡単ですけど）、node.js が注目された背景には <a href="http://www.hyuki.com/yukiwiki/wiki.cgi?TheC10kProblem">C10k 問題</a> があり、10000 (10k) を超えるクライアント接続に従来の（マルチプロセス／マルチスレッド型）ウェブサーバでは耐えられなくなってきたので、単一プロセス非同期 I/O ウェブサーバが必要とされている現状があります。</p>
<p>node.js というとサーバサイド JavaScript により学習コストの低下を期待する向きもあると思いますが、（非同期 I/O を使ってる関係で）ちょっとしたコーディングミスがサーバ全体の性能に影響を与える場合もありますのでプログラミングには注意が必要です。</p>
<h3>express フレームワークを使う</h3>
<p>小難しい話はこの辺にして、node.js 本体に含まれるモジュールだけでコーディングしているとソースが長ったらしくなるので、<a href="http://expressjs.com/">express フレームワーク</a>を使うようにソースを書き換えます。</p>
<p>先ほどまで全然説明していませんでしたが、モジュールの読み込みには require 関数を使います。require はモジュールオブジェクトを返します。モジュールオブジェクトは変数に代入して使用するのが一般的です。</p>
<p>express フレームワークでは、express.createServer でサーバオブジェクトを作成し、サーバオブジェクトの get メソッド等で URL マッパを設定します。以下の例ではサーバルート (/) へのリクエストに対し、sendfile でファイルの中身をレスポンスします。（上の例と同じ処理です。）</p>
<p>以下が修正したソースです。ついでにファイル名も変えます。server.js として保存してください。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// モジュールの読み込み</span><br />
<span style="color: #003366; font-weight: bold;">var</span> express <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'express'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// サーバを作成</span><br />
<span style="color: #003366; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> express.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// '/' のリクエストハンドラ</span><br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">sendfile</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.html'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// サーバを起動</span><br />
app.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8124</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'127.0.0.1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<h3>POST パラメータの処理と ejs テンプレート</h3>
<p>index.html からは HTTP POST でフォームデータを送信しますので、そのリクエストハンドラを記述していきます。</p>
<p>express で POST メソッドのリクエストハンドラを記述する場合、サーバオブジェクトの post メソッドで URL マッパを設定します。</p>
<p>HTTP 経由で受け取ったパラメータは、POST の場合は req.body にオブジェクトとして渡されます。あらかじめ app.use(express.bodyDecoder()) を呼び出しておかないと POST パラメータは処理してくれないので注意してください。</p>
<p>あとこのチュートリアルでは使ってませんが、URL の QueryString （PHP の $_GET） は req.query に渡されます。</p>
<p>また HTML コンテンツにデータを埋め込むため、<a href="https://github.com/visionmedia/ejs">ejs テンプレートエンジン</a>を使用するように変更します。ejs の 他に <a href="http://jade-lang.com/">Jade</a>、<a href="http://github.com/visionmedia/haml.js">Haml</a>、<a href="https://github.com/mauricemach/coffeekup">CoffeeKup</a>、<a href="https://github.com/kof/node-jqtpl">jQuery Templates</a> などのテンプレートエンジンも express と連動可能です。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// ejs モジュールも読み込む</span><br />
<span style="color: #003366; font-weight: bold;">var</span> express <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'express'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; ejs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> express.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// bodyDecoder を指定しないと express が POST パラメータを処理してくれない</span><br />
app.<span style="color: #003366; font-weight: bold;">use</span><span style="color: #009900;">&#40;</span>express.<span style="color: #660066;">bodyDecoder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// app.render('*.ejs') は ejs テンプレートエンジンで処理させる</span><br />
app.<span style="color: #660066;">register</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.ejs'</span><span style="color: #339933;">,</span> ejs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ejs テンプレートエンジンでレンダリング</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// req.body に POST パラメータがセットされるので</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// そのままテンプレートに渡す</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result.ejs'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> message<span style="color: #339933;">:</span> req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span> <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8124</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'127.0.0.1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>テンプレートファイルは views サブディレクトリに配置します。views サブディレクトリにはページレイアウトを定義する layout.ejs が必要です。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;!doctype HTML&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;UTF-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>URL shortener by Node.js<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>URL shortener by Node.js<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;%- body %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></div>
<p>views/index.ejs には先ほどの index.html の form 部分を記述します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;POST&quot;</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/&quot;</span>&gt;</span><br />
&nbsp; Enter URL: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;url&quot;</span> <span style="color: #000066;">size</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;50&quot;</span> <span style="color: #000066;">maxlength</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;256&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Submit&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></div></div>
<p>views/result.ejs には message 置換変数を配置します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;&lt;%<span style="color: #66cc66;">=</span> message %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span></div></div>
<p>ejs では &lt;%= varname %> が html エスケープ付きのテンプレート変数出力、&lt;%- varname %> がエスケープなしの変数出力です。&lt;% code %> で JavaScript コードを直接記述することもできます。詳しくは <a href="https://github.com/visionmedia/ejs">https://github.com/visionmedia/ejs</a> をご覧ください。</p>
<h3>MySQL との連動</h3>
<p>今回のウェブアプリではテーブル短縮 URL 変換用テーブルをデータベースに保持します。テーブル定義はこんな感じです。</p>
<p>mysql コマンド等で予めデータベースに作成します。</p>
<div class="codecolorer-container sql dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> shorten_urls<br />
<span style="color: #66cc66;">&#40;</span>id &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">BIGINT</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span><br />
&nbsp;long_url &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">256</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">COLLATE</span> utf8_bin<span style="color: #66cc66;">&#41;</span>;</div></div>
<p>node.js から MySQL データベースへ問い合わせを行うには、mysql モジュールの Client ライブラリを使用します。データベース問い合わせも I/O ですので非同期です。</p>
<p>以下が最終的に完成した短縮 URL ウェブアプリケーションプログラムです。base62 モジュールについては後述します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// サーバのアドレスとポート</span><br />
<span style="color: #003366; font-weight: bold;">var</span> HOSTNAME <span style="color: #339933;">=</span> <span style="color: #3366CC;">'localhost'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> PORT <span style="color: #339933;">=</span> <span style="color: #CC0000;">8124</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// MySQL データベース名、ユーザー名、パスワード</span><br />
<span style="color: #003366; font-weight: bold;">var</span> DBNAME <span style="color: #339933;">=</span> <span style="color: #3366CC;">'nodejs_url_shortener'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> DBUSER <span style="color: #339933;">=</span> <span style="color: #3366CC;">'root'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> DBPASSWD <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> sys <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sys'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; express <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'express'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; ejs <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; Client <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mysql'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Client</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; base62 <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'./base62'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// MySQLデータベースに接続しcallbackを呼び出す</span><br />
<span style="color: #003366; font-weight: bold;">function</span> mysql<span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> client <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Client<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">database</span> <span style="color: #339933;">=</span> DBNAME<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">user</span> <span style="color: #339933;">=</span> DBUSER<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">password</span> <span style="color: #339933;">=</span> DBPASSWD<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; client.<span style="color: #660066;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>client<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> express.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
app.<span style="color: #003366; font-weight: bold;">use</span><span style="color: #009900;">&#40;</span>express.<span style="color: #660066;">bodyDecoder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
app.<span style="color: #660066;">register</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.ejs'</span><span style="color: #339933;">,</span> ejs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// ルート GET</span><br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'index.ejs'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// ルート POST</span><br />
app.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// テンプレート変数</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> locals <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; error<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; short_url<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">null</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// パラメータをチェック</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">error</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'Missing url parameter'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp;<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">256</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">error</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'url parameter too long'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>locals.<span style="color: #660066;">error</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result.ejs'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locals<span style="color: #339933;">:</span> locals<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// idを短縮URLに変換して出力</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span> render_short_url<span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">short_url</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'http://'</span> <span style="color: #339933;">+</span> HOSTNAME<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>PORT <span style="color: #339933;">!=</span> <span style="color: #CC0000;">80</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">short_url</span> <span style="color: #339933;">+=</span> <span style="color: #3366CC;">':'</span> <span style="color: #339933;">+</span> PORT<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; locals.<span style="color: #660066;">short_url</span> <span style="color: #339933;">+=</span> <span style="color: #3366CC;">'/'</span> <span style="color: #339933;">+</span> base62.<span style="color: #660066;">int_to_base62_string</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'result.ejs'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; locals<span style="color: #339933;">:</span> locals<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// データベースに短縮URLを登録して表示</span><br />
&nbsp; &nbsp; mysql<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>client<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'INSERT INTO shorten_urls (long_url) VALUES (?)'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#91;</span>req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// キー重複は無視</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err <span style="color: #339933;">&amp;&amp;</span> err.<span style="color: #660066;">number</span> <span style="color: #339933;">!=</span> Client.<span style="color: #660066;">ERROR_DUP_ENTRY</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// インサート成功</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; render_short_url<span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">insertId</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// インサート失敗時はlong_urlをキーで検索する</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'SELECT id FROM shorten_urls WHERE long_url = ?'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#91;</span>req.<span style="color: #660066;">body</span>.<span style="color: #660066;">url</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> <span style="color: #003366; font-weight: bold;">new</span> Error<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Something wrong'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; render_short_url<span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">id</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// 短縮URLをリダイレクト</span><br />
app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/^\/([0-9A-Z]{5,})$/</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; mysql<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>client<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// idからurlを検索してリダイレクト</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'SELECT long_url FROM shorten_urls WHERE id = ?'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#91;</span>base62.<span style="color: #660066;">base62_string_to_int</span><span style="color: #009900;">&#40;</span>req.<span style="color: #660066;">params</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">length</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// データが無い</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Not Found'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">404</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">redirect</span><span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">long_url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
app.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span>PORT<span style="color: #339933;">,</span> HOSTNAME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>短縮 URL を展開する際、URL に埋め込まれた ID を正規表現でパースして req.params 経由で受け取ります。この辺は express の機能を使ってますので、詳しくは express のマニュアルの <a href="http://expressjs.com/guide.html#Routing">Routing</a> の項をご覧ください。</p>
<p>コードの修正が終わったら、result.ejs はエラーメッセージも埋め込めるように少し修正します。</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;% if <span style="color: #66cc66;">&#40;</span>error<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;&lt;%<span style="color: #66cc66;">=</span> error %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span><br />
<span style="color: #009900;">&lt;% <span style="color: #66cc66;">&#125;</span> else <span style="color: #66cc66;">&#123;</span> %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span>&gt;</span>Short url is <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= short_url %&gt;</span></span>&quot;&gt;<span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> short_url %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span><br />
<span style="color: #009900;">&lt;% <span style="color: #66cc66;">&#125;</span> %&gt;</span></div></div>
<p><a href="https://github.com/visionmedia/ejs">ejs</a> テンプレートエンジンでは、&lt;% %> 内に JavaScript のコードをそのまま記述できます。</p>
<h4>mysql モジュールの使い方</h4>
<p>MySQL データベースへの問い合わせは、mysql モジュールの Client クラスを使用して行います。</p>
<p>データベース問い合わせも I/O ですので非同期で実行します。データベース接続やクエリが完了した際に実行される処理をコールバック関数で指定します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> Client <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mysql'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Client</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> client <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Client<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// 接続先データベースを指定</span><br />
client.<span style="color: #660066;">database</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'DB'</span><span style="color: #339933;">;</span><br />
client.<span style="color: #660066;">user</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'USER'</span><span style="color: #339933;">;</span><br />
client.<span style="color: #660066;">password</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'PASSWORD'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// データベースへ接続する</span><br />
client.<span style="color: #660066;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// クエリを実行する</span><br />
&nbsp; &nbsp; client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;SELECT * FROM T WHERE var = ?&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #003366; font-weight: bold;">var</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>connect メソッドのコールバック関数には、接続成功時は null が、失敗時は例外送出可能なエラーオブジェクトが渡されます。</p>
<p>query メソッドの引数は SQL、バインド変数、コールバック関数です。バインド変数とコールバック関数はそれぞれ省略可能ですので、以下のコードはすべて有効です。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;SQL&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;SQL&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #003366; font-weight: bold;">var</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;SQL&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>query メソッドのコールバック関数の引数は、SQL が SELECT の場合は function(err, results, fields) となります。SELECT 以外の場合は function(err, fields) です。</p>
<p>SELECT の場合も SELECT 以外の場合も、err には SQL 実行成功時 は null が、失敗時は例外送出可能なエラーオブジェクトが渡されます。</p>
<p>results は SELECT された列の配列です。配列の要素は列名をキーに持つオブジェクトです。SELECT 時の fields には SELECT された列定義が返されます。</p>
<p>SELECT 以外の場合、fields には affectedRows や insertId など SQL の実行結果を表す情報が渡されます。</p>
<p>MySQL モジュールの API の詳細については、<a href="https://github.com/felixge/node-mysql">https://github.com/felixge/node-mysql</a> をご覧ください。</p>
<h4>非同期コードでの例外処理</h4>
<p>非同期で実行される箇所で例外を送出する場合は注意が必要です。このように単純に例外を送出するとサーバが終了します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;sql...&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">throw</span> err<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ...</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>サーバを終了させずにユーザーにエラーを表示する場合は、例外ではなく普通にコンテンツを表示します。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">client.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;sql...&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> results<span style="color: #339933;">,</span> fields<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Not Found'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">404</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ...</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>express には例外送出によりエラー出力をフックするための仕組みが app.error() として用意されていますが、非同期部分から例外を送出してもこの仕組みで補足されませんので例外によらず直接エラー出力を行う必要があるようです。</p>
<h3>自作モジュール</h3>
<p>完成したウェブアプリケーションでは、短縮 URL の id 部分に、base62 の数値を 0-9a-zA-Z で文字列表現するモジュールを使用していますが、このモジュールは自作したものです。（機能的に分けただけで npm からインスコできる形のモジュールではありません。）</p>
<p>自作モジュールのロードも require で行いますが、モジュール名に ./ を付けて require(&#8216;./base62&#8242;) とすることでモジュール検索パスを無効にしています。</p>
<p>モジュールは普通の JavaScript ファイルとして作成します。require では拡張子を省略していますので、base62 モジュールのファイル名は base62.js です。</p>
<p>モジュールから外部へエクスポートするシンボルは、exports の要素にします。base62 モジュールでは int_to_base62_string と base62_string_to_int 関数をエクスポートします。</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> base62_map <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; int_map <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> x <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> String<span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; base62_map.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; int_map<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> x<span style="color: #339933;">++;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> a <span style="color: #339933;">=</span> <span style="color: #3366CC;">'a'</span>.<span style="color: #660066;">charCodeAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">26</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> String.<span style="color: #660066;">fromCharCode</span><span style="color: #009900;">&#40;</span>a <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; base62_map.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; int_map<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> x<span style="color: #339933;">++;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> A <span style="color: #339933;">=</span> <span style="color: #3366CC;">'A'</span>.<span style="color: #660066;">charCodeAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #CC0000;">26</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> String.<span style="color: #660066;">fromCharCode</span><span style="color: #009900;">&#40;</span>A <span style="color: #339933;">+</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; base62_map.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; int_map<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> x<span style="color: #339933;">++;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
exports.<span style="color: #660066;">int_to_base62_string</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>num<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> ret <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>num <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">=</span> base62_map<span style="color: #009900;">&#91;</span>num <span style="color: #339933;">%</span> <span style="color: #CC0000;">62</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span> ret<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; num <span style="color: #339933;">=</span> parseInt<span style="color: #009900;">&#40;</span>num <span style="color: #339933;">/</span> <span style="color: #CC0000;">62</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> head <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> n <span style="color: #339933;">=</span> <span style="color: #CC0000;">5</span> <span style="color: #339933;">-</span> ret.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> n <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> <span style="color: #339933;">--</span>n<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; head <span style="color: #339933;">+=</span> <span style="color: #3366CC;">'0'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>head<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">=</span> head <span style="color: #339933;">+</span> ret<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> ret<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
exports.<span style="color: #660066;">base62_string_to_int</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> ret <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> str.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> str.<span style="color: #660066;">substr</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">*=</span> <span style="color: #CC0000;">62</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">+=</span> int_map<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> ret<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h3>アプリを動かしてみる</h3>
<p>完成したので短縮URLウェブアプリを動かしてみます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>node server.js</div></div>
<p>サーバが起動したらブラウザで <a href="http://localhost:8124">http://localhost:8124</a> にアクセスします。</p>
<p><a href="http://sakuratan.biz/blog/wp-content/uploads/2011/01/node1.png"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/node1-300x180.png" alt="URL Shortener" title="URL Shortener" target="_blank" width="300" height="180" class="aligncenter size-medium wp-image-3296 capture" /></a></p>
<p>短縮したい URL を入力して submit を押すと URL が短縮されます。</p>
<p><a href="http://sakuratan.biz/blog/wp-content/uploads/2011/01/node2.png"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/node2-300x180.png" alt="URL Shortener" title="URL Shortener" target="_blank" width="300" height="180" class="aligncenter size-medium wp-image-3302 capture" /></a></p>
<p>そのまま短縮された URL をクリックすると元の URL にリダイレクトします。</p>
<p><a href="http://sakuratan.biz/blog/wp-content/uploads/2011/01/google.png"><img src="http://sakuratan.biz/blog/wp-content/uploads/2011/01/google-300x180.png" alt="google" title="google" target="_blank" width="300" height="180" class="aligncenter size-medium wp-image-3300 capture" /></a></p>
<p>チュートリアルは以上です。</p>
<p>最近の流行りは XMLHttpRequest や jsonp とか使った Facebook の BigPipe みたいな感じのウェブアプリだと思いますので、上で作ったようなちょいと古めのウェブアプリを node.js で作りたいかと聞かれたら答えは明らかに NO ですが、node.js の仕組みを覚えるにはこんな感じの簡単なものから入るのがよろしいんじゃないかと思います。</p>
<p>個人的には今のところ node.js を使う予定はありませんが、どうせ覚えるなら早めの方がよろしいんじゃないでしょうか。</p>
<p>んでわ</p>
<p>P.S. ずっと Node.js だと思い込んでたもんで最初先頭大文字で表記してたんですが、よく見りゃ node.js だったので後から直しました。キャプチャとかソース中の表記は直すのめんどいんで Node.js のままにしてます。サーセン</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/3101/feed</wfw:commentRss>
		<slash:comments>1029</slash:comments>
		</item>
		<item>
		<title>MacPortsからMySQLをインスコしようとしたらトラブったのでメモ</title>
		<link>http://sakuratan.biz/archives/3197</link>
		<comments>http://sakuratan.biz/archives/3197#comments</comments>
		<pubDate>Wed, 12 Jan 2011 07:25:01 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[MacPorts]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=3197</guid>
		<description><![CDATA[最近 MacBook を買ったので、ちょいちょい Mac でもプログラム作ったりしてます。 開発環境の構築は面倒っちいのでパッケージングシステムを使ってしてます。Mac にも Linux の RPM とか FreeBSD の ports みたいなパッケージングシステムが何種類かあるのですが、とりあえず MacPorts を使ってます。 「MacPorts で MySQL インスコできたよー＼(^o... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/3197">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>最近 MacBook を買ったので、ちょいちょい Mac でもプログラム作ったりしてます。</p>
<p>開発環境の構築は面倒っちいのでパッケージングシステムを使ってしてます。Mac にも Linux の RPM とか FreeBSD の ports みたいなパッケージングシステムが何種類かあるのですが、とりあえず <a href="http://www.macports.org/">MacPorts</a> を使ってます。</p>
<p>「MacPorts で MySQL インスコできたよー＼(^o^)／」とか書いてるブログが山ほどあったので、自分の MacBook にも MySQL インスコしてみよっかなーと作業を始めてみたらトラブったのでメモっときます。</p>
<h3>インストール手順</h3>
<p>root での作業は sudo から実行しています。ガイルとザンギは無視してくださいww</p>
<h4>1. mysql5 と mysql5-server パッケージをインストール</h3>
<p>port install で mysql5 と mysql5-server をインストールします。ビルドにちょっと時間がかかりますが、ここでは問題は発生しません。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> port <span style="color: #c20cb9; font-weight: bold;">install</span> mysql5 mysql5-server<br />
...</div></div>
<div class="AA2">
_＿＿＿＿_<br />
＼　　　　／<br />
　（　´∀｀）　ザンギエフへ　げんきですか。いまmysql5溜めてます<br />
　　　　 　 _　<br />
　　　　　 i_iヽ<br />
　　　　（ﾟдﾟ,,;;）　うるさい死ね　溜めるな殺すぞ
</div>
<h4>2. mysql_install_db5 を実行する</h4>
<p>mysql ユーザーで mysql_install_db5 を実行してデータベースを作成します。ここでも問題は発生しないと思います。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-u</span> mysql mysql_install_db5<br />
...</div></div>
<div class="AA2">
_＿＿＿＿_<br />
＼　　　　／<br />
　（　´∀｀）　mysql_install_db5 撃っておきました。ガードしてね　飛び込みはしますか？<br />
　　　　 　 _　<br />
　　　　　 i_iヽ<br />
　　　　（#)Д`;;）　死ねくそガイル
</div>
<h4>3. mysql サーバを起動する</h4>
<p>mysql サーバの起動スクリプトを実行します。以下のようにエラーメッセージが出ます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>share<span style="color: #000000; font-weight: bold;">/</span>mysql5<span style="color: #000000; font-weight: bold;">/</span>mysql<span style="color: #000000; font-weight: bold;">/</span>mysql.server start<br />
Starting MySQL<br />
...... ERROR<span style="color: #000000; font-weight: bold;">!</span> Manager of pid-file quit without updating file.</div></div>
<div class="AA2">
_＿＿＿＿_<br />
＼　　　　／<br />
　（　´∀｀）　ごめんね、ERROR!痛かった？　起き上がりにソニック重ねておきます<br />
　　　　 　 _　<br />
　　　　　 i_iヽ<br />
　　　　（#)Д`;;）　うるさい死ね　着地と同時にすぐ座り込むな
</div>
<h3>トラブルシューティング</h3>
<p>どこで実行に失敗してるのか確認するためログファイルを開きます。MySQL のログファイルは /opt/local/var/db/mysql5/snowleopard.local.err (ログファイル名は &#8220;マシン名.err&#8221; で環境によります）にあります。</p>
<p>問題はこの辺で発生しているようです。</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">110112 14:49:16 &nbsp;InnoDB: Started; log sequence number 0 0110112 14:49:16 [ERROR] Can't start server : Bind on unix socket: Permission den<br />
ied110112 14:49:16 [ERROR] Do you already have another mysqld server running on soc<br />
ket: /opt/local/var/run/mysql5/mysqld.sock ?<br />
110112 14:49:16 [ERROR] Aborting</div></div>
<p>ログによるとソケット mysqld.sock の作成に失敗しているようです。ソケットの作成先ディレクトリの /opt/local/var/run/ を ls で見てみます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<br />
ls: run: Permission denied<br />
$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-l</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<br />
drwx------ &nbsp;<span style="color: #000000;">5</span> root &nbsp;admin &nbsp;<span style="color: #000000;">170</span> &nbsp;<span style="color: #000000;">1</span> <span style="color: #000000;">12</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">45</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<span style="color: #000000; font-weight: bold;">/</span></div></div>
<p>あら、ディレクトリが開けませんね。/opt/local/var/run/ にパーミッションが無いのが問題のようです。</p>
<p>MacPorts では mysql を _mysql ユーザーで実行するのですが、ソケットの作成も _mysql ユーザーで行いますので、run ディレクトリにパーミッションが無いとソケットの作成に失敗し起動できません。</p>
<p>ということでディレクトリにパーミッションを付与して再起動してみます。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">755</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<span style="color: #000000; font-weight: bold;">/</span><br />
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>share<span style="color: #000000; font-weight: bold;">/</span>mysql5<span style="color: #000000; font-weight: bold;">/</span>mysql<span style="color: #000000; font-weight: bold;">/</span>mysql.server start<br />
Starting MySQL<br />
. SUCCESS<span style="color: #000000; font-weight: bold;">!</span></div></div>
<p>動きますた。</p>
<h3>その他の設定</h3>
<p>MySQL サーバの起動に成功したらシステムの設定をします。設定方法は <a href="http://d.hatena.ne.jp/akio0911/20080318/1205838594">MacPortsを使ってMacにMySQLをインストール</a>や <a href="http://code.google.com/p/bear-project/wiki/setup_osx">PHP5環境構築(OSX macports)</a> などを参考にしてください。</p>
<p>システムブート時に mysql を起動するように設定する際、/Library/LaunchDaemons/org.macports.mysql5.plist のインストール方法が若干改良されていますので、launchctl を直接実行せずに port load を実行した方が良いと思います。</p>
<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span><span style="color: #c20cb9; font-weight: bold;">sudo</span> port load mysql5</div></div>
<p>おしまい</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/3197/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MySQL のコネクションタイムアウトと削除されたプロセスのコネクションの残留</title>
		<link>http://sakuratan.biz/archives/1624</link>
		<comments>http://sakuratan.biz/archives/1624#comments</comments>
		<pubDate>Sat, 06 Feb 2010 00:42:45 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[CGI]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=1624</guid>
		<description><![CDATA[だいぶ前にロプローから MySQL データベースのコネクションの生存期間について聞かれてたんですが、返事するの忘れてたので今頃ブログ書いてます。どっちかって言うと忘れてたというよりは、手元の環境で問題が再現できないので放置してた感じですがw まず MySQL コネクションはデフォルト 8 時間でタイムアウトします。 関係しているシステムパラメータは wait_timeout か interacti... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/1624">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>だいぶ前にロプローから MySQL データベースのコネクションの生存期間について聞かれてたんですが、返事するの忘れてたので今頃ブログ書いてます。どっちかって言うと忘れてたというよりは、手元の環境で問題が再現できないので放置してた感じですがw</p>
<p style="margin-top:2em">まず MySQL コネクションはデフォルト 8 時間でタイムアウトします。</p>
<p>関係しているシステムパラメータは wait_timeout か interactive_timeout のいずれかです。CGI の場合は通常 wait_timeout が関係します。詳細は <a href="http://dev.mysql.com/doc/refman/5.1/ja/server-system-variables.html">http://dev.mysql.com/doc/refman/5.1/ja/server-system-variables.html</a> をご覧ください。</p>
<p style="margin-top:2em">システムパラメータの確認は SHOW VARIABLES コマンドで行えます。以下はポックン家のテスト用環境の値です。</p>
<pre>
mysql> SHOW VARIABLES LIKE '%_timeout';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| connect_timeout            | 10    |
| delayed_insert_timeout     | 300   |
| innodb_lock_wait_timeout   | 50    |
| innodb_rollback_on_timeout | OFF   |
| interactive_timeout        | 28800 |
| net_read_timeout           | 30    |
| net_write_timeout          | 60    |
| slave_net_timeout          | 3600  |
| table_lock_wait_timeout    | 50    |
| wait_timeout               | 28800 |
+----------------------------+-------+
10 rows in set (0.00 sec)
</pre>
<p>28800 秒なので 8 時間です。</p>
<p style="margin-top:2em">元々聞かれていたのは、「CGI プロセスをkill した際にデータベースコネクションが残ったままになることがあるか？」というような内容だったのですが、以下の手順で似たような現象を確認できます。（MySQL 5.0.67）</p>
<ol>
<li>あるプロセスがテーブルをロックしたままの状態になる</li>
<li>他のプロセスがロックされたテーブルを参照しようとし、1. のロックが解除されるのを待つ状態となる</li>
<li>2 のプロセスを kill -9 するとプロセスは消えるが、データベースコネクションはロック待ちの状態のまま残る</li>
</ol>
<p>ロック待ちのまま残ったコネクションは、1. のテーブルのロックが解除されると切断されます。ロック待ちのコネクションが切断されるまでの間、各コネクションはサーバのコネクションプールを消費します。従って、2. と同じ処理を行うプロセスが増えるとすべてロック待ちとなり、最終的に max_connections を越えるとデータベースに接続できなくなります。</p>
<p>他の原因により同様の事象が発生するかを確認してませんのでもうちょっと調べた方が良いような気もしますが、kill してもコネクションが残る状態自体は発生し得るようでしたのでとりあえずご報告ということで。（テーブルのロックは LOCK TABLE WRITE コマンドで発生させたのですが、MyISAM を使用している場合、テーブルロックを長時間持続させることはレアケースだとと思いますので、もうちょっと一般的な状況で発生させる方法が無いか調べた方が良いという感じです。）</p>
<p style="margin-top:2em">ちなみに MySQL の接続中のコネクションは SHOW PROCESSLIST コマンドで、ロック中のテーブルは SHOW OPEN TABLES コマンドで確認できます。</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/1624/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>WordPress をインストールしたさくらインターネットの共有鯖で MySQL4 から MySQL 5 に移行しつつ文字コードを EUC-JP から UTF-8 に変える方法</title>
		<link>http://sakuratan.biz/archives/577</link>
		<comments>http://sakuratan.biz/archives/577#comments</comments>
		<pubDate>Sun, 19 Apr 2009 17:18:28 +0000</pubDate>
		<dc:creator>さくら</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[開発環境]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[さくらインターネット]]></category>

		<guid isPermaLink="false">http://sakuratan.biz/?p=577</guid>
		<description><![CDATA[さくらです♪こんばんわ♡☆彡 やっとさくらの鯖も MySQL5.1 に対応したみたいだから移行してみたわ。 なんか WordPress も速くなるらしいし期待 ageage よね！ ついでにデータベースの文字コードを EUC-JP から UTF-8 に変更してみたの。 どこに書いてたか忘れてたけど、MySQL4 の UTF-8 はバグってるらしいって聞いてたから EUC-JP にしてたのね。でもト... <div style="margin-top:1ex"><a href="http://sakuratan.biz/archives/577">(続きを読む)</a></div>]]></description>
			<content:encoded><![CDATA[<p>さくらです♪こんばんわ♡☆彡</p>
<p>やっとさくらの鯖も MySQL5.1 に対応したみたいだから移行してみたわ。<br />
なんか WordPress も速くなるらしいし期待 ageage よね！</p>
<p>ついでにデータベースの文字コードを EUC-JP から UTF-8 に変更してみたの。<br />
どこに書いてたか忘れてたけど、MySQL4 の UTF-8 はバグってるらしいって聞いてたから EUC-JP にしてたのね。でもトラバが文字化けしたりする原因になってるっぽかったし、WordPress をもっとシャキシャキ動くようにしたいから前から UTF-8 に変更したかったんだけど、なんとなく伸び伸びになってたの。なんで今回一緒に片付けることにしたわ。</p>
<p>同じことしたい人も他にいるかもしれないから、やり方まとめとくわね。<br />
まず最初に全体的な流れを説明するわ。</p>
<ol>
<li>データベースのダンプを作成する</li>
<li>MySQL4 データベースを削除する</li>
<li>MySQL5 データベースを再作成する</li>
<li>データベースダンプをリストアする</li>
<li>WordPress の設定を変更する</li>
</ol>
<p>MySQLAdmin とか使ってもできると思うんだけど、わざわざネットワークトラフィック使う意味があんまりないから全部鯖上のシェルで操作するやり方を説明してるわよ。先に <a href="http://sourceforge.jp/projects/ttssh2/">TeraTerm</a> とか何でもいいからターミナルエミュレータを用意しといてね。ターミナルは UTF-8 を強制的に表示できるやつが便利だと思うわよ。</p>
<p>あ…そうそう、一ついい忘れてたんだけど、MySQL5 が使えるかは共有 SSL が使えるかとセットになってるはずだから、コントロールパネルのドメイン設定とかで SSL が使えるか確認してから移行作業するかどうか検討してね♡</p>
<p>あと以下の作業を始める前に、WordPress の wp-config.php のデータベースパスワードをコメントアウトするとかして WordPress を一時停止しといた方がいいと思うわ。じゃ頑張って！！</p>
<h2>データベースのダンプを作成する</h2>
<p>ダンプってのは丸まんま取り出したデータって意味でとらえて貰って構わないわ。データベースダンプの場合、CREATE TABLE とかデータベースを再作成するのに必要なデータ一式ってことよ。</p>
<p>ダンプを取るには <a href="http://dev.mysql.com/doc/refman/4.1/ja/mysqldump.html">mysqldump</a> コマンドを使うの。普段はバックアップを取るのに使うやつね。</p>
<p>ちなみに今、さくらインターネットの共有鯖には MySQL4 用の mysqldump-4.0 と MySQL5 用の mysqldump がインスコされてるはずなの。当然今回は MySQL4 から MySQL5 に移行するんだから、mysqldump-4.0 を使うのよ。ターミナルで鯖にログオンしたらこんな感じで実行するの。</p>
<pre>$ cd [どっか]
$ mysqldump-4.0 -u [USER] -h [HOST] [DBNAME] -p > mysql.dump
Enter password:</pre>
<p>[どっか] はどっか適当なディレクトリのことよ。別に HOME でも構わないわ。<br />
[USER] はデータベースユーザー名、[HOST] はデータベースホスト名、[DBNAME] はデータベース名ね。データベース初期化したときにさくらインターネットから教えてもらってるはずよ。</p>
<p>コマンドを実行したらパスワード入力待ち状態になるからちゃんと入力して。入力したら mysql.dump ってファイルにデータベースダンプが取れるわ。後で使うから大事に取っとくのよ。</p>
<p>え？ユーザー名とかが分かんないですって？<br />
よく今まで使ってこれたわね…悪いけど付き合ってらんないわww</p>
<h2>MySQL4 データベースを削除する</h2>
<p>さくらインターネットのコントロールパネルの [データベースの設定] から [データベースを削除] ボタンを押せば消せるわ。このキャプチャの下の方にあるボタンよ。</p>
<p><img src="http://sakuratan.biz/blog/wp-content/uploads/2009/04/dropdb.png" alt="データベースの削除" title="データベースの削除" width="520" height="301" class="aligncenter size-full wp-image-578" style="border:solid 1px gray" /></p>
<p>消す前に深呼吸でもして、手抜かりが無いか確認した方がいいと思うわ。<br />
もう後戻りできないところに来てるの、ワタシ達…<br />
<strike>一緒に元気な赤ちゃん育てましょ！！</strike></p>
<h2>MySQL5 データベースを再作成する</h2>
<p>データベースを消したらそのまま新しいデータベースを作ればいいわ。MySQL のバージョンが選べるようになってるから MySQL5.1 を選ぶのよ。</p>
<p><img src="http://sakuratan.biz/blog/wp-content/uploads/2009/04/createdb.png" alt="データベースの作成" title="データベースの作成" width="522" height="155" class="aligncenter size-full wp-image-579" style="border:solid 1px gray" /></p>
<p>ついでにデータベースのパスワードを変えとくのもいいわね。</p>
<h2>データベースダンプをリストアする</h2>
<p>リストアってのはダンプを元に戻すってことね。<br />
ちょっと今回は文字コードを変更する関係で、リストアする前にデータベースのデフォルト文字セットを UTF-8 に変更したりしてるわよ。要らない人はその辺<strike>もっとさくらにザーメン</strike>飛ばしちゃって。</p>
<p>リストアするには <a href="http://dev.mysql.com/doc/refman/5.1/ja/mysql.html">mysql</a> コマンドでダンプファイルを読みこめばいいの。とりあえずターミナルに戻ってコマンドを実行してちょうだい。<br />
後でログとか見たかったら <a href="http://www.linux.or.jp/JM/html/util-linux/man1/script.1.html">script</a> コマンドを先に実行しといたらいいと思うわ。これしとくと、typescript ってファイルにコマンドと結果全部が保存されるの。</p>
<pre>$ script
Script started, output file is typescript
$ mysql -v -u [USER] -h [HOST] [DBNAME] -p</pre>
<p>mysql コマンドを -v 付きで実行してるのは、後で \. コマンドでダンプを読み込む際に実行したコマンドを表示させるためね。これするとメッセージが大量に表示されるようになるから、バカでかいダンプファイル作ってる人は -v 付けない方がいいと思うわよ。<br />
で、MySQL データベースにログオンしたらまず \s コマンドで文字セットを見て頂戴。こんな感じで全部 ujis になってるんじゃないかしら？</p>
<pre>mysql> \s
[省略]
Server characterset:    ujis
Db     characterset:    ujis
Client characterset:    ujis
Conn.  characterset:    ujis
[省略]</pre>
<p>ujis ってのは EUC-JP のことね。とりあえず utf8 になってなかったら alter database コマンドで文字セットを変えるの。</p>
<pre>mysql> alter database [DBNAME] character set utf8;</pre>
<p>[DBNAME] はデータベース名ね。さくらインターネットの共有鯖ならユーザー名と一緒になってると思うわ。実行したら \s コマンドで再確認してね。</p>
<pre>mysql>\s
[省略]
Server characterset:    ujis
Db     characterset:    utf8
Client characterset:    ujis
Conn.  characterset:    ujis
[省略]</pre>
<p>Db characterset が utf8 に変わってると思うわ。これを確認してから \C [CHARSET] コマンドでクライアントと接続文字セットも utf8 に変えるの。</p>
<pre>mysql> \C utf8
Charset changed</pre>
<p>これで Client characterset と Conn.  characterset も utf8 に変わるはずよ。\s で再確認してちょうだい。<br />
本当は Client characterset はターミナルの設定に合わせて指定しないといけないんだけど、その辺は行間を読んでよねww</p>
<p>文字セットの変更が終わったらダンプをリストアするわ。\. コマンドを実行しちゃって！</p>
<pre>mysql> \. mysql.dump
[省略]
Query OK, 1 row affected (0.00 sec)
mysql> \q
Bye
$ exit
Script done, output file is typescript</pre>
<p>リストアしたら mysql はすぐ終了しちゃってもいいわよ。シェルからも exit してるのは script コマンドを終了させるためね。exit の代わりにCtrl-D でもいいわよ。</p>
<p>暇だったらここで typescript ファイルを見てみるのもいいと思うわ。<br />
まあさくら程度ブログで記事書いてる人はデータベースも結構大きくなってる思うから、目視で検査するのは無理っぽいんだけどね。<br />
どっちにしろ作業ログなんか気休め程度に思っといた方がいいわよ。<br />
この時点で何か問題見つけてももうどうにもならないんだからwww</p>
<h2>WordPress の設定を変更する</h2>
<p>WordPress の設定で最小限必要なのは、データベースが新しいホストに変わってるはずだからそれを直すことね。後、データベース再作成のときにパスワード変えたりとかしてたらそれも直さないといけないわよ。</p>
<p>一応今回は WordPress の移行に関する説明だからこの辺の詳細は省略するわね。詳しく知りたい人は <a href="http://ja.wordpress.org/install/">ja.wordpress.org の インストールガイド</a> でも見てね。</p>
<p>とりあえずこれで「MySQL4 から MySQL5 への移行 + WordPress の再設定 + MySQL の文字コードを EUC-JP から UTF-8 にする」は完了よ！<br />
さくらのやり方を参考にして失敗しても知らないけど、やる気のある人はトライしてみて！！！</p>
<p>さくら</p>
]]></content:encoded>
			<wfw:commentRss>http://sakuratan.biz/archives/577/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
