-->

2011-12-06

node.js, express, ejsのインストール

参考URL。
http://d.hatena.ne.jp/t_43z/20110503/1304421488
http://d.hatena.ne.jp/sasaplus1/20110104/1294076643
http://d.hatena.ne.jp/tek_koc+programing/20110430/1304174401
http://nodejs.org/
http://nodejs.jp/
http://nodejs.jp/nodejs.org_ja/api/index.html
http://hideyukisaito.github.com/expressjs-doc_ja/
http://hideyukisaito.github.com/expressjs-doc_ja/guide/#template-engines

node.js, express, ejsのインストール。

ユーザー作成。
#$ sudo userdel nodejs -r
$ sudo useradd -m nodejs
$ sudo su - nodejs
$ pwd
/home/nodejs
$ whoami
nodejs

naveをインストール。
$ git clone https://github.com/isaacs/nave.git ~/.nave
$ ~/.nave/nave.sh use latest
...(長い)
$ ~/.nave/nave.sh use latest
already using 0.6.5
$ alias nave=$(realpath ~/.nave/nave.sh)
$ echo alias nave=$(realpath ~/.nave/nave.sh) >> .bashrc
$ tail -n2 .bashrc
# Put your fun stuff here.
alias nave=/home/nodejs/.nave/nave.sh
$ nave use latest
already using 0.6.5

npmをインストール。(nave use latestが成功していればすぐ終わる)
$ curl http://npmjs.org/install.sh | sh

モジュールをインストール。
$ npm install express@latest
$ npm install ejs@latest
$ npm ls
/home/nodejs
├── ejs@0.5.0
└─┬ express@2.5.1
  ├─┬ connect@1.8.2
  │ └── formidable@1.0.8
  ├── mime@1.2.4
  ├── mkdirp@0.0.7
  └── qs@0.4.0

別のユーザーで実行。(ejs-test001.jsは参考サイトのserver.jsのrequire.paths.pushをコメントアウトしたもの)
$ NODE_PATH=/home/nodejs/node_modules/ /home/nodejs/.nave/installed/0.6.5/bin/node ejs-test001.js

別のユーザーで実行。
$ w3m http://127.0.0.1:8124/
hello world!

<p>hello world!</p>

大丈夫そうであればnodeコマンドを検索パスに入れるなど。
$ cat /usr/local/bin/node
#!/bin/sh
NODE_PATH=/home/nodejs/node_modules/ /home/nodejs/.nave/installed/0.6.5/bin/node $@

再確認。
$ node ejs-test001.js
$ w3m http://127.0.0.1:8124/

npmのalias。
$ alias npm=$(realpath ./.nave/installed/0.6.5/bin/npm)
$ echo alias npm=$(realpath ./.nave/installed/0.6.5/bin/npm) >> .bashrc
$ tail -n3 .bashrc
# Put your fun stuff here.
alias nave=/home/nodejs/.nave/nave.sh
alias npm=/home/nodejs/.nave/installed/0.6.5/lib/node_modules/npm/bin/npm-cli.js

2011-11-30

node.jsのtest

