2011年8月3日水曜日

muninで独自プラグインを作成

どうも、俺@終業前です。

今日はmuninで独自のデータを取得する方法についてめもめも。
すごく簡単です。
例としてDB(MySQL)からとあるテーブル(fooテーブルとbarテーブル)の総件数をロギングしたいと思います。

まずmuninのプラグインのあるディレクトリに実行ファイルを作成します。
このファイルはシェルスクリプトでもphpスクリプトでも何でも構いません。決められた引数に対して決められた値を返せれば良いです。
yumでインストールした場合は、/usr/share/munin/plugins 以下になります。
# cd /usr/share/munin/plugins
# vim table_count
当然このファイルには実行権限を付けておいてください。
# chmod +x table_count

基本的には
1)引数「config」を与えられたときに値を返す(グラフ情報)
2)引数なしで実行されたときに値を返す(実際の値)
のように作成します。
他にも引数はいくつかありますが、特にMuninプラグインの作り方:ククログに詳しく書かれてありましたので参考にしてください。

引数「autoconf」と引数「suggest」についてとても参考になりました。
今回はこれらは割愛します。

まず引数「config」の時の処理を書きます。
# vim table_count
----------------------------------------
#!/bin/sh

if [ "$1" = "config" ]; then
  echo 'graph_title table count' # グラフのタイトル。
  echo 'graph_args --base 1000 -l 0' # 何も気にせず書く。
  echo 'graph_vlabel adfit_database_info' # グラフのラベル。y軸のとこに出ます。
  echo 'graph_category other' # グラフのカテゴリ。一覧のHTMLで表示されるカテゴリ。DiskとかNetworkとかOtherとかProcessesとかのやつ。
  echo 'graph_info Database data info.' # グラフの情報。詳細ページの下の方に出る。

  echo 'foo.label total foo' # fooテーブルの件数についてのラベル。
  echo 'foo.draw LINE2' # 線グラフという意。他にもAREAやSTACKがある、らしい。
  echo 'foo.info total foo table count.' # ラベルfooに対する説明。

  echo 'bar.label bar table count' # barテーブルの件数についてのラベル。
  echo 'bar.draw LINE2' # 線グラフという意。他にもAREAやSTACKがある、らしい。
  echo 'bar.info total bar table count.' # ラベルfooに対する説明。
  exit 0
fi

引き続き、引数なしで実行された時の処理を書きます。
# vim table_count
----------------------------------
echo -n "foo.value "
/path/to/mysql databasename -u username -e 'SELECT COUNT(*) FROM foo' | awk 'NR==4 { print }' | sed -e "s/ //g"

echo -n "bar.value "
/path/to/mysql databasename -u username -e 'SELECT COUNT(*) FROM bar' | awk 'NR==4 { print }' | sed -e "s/ //g"
かなりぶきっちょな書き方ですみません。もっとスマートな方法あるかも知れません。

これを実行プラグインのシンボリックリンクがあるディレクトリに、同じくシンボリックリンクを貼ります。
yumでインストールした場合は、/etc/munin/plugins になります。
# ln -s /usr/share/munin/plugins/table_count /etc/munin/plugins

最後にmunin-nodeを再起動して完了です。
# /etc/init.d/munin-node restart


これでグラフが描画されるはずです。
以上でぇぇぇぇぇぇぇぇす。

2011年7月27日水曜日

javascriptでurlエンコードしたものをphpでデコードする

どうも、俺@仕事中です。
相変わらずNodeやってます。

Node側でユーザの入力データを受け取り、それをphpへ渡すような事をする場合は
javascriptで入力データをURLエンコードしてphpでデコードを行う必要が出てきます。

javascriptには
escape(str);
encodeURI(str);
encodeURIComponent(str);
の3つエンコード関数があり
phpには
urldecode($str);
rawurldecode($str);
の2つデコード関数があります。

どうやらそれぞれエンコード/デコードのアルゴリズムが違うらしく
全くデータの受け渡しが出来なかったので、どれとどれの組み合わせだったらうまく動作するのか確認しようかな
と思ってたところ、やってくれてる方がいらっしゃいました。

JavaScriptとPHPのURLエンコード【JavaScript,PHP】:Programming Magic

このサイトを参考にして、javascriptでは
encodeURIComponent(str)
してからphpへ送り、
phpでは
rawurldecode($str);
すれば正しく受け渡しができました。感謝!!
逆の場合でも同じですね。


以上でぇぇえっぇぇす。

2011年7月19日火曜日

socket.ioをv0.6.xからv0.7.xへ変更する

どうも、俺@仕事中です。

socket.ioのv0.7.xが出てたという噂を聞きつけて早速
# npm update socket.io
しちゃったら、途端にnodeアプリが動作しなくなっちゃいました。
そこで、socket.ioのv0.7.xの仕様変更、特にメッセージ送受信部分について簡単にめもめもします。
まぁ、、socket.io : github : Migrating 0.6 to 0.7からの引用です。
※express上で動作させているものとします。


■ソケットの生成
・サーバ側
var io = require("socket.io").listen(app);
io.sockets.on('connection', function(socket) {
   console.log('接続されました');
});

