vimperatorからKeySnailへの移行

やろうやろうとおもっていたけど特に不便でもなかったのでやってなかったvimperatorからKeySnailへの移行を果たしました。

まじでEmacs使っている人ならKeySnailおすすめです。

とりあえずVimpと比較して嬉しかったところは、以下のとおりです。

  • Emacsキーバインドがテキスト編集時にフル活用できる。
  • Anythingっぽい絞り込み機能がある。
  • Yankが使える。
  • Pluginマネージャがよく出来ていて、更新が非常に楽!
  • 現在設定されているキーバインドが一覧化できる。

移行してまだ2日ぐらいですが、おそらくもうVimpには戻れない体になっています。

というわけで移行時にやったことをめも。

KeySnailのインストール

http://wiki.github.com/mooz/keysnail/keysnail-japaneseからxpiをダウンロードしてFirefoxにドラッグドロップでインストールします。
インストールが終わったら、上部メニューの
ツール→KeySanil→設定ファイルを作成
から新規で設定ファイルを作ります。

Pluginのインストール

プラグインは以下のページにまとめられています。
http://wiki.github.com/mooz/keysnail/plugin
自分が使っているPluginは以下の通り、

  • bmany
    • ブックマークをanythingっぽく操作できる。
  • Builtin command as Ext
    • M-xが使えるようになる
  • github プラグインヘルパー
  • HoK
    • リンクをキーボードから開ける
  • サイトローカル・キーマップ
    • GoogleReaderとかのサイトで一時的にキーマップを無効化できる。
  • Tanything
    • タブをanythingっぽく操作できる。
  • Yet Another Twitter Client KeySnail
    • TwitterClient

Pluginの設定

以下からPluginの説明と使い方を見ることができます。
ツール→KeySnail→プラグインマネージャを開く

だからプラグインマネージャの説明からコピペしたらOKです。
あと以下のtipsページで気になるものがあれば追加します。
(私はSuggestSearchを追加しました。)
http://wiki.github.com/mooz/keysnail/tips-japanese

とりあえず設定を変更したところを載せてみる。

//{{%PRESERVE%
//bookmarkを開くときは新規タブで開く
//http://d.hatena.ne.jp/mooz/20091213/p1
plugins.options["bmany.default_open_type"] = "tab";

//LocalKeymapの設定
var local = {};
plugins.options["site_local_keymap.local_keymap"] = local;

function fake(k, i) function () { key.feed(k, i); };
function pass(k, i) [k, fake(k, i)];
function ignore(k, i) [k, null];

local["^http://www.google.(co.jp|com)/reader/view/"] = [
    ["j", null],
    ["k", null],
    ["v", null]
];

//tanythinの設定
plugins.options["tanything_opt.keymap"] = {
    "C-z"   : "prompt-toggle-edit-mode",
    "SPC"   : "prompt-next-page",
    "b"     : "prompt-previous-page",
    "j"     : "prompt-next-completion",
    "k"     : "prompt-previous-completion",
    "g"     : "prompt-beginning-of-candidates",
    "G"     : "prompt-end-of-candidates",
    "D"     : "prompt-cancel",
    // Tanything specific actions
    "O"     : "localOpen",
    "q"     : "localClose",
    "p"     : "localLeftclose",
    "n"     : "localRightclose",
    "a"     : "localAllclose",
    "d"     : "localDomainclose",
    "c"     : "localClipUT",
    "C"     : "localClipU",
    "e"     : "localMovetoend"
};
//}}%PRESERVE%

//最初から定義されているキーマップを変更

key.setViewKey('C-f', function () {
    getBrowser().mTabContainer.advanceSelectedTab(1, true);
}, 'ひとつ右のタブへ', false);

key.setViewKey('C-b', function () {
    getBrowser().mTabContainer.advanceSelectedTab(-1, true);
}, 'ひとつ左のタブへ', false);

key.setViewKey('r', function () {
    BrowserReload();
}, '更新', true);

key.setViewKey('h', function () {
    BrowserBack();
}, '戻る', false);

key.setViewKey('l', function () {
    BrowserForward();
}, '進む', false);

//スクロールの幅を変更
key.setViewKey([["C-n"], ["j"]], function (aEvent) {
   for (var i = 0; i < 5; i ++){
    key.generateKey(aEvent.originalTarget, KeyEvent.DOM_VK_DOWN, true);
   }
}, '一行スクロールダウン', false);