var
http = require("http"),
querystring = require("querystring"),
convertDate = function(date){
  return ("0" + date.getHours()).slice(-2) + ":" +
    ("0" + date.getMinutes()).slice(-2) + ":" +
    ("0" + date.getSeconds()).slice(-2);
},
htmlEscape = (function(){
  var pattern = /([&<>\"])/g,
  escapeChars = {"&":"&amp;", "<":"&lt;", ">":"&gt;", "\"":"&quot;"},
  urlPattern = /(^|[^-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#])(https?:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]{5,63})($|[^-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#])/;
  return function(str){
    return String(str).replace(pattern, function(){
      return escapeChars[arguments[1]];
    }).replace(urlPattern, "$1<a href=\"$2\">$2</a>$3");
  };
})(),
appUrl = "http://192.168.0.100/nodejs/",
readCount = 0,
writeCount = 0,
bbsLog = [];
http.createServer(function (request, response) {
  var
  postMessage = function(){
    var body = "";
    request.on("data", function(data){
      body += data;
    });
    request.on("end", function(){
      var $_POST =  querystring.parse(body), writeDate;
      if (typeof $_POST["message"] == "string" && $_POST["message"] !== "")
      {
        writeDate = new Date;
        bbsLog.unshift({"date":writeDate, "message":$_POST["message"]});
        while (bbsLog.length > 10)
        {
          bbsLog.pop();
        }
        writeCount++;
        console.log(writeDate, "postMessage", readCount, writeCount, $_POST);
      }
      response.writeHead(302, {"Location": appUrl});
      response.end();
    });
  },
  getMessage = function(){
    var
    bbsLogToHtml = function(){
      var i, buf = "";
      for (i = 0; i < bbsLog.length; i++)
      {
        buf += convertDate(bbsLog[i].date);
        buf += " : ";
        buf += htmlEscape(bbsLog[i].message);
        buf += "<br/>";
      }
      return buf;
    };
    readCount++;
    response.writeHead(200, {"Content-Type": "text/html; charset=UTF-8"});
    response.end(
      "<html>" +
        "<head>" +
        "<style>" +
        "*{" +
        "font-family: monospace, sans-serif;" +
        "}" +
        "</style>" +
        "</head>" +
        "<body>" +
        "<h1>Sample BBS</h1>" +
        "readCount : " + readCount + "<br/>" +
        "writeCount : " + writeCount + "<br/>" +
        "<form action=\"" + appUrl + "\" method=\"post\">" +
        "<input type=\"text\" name=\"message\" value=\"Hello World\" size=\"63\"/>" +
        "<input type=\"submit\"/>" +
        "&nbsp;<a href=\"" + appUrl + "\">Reload</a>" +
        "</form>" +
        bbsLogToHtml() +
        "</body></html>");
    console.log(new Date, "getMessage", readCount, writeCount);
  };
  if (request.method == "POST")
  {
    postMessage();
  }
  else
  {
    getMessage();
  }
}).listen(8124);
console.log("Server running at http://127.0.0.1:8124/");

node.jsのマニュアルの最初の方にあるサンプル+postデータの取得のサンプルです。
普通は express, ejs などのフレームワークやテンプレートエンジンを使うらしいのでそっちが良いです。
ab2でベンチマーク(getMessage()を連続で実行)を取った所-c5000~10000ぐらいまでは性能が低下せずに-c20000では処理量が半分まで落ちた。
サンプルの処理内容は単純だがメモリの利用量が少ないことやシングルタスク(Phenom(tm) 9350e)でRequests per secondが2500前後になることを見ると、実用性があるように思う。
エラーが不親切な気もするが設定があるのかもしれない。
// インストール(gentooの場合)
$ sudo ACCEPT_KEYWORDS="~*" emerge --oneshot -avt =net-libs/nodejs-0.6.2
// 実行
$ node example.js > /tmp/nodejs.example.js.log 2>&1 &
// テスト
$ ab2 -n1000 -c100 http://127.0.0.1:8124/ 2>&1|grep "^Requests per second"
Requests per second:    2621.41 [#/sec] (mean)

参考URL。
http://nodejs.jp/nodejs.org_ja/api/synopsis.html
http://onlineconsultant.jp/pukiwiki/?node.js%20GET%20POST%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B
http://snippets.dzone.com/posts/show/13311

2011-11-24

javascriptのtry{...}catch(e){...}の変数eのスコープ

ブラウザによってcatch(e)のeの参照できる範囲が違うので、
finallyなどで代用できる場合はそうしたほうが良いかもしれない。

もしくはeのスコープが限定的になるように無名関数で囲む。
(function(){
  var e;
  try
  {
    ...;
  }
  catch(e)
  {
    ...;
  }
})();

もしくは"e"を予約語として扱う。
"for","if"のように変数名に使えないものとして扱う。
try,catchが入れ子になっていたら困るかもしれない。


Firefox8の場合。catch(e){var e; ...} っぽい感じ。
Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/8.0
number : 1
number : 1
string : throw
number : 1
number : 2
number : 2 

IE8の場合。var e; catch(e){...} っぽい感じ。
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
number : 1
undefined : undefined
string : throw
string : throw
number : 2
number : 1

2011-11-22

convertCsvToTable.js


ダウンロード。
https://docs.google.com/open?id=0BwK7sPpG0c5ZYjJmZjMxYTItZGU4ZS00N2IyLThlNGItZDFiYmM3MjVmYjlm

説明。
mail
メールソフトを開きます。
下書きなどで保存します。
内容はcsv固定です。
html
htmlのソースを表示します。
メモ帳などにコピーアンドペーストします。
htmlファイルに保存してブラウザで表示してもjavascriptの機能はありません。
save
csvを表示します。
メモ帳などにコピーアンドペーストします。
load
csvをペーストします。
成功すると表示が更新されます。
reset
初期表示に戻します。
成功すると表示が更新されます。
save-json
json(javascriptの配列データ)を表示します。
メモ帳などにコピーアンドペーストします。
必要ない場合は関数の引数の該当部分をfalseにしてjquery.json-2.3.jsのタグを削除して下さい。
load-json
jsonをペーストします。
成功すると表示が更新されます。
必要ない場合は関数の引数の該当部分をfalseにしてjquery.json-2.3.jsのタグを削除して下さい。
csvの1行目
列のタイトルがあるものとして処理します。
固定です。
列のタイトルをクリック
データをソートします。
もう1度クリックすると逆順にソートします。
ソートの種類
種類は1種類で固定です。
列全体が数字に似ているデータの場合、表示が右寄せになる場合があります。
そうなると数値的にソートしますのでご注意下さい。
文字列の場合ひらがなとカタカナやアルファベットの大文字小文字などを無視してソートします。
問題がある場合、別のデータを追加してソートして下さい。
データ部分をクリック
背景色を変更します。
もう1度クリックすると戻ります。
tableの1列目
行番号を表示します。
行番号をクリック
行全体の背景色を変更します。
データ部分のクリックを無効化します。
もう1度クリックすると戻ります。
/*$.ajax({url:"test.csv" ... */とは?
javascriptのコメントです。
1つ上の行をコメントアウトして、この行を有効にすると動的にcsvファイルをロードします。
外部ドメインや、もしくは同一ドメインであっても自身の管理外のファイルを指定してはいけません。
エラー時などの処理がありません。手動で追加して下さい。下記は公式サイトのマニュアルです。
http://api.jquery.com/jQuery.ajax/
対応ブラウザ
確認したブラウザは以下の通りです。
windows xp professional の IE8
windows xp professional の IETester v0.4.11 の IE6,IE7,IE8
windows xp professional の Opera 11.52
windows xp professional の Google Chrome 11.0.696.68
windows xp professional の Safari 5.0.5
windows xp professional の Firefox 8.0
gentoo linux の www-client/opera 11.52.1100
gentoo linux の www-client/chromium 15.0.874.120
gentoo linux の www-client/firefox 7.0.1-r1
似た環境のOS/ブラウザで動作する可能性が高いです。
その他
データに半角のダブルクォーテーションやバックスラッシュがある場合、利用者ごとの期待した結果にならない場合があります。
フォーマットの変更やデータの追加、変更、削除はできないです。excel, open office, libre officeなどで対応して下さい。
エラーやバグや不具合や使いにく点がある場合このページのコメントなどでご報告頂けるとありがたいです。

2011-11-18

javascriptのinclude

テスト用のinclude関数です。
実際にローカル以外で使用すると非同期ではないので、
読み込みごとに停止しているのが目立つようになりますので使えません。
var include = function(){
  var hostnamePattern = new RegExp(
    "^https?://" +
      location.hostname.replace(
        new RegExp("[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]", "g"),
        "\\$&") +
      "/"),
  protocolPattern = new RegExp("^[A-Za-z]+://"),
  statusOkPattern = new RegExp("^[^23]"),
  getErrorFunc = function(jqXHR, textStatus, errorThrown){
    var status = String(jqXHR.status);
    if (status.match(statusOkPattern))
    {
      jqXHR.responseText = "";
      throw textStatus + " " + status + " " + errorThrown + ".";
    }
  };
  return function(path){
    var ret = "";
    if (path.match(hostnamePattern) || !path.match(protocolPattern))
    {
      ret = $.ajax({
        type: "GET",
        url: path,
        dataType: "text",
        async: false,
        error: getErrorFunc
      }).responseText;
    }
    else
    {
      throw "other site url. \"" + path + "\"";
    }
    return ret;
  };
}();

例。
...
eval(include("mb_convert_kana.js"));
...

非同期で読み込むがファイルに依存性がある場合RequireJSなどがあるようです。
http://requirejs.org/docs/api.html
http://zudolab.net/blog/?p=451

もしくは2回目以降のアクセスは304になることを期待して1つのファイルにまとめて<head>に書くというのもありだと思います。
非同期でも同期でも100ファイル読み込んだら200か304を100回webサーバーから受け取るということに変わりないと思うので。
$ echo "var a=1;" > 00_a.js
$ echo "var b=a+1;" > 01_b.js
$ ls -1 *.js | grep -v ^all.js$ | while read -r f; do cat $f; done > all.js
$ cat all.js
var a=1;
var b=a+1;

メールが届かない(clamdが起動していない)

メールが届いていない。
$ sudo tail -n1 /var/log/mail.err
Nov 18 03:37:59 amdgentoo dovecot: master: Error: service(imap-login): command startup failed, throttling

$ sudo tail -n4500 /var/log/mail.log | lv
...
Nov 18 06:10:17 amdgentoo postfix/pickup[4409]: warning: 7D08E16D908: message has been queued for 1 days
Nov 18 06:10:17 amdgentoo postfix/pickup[4409]: 7D08E16D908: uid=0 from=<root>
Nov 18 06:10:17 amdgentoo postfix/cleanup[18504]: 7D08E16D908: message-id=<20111117211017.7D08E16D908@amdgentoo.localnet>
Nov 18 06:10:17 amdgentoo postfix/cleanup[18504]: 7D08E16D908: milter-reject: END-OF-MESSAGE from localhost[127.0.0.1]: 4.7.1
Service unavailable - try again later; from=<root@amdgentoo.localnet> to=<root@amdgentoo.localnet>
...

大量に下記のエラーが発生している。書き込めなくなっている。
$ sudo tail -f /var/log/clamav/clamav-milter.log
...
ERROR: Failed to initiate streaming/fdpassing
WARNING: No clamd server appears to be available
...

最大値を増やす。
$ rcsdiff /etc/config-archive/etc/clamav-milter.conf,v /etc/clamav-milter.conf
===================================================================
RCS file: /etc/config-archive/etc/clamav-milter.conf,v
retrieving revision 1.7
diff -r1.7 /etc/clamav-milter.conf
231c231
< #LogFileMaxSize 2M
---
> LogFileMaxSize 20M

clamav-milter.logのローテーションの設定は無い。
$ qlist clamav|grep /etc/logrotate.d/
/etc/logrotate.d/clamav

サイズを増やすと同じエラーが書き込まれる。
$ ll -h /var/log/clamav/clamav-milter.log
-rw-r----- 1 clamav clamav 1.4M 2011-11-18 06:10:26 /var/log/clamav/clamav-milter.log

/etc/conf.d/clamdがいつのまにか下記のようになっている。
MILTER_NICELEVEL=19
START_MILTER=yes

戻した。
$ diff -u -U16 /usr/portage/app-antivirus/clamav/files/clamd.conf /etc/conf.d/clamd
--- /usr/portage/app-antivirus/clamav/files/clamd.conf  2008-03-01 08:46:46.000000000 +0900
+++ /etc/conf.d/clamd   2011-11-18 06:22:12.601252509 +0900
@@ -1,9 +1,11 @@
 # Config file for /etc/init.d/clamd

 # NOTICE: Since clamav-0.85-r1, only START_CLAMD and START_FRESHCLAM settings
 #        are used, other are silently ignored

 START_CLAMD=yes
 START_FRESHCLAM=yes
 CLAMD_NICELEVEL=3
 FRESHCLAM_NICELEVEL=19
+MILTER_NICELEVEL=19
+START_MILTER=yes

デフォルト値はyesが無いとclamdなどは起動しない。
$ grep START_CLAMD /etc/init.d/clamd
        if [ "${START_CLAMD}" = "yes" ]; then
        if [ "${START_CLAMD}" = "yes" ]; then
        if [ "${START_CLAMD}" = "yes" ]; then

メールが送れない状態。
$ pstree clamav
clamav-milter───2*[{clamav-milter}]

メールが送れる状態。
$ pstree clamav
clamav-milter───2*[{clamav-milter}]

clamd───{clamd}

freshclam

システム更新時に起動時のデフォルト値が変わりそれに合わせて設定を更新したが、
しかし起動時のデフォルト値は戻った、といった原因かもしれない。
もしくは何かの都合で/etc/conf.d/clamdの設定を手動で減らしたのかもしれない。

2011-11-13

mb_convert_kana.js


ダウンローはこちらから。
https://docs.google.com/open?id=0BwK7sPpG0c5ZYWRiNDcyZWYtODY2Ni00MmRkLWIwMjMtYTcwNWExZTgwMzZm

説明。
http://php.net/manual/ja/function.mb-convert-kana.php

2011-11-10

jquery-1.7.min.jsの短くなりそうな点 part2


91186 byte になった。
null,数字,文字列が複数ある場合変数にする。文字列は完全一致するもの同士のみ。
true,falseが!0,!1になっているので真似する。0.5 => .5 に省略する。
ハッシュのキーは文字列ではない場合、予約語を使うとIE系でエラーになる。
IE系で、そのスコープでは使わないからといって同じ名前の変数名に上書きすると、
ある程度の量で全く別の変数を見るかもしれない。それは124回目からかもしれない。
window.defineという変数があるかどうか見ている。たぶんrequireJS関連。

2011-11-28 追記
91096 byteになった。
使っていないかもしれないvarの部分を削除した。
u.test("\u00a0")などの部分が逆に長くなった。

2011-12-02 追記
91080 byteになった。
\u00a0 => \xa0, \u00c0 => \xc0