・クライアント側
var socket = io.connect('http://node.server.com:3000');
すでにv0.6.xと実装が異なります。

■メッセージ送受信
・サーバ側
io.sockets.on('connection', function(socket) {
  socket.on('message', function(data) {
    // 受信処理
  });
});

・クライアント側
var socket = io.connect('http://node.server.com:3000');
socket.send(data);
// または
socket.json.send(data, [callback]);
v0.7.xからは socket.json.send() により明示的にJSONへ変換するように指定できるようになりました。(省略可)
それ以前は自動的にJSONへ変換がかかっていたので、それを変換する/しないが指定できるようになった形です。
callbackでは、送信後の処理を記述できます。(送達確認処理)

■メッセージ送受信(カスタムイベント)
v0.7.xからはメッセージやり取りに開発者の指定するカスタムイベントによって送受信できるようになりました。
・サーバ側
socket.on('custom event', function(data) {
  // custom eventを受け取ったときの処理
});

・クライアント側
socket.emit(custom event, data, [callback]);


■サーバからのメッセージ送信
・サーバ側
// 自分自身へ送る
socket.emit('custom response', data);
// 自分以外全員へ送る
socket.broadcast.emit('custom response', data);
// 自分を含む全員へ送る
io.sockets.emit('custom response', data);

ちなみにこれらemit()でサーバから送られたデータをクライアント側で受け取る場合は、第1引数に指定されたイベント名でなければ受信できません。
・クライアント側
socket.on('custom response', function(data) {
  // 受け取ったときの処理
});

v0.6.xのようにクライアント側で
socket.on('message', function(data) {
});
で受け取る場合は、サーバ側の送信部分は
socket.send(data);
socket.broadcast.send(data);
io.sockets.send(data);
のように記述すればOKです。

また特定のソケットセッションに対し送信することもできるようになりました。
・サーバ側
io.sockets.socket(<session id>).send(data);
io.sockets.socket(<session id>).emit('custom response', data);
<session id>は任意のセッションIDです。

セッションIDはv0.6.xまではsocket.sessionIdで取得していましたが、v0.7.xからはsocket.idで取得できるようになりました。



以上でぇぇぇぇぇす。

2011年7月15日金曜日

node.jsで自作モジュールの作り方

どうも、俺@昼ごはんは鯛の刺身を食べました。

さて、nodeでモジュールを作る方法についてメモメモです。
nodeは本日v0.5.1がリリースされたとこですね。

nodeで言う「モジュール」というのはjavaやphpなどでいう「クラス」みたいなものです。
でも実態はjavascriptなので、中身は関数群というか関数オブジェクトのかたまりですね。
参考)http://nodejs.org/docs/v0.5.1/api/modules.html#modules
commonsJSの仕様にのっとって利用します。

利用するフレームワークはexpressとします。
サンプルとしてよくある人間クラス(Person)を作ります。
hello()メソッドで"hello!"と、myName()メソッドで自分の名前を出力します。
Person.js
var Person = function(name) {
  this.name = name;
  this.hello = function() {
    console.log("hello");
  };
  this.myName = function() {
    console.log(this.name);
  };
};
module.exports = Person;
module.exportsは、モジュール全体を関数化(オブジェクト化)する時に利用します。
ちなみにjavascriptのprototypeを使うパターンでも同じです。
var Person = function(name) {
  this.name = name;
};
Person.prototype.hello = function() {
  console.log("hello");
};
Person.prototype.myName = function() {
  console.log(this.name);
};
module.exports = Person;

app.js
var Person = require("/path/to/Person");
var p = new Person("koexuka");
p.hello();  // "hello!"
p.myName();  // "koexuka"
です。


またはもう一つやり方があり
Person.js
exports.setName = function(name) {
  this.name = name;
};
exports.hello = function() {
  console.log("hello!");
};
exports.myName = function() {
  console.log(this.name);
};

app.js
var p = require("/path/to/Person");
p.setName("koexuka");
p.hello();  // "hello!"
p.myName();  // "koexuka"
です。
こちらの方が少し簡略ですね。


以上でぇぇぇえぇぇぇぇす。

2011年7月14日木曜日

使いどころが分からないUnixコマンド

どうも、俺@仕事中です。

今日はどういう使い方をしたら良いか分からないUnixコマンドの紹介です。
$ talk username
talkコマンド。
同サーバにログインしているusernameとチャットをすることができます。
ちなみに別ホストにいるユーザに対しては
$ talk username@ホスト名
です。
チャットを終了する場合は<Ctrl>+dです。
ただしtalkdデーモンが起動している必要があります。これまたマニアックなデーモンですね。
今時、便利なメッセンジャーアプリが多くありますし、電話もありますし。。
全ての通信手段が利用不可になり、サーバ上でやり取りをするしかない場合は使えるかもしれません。


続いて
$ time cmd
timeコマンド。cmdは実行コマンドです。
引数に指定したコマンドの開始~終了までの実行時間を測定します。
どんなベンチマークで使うのでしょう。。



以上でぇぇぇぇぇす。