key.setViewKey([["C-p"], ["k"]], function (aEvent) {
   for (var i = 0; i < 5; i ++){
    key.generateKey(aEvent.originalTarget, KeyEvent.DOM_VK_UP, true);
   }
}, '一行スクロールアップ', false);



//.keysnail.jsの末尾
//追加
//suggestSearch
key.setViewKey('s', function (ev, arg) {
                   let engines = util.suggest.getEngines();

                   // If you want to use all available suggest engines,
                   // change suggestEngines value to util.suggest.filterEngines(engines);

                   let suggestEngines = [util.suggest.ss.getEngineByName("Google")];
                   let collection = engines.map(
                       function (engine) [(engine.iconURI || {spec:""}).spec, engine.name, engine.description]
                   );

                   prompt.selector(
                       {
                           message : "engine:",
                           collection : collection,
                           flags : [ICON | IGNORE, 0, 0],
                           header : ["Name", "Description"],
                           keymap : {
                               "s" : "prompt-decide",
                               "j" : "prompt-next-completion",
                               "k" : "prompt-previous-completion"
                           },
                           callback : function (i) {
                               if (i >= 0)
                                 util.suggest.searchWithSuggest(engines[i], suggestEngines, "tab");
                           }
                       });
               }, "Search With Suggest", true);


//tab
key.setViewKey("t", function (ev, arg) {
                   ext.exec("tanything", arg);
               }, "タブを一覧表示", true);


//hit a hint
key.setViewKey('f', function (aEvent, aArg) {
    ext.exec("hok-start-background-mode", aArg);
}, 'リンクをバックグラウンドで開く Hit a Hint を開始', true);

//フォーカス操作
key.setGlobalKey(['C-c', 'b'], function (ev, arg) {
    let elem = document.commandDispatcher.focusedElement;
    if (elem) elem.blur();

    gBrowser.focus();
    _content.focus();
}, 'コンテンツにフォーカス', true);


//C-gを強化
hook.setHook('KeyBoardQuit', function (aEvent) {
    // キーシーケンス入力中なら無視
    if (key.currentKeySequence.length)
        return;

    // 検索バーを閉じる
    command.closeFindBar();

    if (util.isCaretEnabled())
    {
        let marked = aEvent.originalTarget.ksMarked;
        let type = typeof marked;
        if (type === "number" || type === "boolean" && marked)
        {
            // マークされてるときは、マークの解除だけ
            command.resetMark(aEvent);
        }
        else
        {
            // それ以外はフォーカスをコンテンツへ
            let elem = document.commandDispatcher.focusedElement;
            if (elem) elem.blur();
            gBrowser.focus();
            _content.focus();
        }
    }
    else
    {
        // テキスト編集してなければ選択の解除だけ
        goDoCommand("cmd_selectNone");
    }

    // ブラウザ画面なら ESC キーイベントも投げておく
    if (KeySnail.windowType == "navigator:browser")
        key.generateKey(aEvent.originalTarget, KeyEvent.DOM_VK_ESCAPE, true);
});
key.setViewKey("d", function (ev) {
    BrowserCloseTabOrWindow();
}, 'タブ / ウィンドウを閉じる', false);

//標準のコマンドが聞かないので代替(たぶん自分の環境のせい?)http://gist.github.com/287576
key.setGlobalKey(["C-x", "k"], function (ev) {
    BrowserCloseTabOrWindow();
}, 'タブ / ウィンドウを閉じる', false);

key.setGlobalKey(["C-c", "u"], function (ev) {
    undoCloseTab();
}, '閉じたタブを元に戻す', false);

key.setGlobalKey(["C-x", "C-c"], function (ev) {
    goQuitApplication();
}, 'Firefox を終了', true);


//bookmark http://d.hatena.ne.jp/mooz/20091213/p1
key.setViewKey([':', 'b'], function (ev, arg) {
    ext.exec("bmany-list-all-bookmarks", arg, ev);
}, "bmany - ブックマークを一覧表示");

key.setViewKey([':', 'B'], function (ev, arg) {
    ext.exec("bmany-list-bookmarklets", arg, ev);
}, "bmany - ブックマークレットを一覧表示");

key.setViewKey([':', 'k'], function (ev, arg) {
    ext.exec("bmany-list-bookmarks-with-keyword", arg, ev);
}, "bmany - キーワード付きブックマークを一覧表示");


key.setViewKey('g', function (aEvent) {
  getBrowser().selectedTab = getBrowser().addTab("http://google.co.jp/reader/view/");
}, 'GoogleReaderを開く');

objective-cのキー値コーディングでvalueにBOOLを使う方法

objective-cのキー値コーディングでBOOLをやり取りする方法がわからなくて少しはまったのでメモ。(iPhoneのuserDefaultの方法を使えると思い込んでた。。。)

そもそもsetValue forKeyでつかうvalueはid型。つまりオブジェクトじゃなきゃいけないけどBOOLはプリミティブ型なのでそのままじゃ出し入れできない。

そこでつまったんですが以下の方法でできました。わかってしまえば当たり前ですね。

//id paramsのプロパティhogeにBOOL(YES)を設定
[params setValue:[NSNumber numberWithBool:YES] forKey:@"hoge"];

//id paramsのプロパティhogeからBOOLを取得
NSNumber *i = (NSNumber *)[params valueForKey:@"hoge"];
BOOL b = [i boolValue];

BOOLはC言語のtrue,falseのエイリアスなので、0ならNO,0以外ならYESなのでNSNumberオブジェクトに変換してやり取りすればOKです。

mongoDBをrubyからmongo使う(mongo-acriverecord-ruby)

mongo-acriverecord-rubyを使うと、mongoDBでactiverecordチックにアクセスできる。
http://github.com/mongodb/mongo-activerecord-ruby:mongo-activerecord-ruby

本当のactiverecordから使うならhttp://github.com/mongodb/activerecord-mongo-adapter:activerecord-mongo-adapterがいいみたいです。

せっかくのドキュメント指向なのにRDB風に使うのはどうなの?とか思いますが。

インストール

前提としてhttp://d.hatena.ne.jp/amacou/20091205/1260035177:昨日の作業はやっていて、デーモンも上がっている状態です。

gemcutterすでにインストールしてるなら以下は省略。

$ sudo gem install gemcutter
$ sudo gem tumble

でインストール

$ sudo gem install mongo_record

使ってみる

では、ありがちなblogっぽいDBの操作をやってみます。
まずはPostクラスを作ります。

#post.rb
require "mongo"
require "mongo_record"
require File.join(File.dirname(__FILE__), 'comment')

class Post < MongoRecord::Base
  collection_name :posts
  fields :title, :content
  has_many :comments, :class_name => "Comment"

  def to_s
    "title: #{self.title} content: #{self.content}"
  end

end

つぎにCommentクラスを作ります。

#comment.rb
require "mongo"
require "mongo_record"

class Comment < MongoRecord::Base
  collection_name :comments
  fields :name, :content

  belongs_to :post
  def to_s
    "name: #{self.name}, content: #{self.content}"
  end
end

上記を使うMainファイルを作ります。

#blog.rb
# -*- coding: utf-8 -*-
require "mongo"
require "mongo_record"
require File.join(File.dirname(__FILE__), 'post')
require File.join(File.dirname(__FILE__), 'comment')

MongoRecord::Base.connection = Mongo::Connection.new.db('blog')

#とりあえず空にしとく
Post.destroy_all
Comment.destroy_all

def show
  puts ""
  puts "=" * 50
  Post.find(:all).each do |pos|
    puts "日記"
    puts "  #{pos}"
    pos.comments.each do |com|
      puts "   コメント"
      puts "     #{com}"
    end
  end
  puts "=" * 50
  puts ""
end


puts "日記をつける"

post = Post.new(:title => "うんこ", :content => "きょうはおおきなうんこがでた" )
post.save

show

puts "コメントをつける(belogs_to を利用)"
comment = Comment.new(:name => "通りすがりさん", :content => "わたしもおおきなうんこでした", :post => post)
comment.save


show

puts "コメントをつける2( << を利用)"
comment2 = Comment.create(:name => "通りすがりさん", :content => "わたしはコロコロのうんこでした")
post.comments << comment2
post.save

show

puts "自作自演日記をつける"
comment3 = Comment.create(:name => "自作自演さん", :content => "まだだしちゃだめ")
post2 = Post.new(:title => "うんこ", :content => "でそう", :date => Date.new, :comments => comment )
post2.save

show

で実行

$ ruby blog.rb
日記をつける

==================================================
日記
  title: うんこ content: きょうはおおきなうんこがでた
==================================================

コメントをつける(belogs_to を利用)

==================================================
日記
  title: うんこ content: きょうはおおきなうんこがでた
==================================================

コメントをつける2( << を利用)

==================================================
日記
  title: うんこ content: きょうはおおきなうんこがでた
   コメント
     name: 通りすがりさん, content: わたしはコロコロのうんこでした
==================================================

自作自演日記をつける

==================================================
日記
  title: うんこ content: きょうはおおきなうんこがでた
   コメント
     name: 通りすがりさん, content: わたしはコロコロのうんこでした
日記
  title: うんこ content: でそう
   コメント
     name: 通りすがりさん, content: わたしもおおきなうんこでした
==================================================

ソース見てみたら、belongs_toはまだ実装されていないみたいです。
でもhas_manyとか関連はちゃんと動いています。

実データはどうなっているのか確認。
mongoコマンドでインタラクティブにDBを操作できます。

$ mongo 
MongoDB shell version: 1.1.4
url: test
connecting to: test
type "help" for help
> use blog
switched to db blog
> show collections
comments
posts
system.indexes
> db.posts.find()
{ "_id" : ObjectId("4b1bcc000b965d203b000001"), "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "comments" : [ { "$ref" : "comments", "$id" : ObjectId("4b1bcc000b965d203b000003") } ], "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "title" : "うんこ", "updated_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "_ns" : "posts", "updated_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "content" : "きょうはおおきなうんこがでた" }
{ "_id" : ObjectId("4b1bcc000b965d203b000005"), "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "comments" : [ { "$ref" : "comments", "$id" : ObjectId("4b1bcc000b965d203b000002") } ], "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "title" : "うんこ", "updated_at" : null, "_ns" : "posts", "updated_on" : null, "date" : /(?:)/, "content" : "でそう" }

commentsの中に配列で関連するcommentのIDを保存している。
ちなみにcommentsは以下のようになってました。

> db.comments.find()
{ "_id" : ObjectId("4b1bcc000b965d203b000002"), "name" : "通りすがりさん", "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "post" : { "$ref" : "posts", "$id" : ObjectId("4b1bcc000b965d203b000001") }, "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "_ns" : "comments", "content" : "わたしもおおきなうんこでした" }
{ "_id" : ObjectId("4b1bcc000b965d203b000003"), "name" : "通りすがりさん", "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "_ns" : "comments", "content" : "わたしはコロコロのうんこでした" }
{ "_id" : ObjectId("4b1bcc000b965d203b000004"), "name" : "自作自演さん", "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "_ns" : "comments", "content" : "まだだしちゃだめ" }

ドキュメント指向ってちゃんと勉強していないけど、上記のようなデータだと、postもcommentも同じコレクションにしちゃった方がいいのかな?

ちゃんとドキュメント指向を勉強してみたいです。
(参考になるサイトや参考書をご存知のかたは教えてください。)

mongoDBをmacにインストール

ドキュメント指向のDBってやつはどんな感じか知りたくてmongoDBを使ってみることにした。

http://www.mongodb.org/display/DOCS/Home:mongoDB

mongoDBの特徴は以下の通り

先に使ってみた感想を上げてみると、
一般的なRDBと比べてよかったところは

  • インストールらくちん
  • シンプル
  • 柔軟

短所(?)は

ということで、たぶん簡単なシステムだとmongoDBはかなり魅力的だとおもう。
あとオブジェクト指向アジャイル開発と相性が良さそう。

でもトランザクションとかがガッツリ必要なものは無理っぽい。

rack+sinatra+mongoDBとか素敵な組み合わせに見える

インストール方法

まずダウンロード
http://www.mongodb.org/display/DOCS/Downloads:ここからMac64bitの1.1.4をダウンロードもしくは

wget http://downloads.mongodb.org/osx/mongodb-osx-x86_64-1.1.4.tgz

そんで解凍

tar zxvf mongodb-osx-x86_64-1.1.4.tgz

配置

cd mongodb-osx-x86_64-1.1.4 
sudo cp bin/* /usr/local/bin/
sudo cp -r include/* /usr/local/include/
sudo cp lib/libmongoclient.a /usr/lib/

デーモンの起動

mkdir db
mongod --dbpath ~/db

これで使えるようにになったはず。

rubyからmongoDBを使ってみる

まずライブラリをインストール

sudo gem install gemcutter
sudo gem tumble
sudo gem install mongo
sudo gem install mongo_ext

そんでgithubにのってたコードを実行
http://github.com/mongodb/mongo-ruby-driver:mongo-ruby-driver

require 'rubygems'
require 'mongo'
include Mongo

#dbにコネクションはる
@db   = Connection.new.db('sample-db')

#コレクションをつくる(rdbでいうスキーマみたいなもんだと思う)
@coll = db.collection('test')

#コレクションの中身をとりあえず全削除
@coll.remove

#insert処理
3.times do |i|
  @coll.insert({'a' => i+1})
end

puts "There are #{@coll.count()} records. Here they are:"
@coll.find().each { |doc| puts doc.inspect }

そしたら

$ ruby test.rb
There are 3 records. Here they are:
{"_id"=>4b1a99c40b965d1e66000001, "a"=>1}
{"_id"=>4b1a99c40b965d1e66000002, "a"=>2}
{"_id"=>4b1a99c40b965d1e66000003, "a"=>3}

ってなった。かんたん。


ためしに

require 'rubygems'
require 'mongo'

include Mongo
@db   = Connection.new.db('sample-db')
@coll = @db.collection('test')

@coll.remove
3.times do |i|
   @coll.insert('a' => i + 1)
end
#ここを追加
@coll.insert('unko' => "hoge")

puts "There are #{@coll.count()} records. Here they are:"
@coll.find().each { |doc| puts doc.inspect }

ってやったら

$ ruby test.rb
There are 4 records. Here they are:
{"_id"=>4b1a9a440b965d1e6f000001, "a"=>1}
{"_id"=>4b1a9a440b965d1e6f000002, "a"=>2}
{"_id"=>4b1a9a440b965d1e6f000003, "a"=>3}
{"_id"=>4b1a9a440b965d1e6f000004, "unko"=>"hoge"}

ってなった。おもろい。

CocoaEmacsのコンパイルと設定

環境

ソースの取得とコンパイル

cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/sources/emacs co emacs
cd emacs
./configure --with-ns --without-x
make bootstrap
make install

nextstepのなかにEmacs.appができているのでそれを/Applicationsの中に移動

フォントとメタキーとかの設定

.emacsに以下を追加

;; for Emacs23
(when (>= emacs-major-version 23)
;;metaをコマンドに割り当てる
(setq ns-command-modifier (quote meta))
;;superをoptionに割り当てる
(setq ns-alternate-modifier (quote super))
;;システムにキーを渡さない
(setq mac-pass-control-to-system nil)
(setq mac-pass-command-to-system nil)
(setq mac-pass-option-to-system nil)
(define-key global-map [ns-drag-file] 'ns-find-file)

;;フォントの設定
;;英字Monaco日本語ヒラギノ丸ゴを使う
(setq fixed-width-use-QuickDraw-for-ascii t)
 (setq mac-allow-anti-aliasing t)
 (set-face-attribute 'default nil
                     :family "Monaco"
                     :height 120)
(set-fontset-font
  (frame-parameter nil 'font)
  'japanese-jisx0208
  '("Hiragino Maru Gothic Pro" . "iso10646-1"))
 (set-fontset-font
  (frame-parameter nil 'font)
  'japanese-jisx0212
  '("Hiragino Maru Gothic Pro" . "iso10646-1"))
 (set-fontset-font
  (frame-parameter nil 'font)
  'mule-unicode-0100-24ff
  '("Lucida Grande" . "iso10646-1"))
;;日本語と英語を2:1の大きさにするための設定
;;こだわりがなければコメントアウト
;;ここから
 (setq face-font-rescale-alist
       '(("^-apple-Hiragino_Maru_Gothic_Pro.*" . 1.2)
         (".*osaka-bold.*" . 1.2)
         (".*osaka-medium.*" . 1.2)
         (".*courier-bold-.*-mac-roman" . 1.0)
         (".*monaco cy-bold-.*-mac-cyrillic" . 0.9)
         (".*monaco-bold-.*-mac-roman" . 0.9)
         ("-cdac$" . 1.3)
         ))
;;ここまで
)

本、CD、DVD、ゲームなどのコレクションをWEBで管理するPabo-Tanaをリリースしました

Pabo-Tanaとは

Webで本やCDなどを管理するよくあるサービスです。

他のサービスと何が違うの?

管理のしやすさに特化しました。
例えば、

  1. 検索結果からワンクリックで登録可能
  2. ワンクリックで削除可能
  3. コメントや評価ができる
  4. アイテムを登録時に自動的に分類
  5. 分類ルールはカスタマイズ可能

ということが可能です。
また、登録したアイテムから新作がでたときに自動的にメールで通知します。

これから更新通知はTwitterと本ブログで行います。

もしよろしければお使いください

登録はこちらから
http://pabo-tana.net

Mysqlのレプリケーション設定メモ

環境

CentOS5
Mysql5

前提

マスターのDBはある程度稼働してデータがたまっている状態

マスター側

スレーブ用のユーザを作成
#mysql -u root -p 
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO repl@"%" IDENTIFIED BY 'パスワードを記述';
mysql> exit
/etc/my.cnfに設定を追加
(省略)
[mysqld]
#以下を追加
log-bin=/var/lib/mysql/mysqld-bin
server-id=1
(省略)
サーバをリスタート
# service mysqld restart
スナップショットを取得

コンソールを2つ開く
1つ目のコンソールでDBの更新を止める

# mysql -u root -p

mysql> FLUSH TABLES WITH READ LOCK;

2つ目のコンソールでデータをtarに固める

# cd /var/lib/mysql
# tar zcvf mysql_snap.tgz ./*

終わったらもう一度1つ目に戻ってバイナリログの位置情報をメモ

mysql> SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| mysqld-bin.000015 |      346 |              |                  | 
+-------------------+----------+--------------+------------------+

メモが終わったら止めていた更新を開始する

mysql> UNLOCK TABLES;

あとはさっき作ったスナップショットをsftpなどでスレーブ側に転送する。

でマスター側は終わり。

スレーブ側

mysqlを停止
# service mysqld stop
転送したスナップショットをmysqlのデータ置き場に解凍
# rm -rf /var/lib/mysql/* #いらないデータを消す(いるデータがある場合バックアップしとく
# cp mysql_snap.tgz /var/lib/mysql
# tar zxvf mysql_snap.tgz
# rm mysql_snap.tgz
# rm mysql-bin.*
/etc/my.cnfを編集
[mysqld]
#以下を追加もしくは変更
server-id=2
mysqlを起動
# service mysqld start
スレーブの設定
#mysql -u root -p
mysql> CHANGE MASTER TO
    -> MASTER_HOST = 'マスタのホスト名かIP',
    -> MASTER_USER = 'repl',
    -> MASTER_PASSWORD = 'さっき設定したパスワード',
    -> MASTER_LOG_FILE = 'mysql-bin.000015',#さっきメモしたバイナリログのファイル名
    -> MASTER_LOG_POS = 346; #さっきメモしたバイナリログのポジション
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G #スレーブがうまく動いているか確認、Slave_IO_Running: YesとSlave_SQL_Running: Yesがあれば一応安心だと思う
このままだとスレーブを再起動したときにlogにエラーが書かれるので起動ファイルを修正
# vi /etc/init.d/mysqld

(省略)
start(){
        touch "$errlogfile"
        chown mysql:mysql "$errlogfile" 
        chmod 0640 "$errlogfile"
        [ -x /sbin/restorecon ] && /sbin/restorecon "$errlogfile"
        if [ ! -d "$datadir/mysql" ] ; then
            action $"Initializing MySQL database: " /usr/bin/mysql_install_db
            ret=$?
            chown -R mysql:mysql "$datadir"
            if [ $ret -ne 0 ] ; then
                return $ret
            fi
        fi
        chown mysql:mysql "$datadir"
        chmod 0755 "$datadir"
        # Pass all the options determined above, to ensure consistent behavior.
        # In many cases mysqld_safe would arrive at the same conclusions anyway
        # but we need to be sure.
        /usr/bin/mysqld_safe   --datadir="$datadir" --socket="$socketfile" \
                --log-error="$errlogfile" --pid-file="$mypidfile" \
                --relay-log=/var/run/mysqld/mysqld-relay-bin \ #この一行を追加
                >/dev/null 2>&1 &
        ret=$?
mysqlを再起動
# service mysqld restart

一応ログをみてエラーが出てなかったら完成
参考http://www.irori.org/doc/mysql-rep.html