日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

ScalaのTestツールScalaTestを使ってみた。

みなさん、こんばんは。
昨日書いたこちらの記事同様Scala書くのが最近とても楽しいので、Scala関連の記事を書こうと思います。

ScalaでTestを書こうと思って、とりあえず出てきたScalaTestというものを試してみました。
SEO高そうですね

使ってみた感想としては、とりあえず全部これでいいんじゃね感です。

|∧∧
|・ω・`) 今回検証に使ったレポジトリも置いておきますね
|o旦o
|―u'
""""""""""""""""'""""""


tarata/scalatest-getting-started · GitHub


とりあえず環境を用意しましょう。

  • Scala 2.11.4
  • sbt 0.13.7

を利用します。
build.sbtに

libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.1" % "test"

と書いてテストツールの準備は終了です。

早いですね。こんな感じです。

https://github.com/tarata/scalatest-getting-started/blob/master/build.sbt

これでsbt testと打てばとりあえずインストールが走り、テストが実行されます。
今はなにもないので、no tests executedとかそれらしきことを言われるでしょう。

次に、以下のことを試してみました。

1. xUnit形式でassertionを行う
2. Property based testingをやってみる

1. テストの形式を選ぶ

ScalaTestではxUnitの形式やBDDっぽくSpecで書く形式などいくつか用意されているようです。
今回はxUnitっぽくやってみました。
xUnit形式の場合、FunSuiteというクラスを継承してTestクラスを作成します。
書いたコードが以下のURLです。

scalatest-getting-started/Calculator.scala at master · tarata/scalatest-getting-started · GitHub

感想としては

  • xUnitっぽく書けました。(当然
  • assert使える(当然
  • ShouldMatchersというtraitを使うと自然言語っぽく書けて( ・∀・)イイ!!

という感じです。
ShouldMatchersは使い勝手そこそこよかったので、使えるかと。
色んな書き方があるようです。
もうちょっと色々試してみようかなぁと思います。

参考:http://www.scalatest.org/user_guide/using_matchers
その他のテスト形式はこちらのブログが綺麗にまとまっていたように感じました。


2. Property based testingをやってみる

そもそもProperty based testingってなんだよ。
って思ったのでぐぐってみて、下記のページを参考にしました。

Abstractivate: Property-based testing: what is it?

タイトルがそのまんま気になってる内容ですねw

Property-based tests make statements about the output of your code based on the input, and these statements are verified for many different possible inputs.

A property-based testing framework runs the same test over and over with generated input

google 翻訳したら以下のようになりました。

プロパティベースのテストは、入力に基づいて、コードの出力についてのステートメントを作成し、これらの記述は、多くの異なる可能な入力に対して検証される。

プロパティベースのテストフレームワークでは、生成された入力に何度も同じテストを実行します

可能な入力を大量に与えて、同一のテストを何度も行うということでしょうか。
HaskellのQuickCheckというものにおける考え方(?)のようです。
そちらの方も後で調べてみようかなと思います。

今回ScalaTestのページに載っていた2種類を試してみました。

Table-driven property checks

前者のTable-driven property checksはDataProvider的な印象を受けました。
自前で用意した入力に対して、テストを行うためです。

書いたテスト
scalatest-getting-started/CalculatorWithTableDrivenPropertyBased.scala at master · tarata/scalatest-getting-started · GitHub

Table関数を利用して、引数として与えたいデータをタプル形式で作り、forAll関数に渡せば良いみたいです。

使った感想

  • データプロバイダーぽい
  • データプロバイダーに慣れてるせいか使いやすかった

Generator-driven property checks

こちらは自前のデータではなく、適当なデータを作成してそのデータセットを入力として、テストを行うということができるようです。

書いたテスト
scalatest-getting-started/CalculatorWithGeneratorDrivenPropertyBased.scala at master · tarata/scalatest-getting-started · GitHub

これを利用する場合、build.sbtに

libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.12.2" % "test"

を追記する必要があります。
もともとScalaCheckの機能のようですね。
HaskellのQuickCheckに対するものがScalaのScalaCheckなのでしょうか。

使った感想

  • 任意と言いつつ、完全なランダムではなさそう。
  • ⇒Test名に入力を含めた際にDuplicateTestNameExceptionが発生したため。
  • ⇒Int型を指定した際には0 , 1, -1, Int型の最大値・最小値とその他ちょっと大きめな値(どういう理由で選ばれたかわからない値)が指定されていたような印象
  • どのタイミングで使うのが良いのだろう。
  • ⇒テストは自分が気になる境界値に対して行うものだと思っているため、任意の入力をするというこのテスト用のデータセットをどのタイミングで使うかがわからない。

という感じでした。

まとめ

  • ScalaでテストするならとりあえずScalaTestを利用するのがよさそう
  • xUnitぽくもBDDぽくも書ける
  • データプロバイダー的なこともできる

やっぱ、sbtでテストできるのは楽ですね。

秘密鍵にパスワード設定してる状態で自動的にgit cloneしたいそんな時の対処方法

こんばんは。
今日はVagrantシェルスクリプトでアプリケーションの実行環境の作成してる時に困った話をします
環境作成にchefやpuppet, ansibleを使わずシェルスクリプトを使っているのですが、アプリケーションをgit cloneする時に

Are you sure you want to continue connecting (yes/no)?

とか

Enter passphrase for key '/path/to/key/private_key':

聞くなよやってるのはvagrantだy
などのプロンプトが出てきて、 vagrant up中にインストール出来ず嫌だなーと思ったので対処法を探しました。そしてたどり着いたのが、 expectコマンド

ということで、お試しにgit cloneを自動化してみました。
作ったレポジトリ

概要

expectコマンドを利用して、vagrant上に自分自身のレポジトリ tarata/expect-command-getting-started · GitHub をcloneしてきます。

準備

expectコマンドとgitをインストールします。

yum install -y expect git

やったこと

#! /bin/sh

password=`cat /vagrant/script/keys/password_for_private_key`
# パスワードはtextファイルに事前に書いておきます。
repo=git@github.com:tarata/expect-command-getting-started.git

expect_message_ssh="Are you sure you want to continue connecting (yes/no)?"
expect_message_key_password="Enter passphrase for key '/home/vagrant/.ssh/private_key_for_github': "
# 秘密鍵の設定は別で行っています。
# https://github.com/tarata/expect-command-getting-started/blob/master/script/install/vagrant/install-keys.sh


expect -c "
set timeout -1
spawn git clone $repo
expect \"${expect_message_ssh}\" {
    send \"yes\n\"
    expect \"${expect_message_key_password}\"
    send \"${password}\n\"
    expect \"${expect_message_key_password}\" {
        set timeout 1
    } \"*$\";
} \"${expect_message_key_password}\" {
    send \"${password}\n\"
    expect \"${expect_message_key_password}\" {
        set timeout 1
    } \"*$\";
}
"

if [ ! -d $HOME/`basename ${repo%.git}` ]; then
    echo "\n"
    echo "failed to git clone"
fi

主な部分はexpect -c 以降の部分です。

expect \"hogehoge\"

とやれば「hogehogeという文字が標準出力に出現したら」という意味になります。
{}を利用することで条件分岐が出来るようです。
条件分岐というとif文が出てきたのですが、イメージ的にはswitch文が近いかと思います。
なので、expectの部分をなんとなく、switchに直すと

git clone $repo
switch (標準出力) {
  case ssh時に出る出力(${expect_message_ssh})
    yes\nと打つ;
    switch(標準出力) {
      case パスワード入力(${expect_message_key_password}):
        [パスワード]\nと打つ;
        switch(標準出力) {
          case パスワード入力(${expect_message_key_password}):
            タイムアウトを1秒にする(パスワードが間違ってるため止める処理);
            break;
          default:
            break;
        }
        break;
      default:
        break;
  case パスワード入力(${expect_message_key_password}):
    [パスワード]\nと打つ;
    switch(標準出力) {
      case パスワード入力(${expect_message_key_password}):
        タイムアウトを1秒にする(パスワードが間違ってるため止める処理);
        break;
      default:
        break;
    }
}

みたいな対応かと・・・(わかりづらい・・・?w
という感じに事前に鍵の準備とパスワードをどこかに記載する必要は当然必要になりますが、プロンプトが出るようなものであったとしても自動化できます。

色々やって困ったこと

ctrl+cをしたいんだけど、どうやってsendすればよいの?

set timeout 1

です。
以下のページでpingを例にしている時に気が付きました。


expectの条件分岐を使ってるんだけど、なぜか2つ目の条件分岐に引っかからない

expect hoge {
  ...何らかの処理
} expect fuga { # expectがいらない

}

となっていた。
case文的な感じなので、expectはいらない。つまり

expect hoge {
  ...何らかの処理
} fuga {

}

みたいな感じです。
プロンプトも操れるようになったので、もうなんでも出来る気がします←
上にも書いちゃいましたが、こちらが今回作ったレポジトリです。
tarata/expect-command-getting-started · GitHub

vagrant upで一応動きは確認できます。
/path/to/project/script/keys/private_key_for_github
githubに登録した秘密鍵を置き、

/path/to/project/script/keys/password_for_private_key
にその秘密鍵のパスワードを記載し、

/path/to/project/script/install/vagrant/install-application.sh
repo変数のレポジトリを変更すれば試せるかと思います。

鍵のパスワードが無くても動く・・・はずw

追記

ssh-agentとssh_configで色々出来るよねと突っ込まれたので、メモとして書いておきます

expect_message_ssh="Are you sure you want to continue connecting (yes/no)?"
expect_message_key_password="Enter passphrase for key '/home/vagrant/.ssh/private_key_for_github':  

この部分を他の方法でどうにかできます。
前者はssh_config
後者はssh-agent

Are you sure you want to continue connecting (yes/no)? の対処

今、ssh_configは /home/vagrant/.ssh/config に書いていて、以下のようになってますが、

Host github.com
    User git
    Port 22
    Hostname github.com
    IdentityFile ~/.ssh/private_key_for_github
    TCPKeepAlive yes
    IdentitiesOnly yes

StrictHostKeyChecking noを追記すれば Are you sure you want to continue connecting (yes/no)? は尋ねられなくなります。

Enter passphrase for key '/home/vagrant/... の対処

こっちはssh-agent、または、forward-agent機能(?)によって、上手くやれそうです(できてない)
思いついたやり方は2つ

  • ゲストOS(VM)でssh-agentを実行し、ssh-addでgithub用の秘密鍵を登録する。
  • ホストOS(VMではない本体)でssh-addを行いforward-agentによって、秘密鍵をゲストOSと共有する

このいずれかの設定ができれば、git push時などにも秘密鍵のパスワードを入力しなくていいので便利です。


2つのやり方のうち前者であれば、ゲストOSで完結するのでMacWindowsに依らない点がメリットです
(なんだけど出来ない(´・ω・`)w
後者はホストOSで設定している鍵を利用できるので、ゲスト側で設定する必要が無いという点がメリットかなぁと思います。


ちなみに、Vagrantの場合Vagrantfileに以下を設定すればforward-agentの設定が出来るようです。

config.ssh.forward_agent = true

参考
ssh-agentを使ってVagrant上のゲストOSからMac側の秘密鍵を使えるようにする | Firegoby

サーバの監視用にxymonを試してみる。

みなさん、こんにちは。
@tana_ra です。

この前VoyageGroupのSunriseというインターンに中の人として参加しました。
2年前参加した時、ゴミ未満でしたが、ある程度知識がついていてよかったです。
ただ、ある程度はわかってきたとはいえ、インフラ力が明らかに足りないので、
もっと勉強しようと思いました。

※ Sunrise

ところで、今仕事とは関係なく manavee 関連のサービスをたてようとしてるんですが、そこで何かが起きた時のために、とりあえず、サーバ監視方法を知ろうと思いました。
ということで、今回はxymonによるサーバ監視を試してみようと思います。
試してみようと思ったけど、まだサービスのサーバもできてないので、今回はインストールのみですw

※ manavee

Install

以下の内容を、install.shとして実行すればインストールされます

Vagrantで作ったVMのboxは tarata/xymon-getting-started · GitHub です。

Install Script

xymon_version='4.3.17'

# 必要なパッケージインストール
yum install -y make vim gcc pcre-devel rrdtool-devel libpng-devel openssl-devel openldap-devel wget fping httpd
if [ -f /usr/bin/fping ];then
    ln -s /usr/sbin/fping /usr/bin/fping
fi

# 監視対象のhttpd起動
chkconfig httpd on
service httpd start

# xymonユーザ作成
grep '^xymon:' /etc/passwd
if [ $? -ne 0 ]; then
    useradd xymon
fi

# xymonインストール
cd /tmp
if [ ! -f /tmp/xymon-${xymon_version}.tar.gz ];then
    wget http://sourceforge.net/projects/xymon/files/Xymon/${xymon_version}/xymon-${xymon_version}.tar.gz
    tar zxvf xymon-${xymon_version}.tar.gz
    cd xymon-${xymon_version}
    ./configure
    make
    make install
fi


# httpd用xymon設定ファイルコピー
if [ ! -f /etc/httpd/conf.d/xymon.conf ];then
    cp /home/xymon/server/etc/xymon-apache.conf /etc/httpd/conf.d/xymon.conf
    service httpd reload
fi

# xymon Service起動スクリプトの作成(sedコマンドによりPATHを変更)
sed -e "s/DAEMON=\/usr\/lib\/xymon\/server\/bin\/xymon.sh/DAEMON=\/home\/xymon\/server\/bin\/xymon.sh/g" /tmp/xymon-${xymon_version}/rpm/xymon-init.d > /etc/init.d/xymon
chmod +x /etc/init.d/xymon

if [ ! -f /etc/logrotate.d/xymon ];then
    cp /tmp/xymon-${xymon_version}/rpm/xymon.logrotate /etc/logrotate.d/xymon
fi

# xymon Service起動
chmod 701 /home/xymon
chkconfig xymon on
service xymon restart

これでインストールが完了します。
この後、 http://{serverのip address}/xymon/xymon.html にアクセスすれば以下の様な画面が見れます。

f:id:arata3da4:20141128125616p:plain

き・・・きいろい・・・けど気にしません。

ほとんどXymonインストールに書いてあったことをまんまやっただけですw

対応はこんな感じです。

必要なパッケージの導入

# 必要なパッケージインストール
yum install -y make vim gcc pcre-devel rrdtool-devel libpng-devel openssl-devel openldap-devel wget fping httpd
if [ -f /usr/bin/fping ];then
    ln -s /usr/sbin/fping /usr/bin/fping
fi

Xymon本体のインストール

# xymonユーザ作成
grep '^xymon:' /etc/passwd
if [ $? -ne 0 ]; then
    useradd xymon
fi

# xymonインストール
cd /tmp
if [ ! -f /tmp/xymon-${xymon_version}.tar.gz ];then
    wget http://sourceforge.net/projects/xymon/files/Xymon/${xymon_version}/xymon-${xymon_version}.tar.gz
    tar zxvf xymon-${xymon_version}.tar.gz
    cd xymon-${xymon_version}
    ./configure
    make
    make install
fi

サービス起動前の下準備

# httpd用xymon設定ファイルコピー
if [ ! -f /etc/httpd/conf.d/xymon.conf ];then
    cp /home/xymon/server/etc/xymon-apache.conf /etc/httpd/conf.d/xymon.conf
    service httpd reload
fi

# xymon Service起動スクリプトの作成(sedコマンドによりPATHを変更)
sed -e "s/DAEMON=\/usr\/lib\/xymon\/server\/bin\/xymon.sh/DAEMON=\/home\/xymon\/server\/bin\/xymon.sh/g" /tmp/xymon-${xymon_version}/rpm/xymon-init.d > /etc/init.d/xymon
chmod +x /etc/init.d/xymon

if [ ! -f /etc/logrotate.d/xymon ];then
    cp /tmp/xymon-${xymon_version}/rpm/xymon.logrotate /etc/logrotate.d/xymon
fi

# xymon Service起動
chmod 701 /home/xymon
chkconfig xymon on
service xymon restart

サービスの方が進んできたら コンフィグファイルについて の方もやってみようかなと思います。

MongoDBのInitial Syncを試してみた。

みなさんこんばんは。
遂に同期とリレーブログを始めることにしました。
酒呑みたちのリレーブログ - はてなブログ グループ

酒呑みたちのリレーブログというわりとひどいタイトルにしたのに誰も文句言いいませんでした。
みんな自覚しているようです。

さて、今回なにしようかなと思ったんですが、仕事でMongoDBを使っているので、それ関連にしようと思いました。

とある理由により、MongoDBでよくInitial Syncをすることが多いんですが、
Tutorialをしっかり読んだことなかったので、それを読みつつ実際に行ってみようと思いました。

前提(MongoDBのレプリケーションについて)

前提として、MongoDBのレプリケーションはPrimaryのlocal データベースのoplogというコレクションに変更に関する情報を持たせて、それをSecondary達が読みに行き、同期を行うといった方法で行っています。
レプリケーションが済んだ状態で、以下の様なコマンドを実行すると見れるはずです。

$ mongo
MongoDB shell version: 2.6.5
connecting to: test
repltry:PRIMARY> use local
switched to db local
repltry:PRIMARY> db.oplog.rs.find()

MongoDBのtutorialを読んでみる。

ここから引用して、自分なりに訳してみました。
Resync a Member of a Replica Set — MongoDB Manual 2.6.4


引用

A replica set member becomes “stale” when its replication process falls so far behind that the primary overwrites oplog entries the member has not yet replicated.
The member cannot catch up and becomes “stale.”
When this occurs, you must completely resynchronize the member by removing its data and performing an initial sync.

  • レプリケーションが遅れ、レプリカセットのあるメンバーがまだ追いついていないoplogをprimary機が上書きしてしまうことでレプリケーションに失敗した際、そのあるレプリカセットは "stale" 状態になる。
  • そのメンバーは(primaryの変更を)キャッチアップ出来ず、"stale"状態となる。
  • それが起きてしまった際には、全データを削除しInitial Syncを実行することによる、完全な再同期が必要となる。

引用

MongoDB provides two options for performing an initial sync:

・Restart the mongod with an empty data directory and let MongoDB’s normal initial syncing feature restore the data.
 This is the more simple option but may take longer to replace the data.
 See Procedures.
・Restart the machine with a copy of a recent data directory from another member in the replica set.
 This procedure can replace the data more quickly but requires more manual steps.
 See Sync by Copying Data Files from Another Member.

  • MongoDBのInitla Syncには2つの方法があります。

1. データを保存しているディレクトリを空の状態でmongodを再起動し、MongoDBによる通常のInitial Sync機能によってデータを復帰させます。
 これは他方より簡単ですが、少し時間がかかるでしょう。
2. レプリカセット内の他メンバーから、最新のデータディレクトリをコピーし、サーバを再起動します。
 これは他方より早いですが、手動のステップが必要になります。


...だそうです。

つまり、MongoDBのレプリケーションでは、Primary機の oplog はある程度書き込まれると、はじめから上書きで書きなおされてしまうため、それに追いつけなかったSecondary機は"stale"状態になるんですね。
そんな時にInitial Syncが必要になるということですね。

(staleってなんだろう・・・)
staleの意味 - 英和辞典 Weblio辞書


実践Initial Sync

2つの方法があるようでしたが、今回は楽めな方を試してみようと思います。
つまり、 Procedures のほうを試します。

MongoDBのレプリケーションは以前やったことがあるので、それを利用します。

よかったら記事も・・・w

MongoDBでレプリカセットを試してみた。 - 日頃の行い

利用したレポジトリはこちらです。
tarata/mongo-replication-try · GitHub

Install

$ vagrant up
[vagrant@localhost ~]$ vagrant ssh web1
[vagrant@localhost ~]$ sh /vagrant/script/master-setup.sh

で準備完了のはずですw

ここからの流れは

1. ダミーデータを突っ込む。
2. 一度同期させる。
3. SecondaryのInitial Sync

です。

ダミーデータを突っ込む。

ダミーデータどうしようかなと思ったらMongoDBのページに有りましたw

Generate Test Data — MongoDB Manual 2.6.4

こいつを元に作ったシェルスクリプトさんを呼び出します。
Primary機で

$ sh /vagrant/script/mongo-dummydata.sh

で多分100,000件くらい突っ込まれますw

一度同期させる

待ちましょうw
終わったかどうかは以下のような方法で確認できます。

$ mongo
$ rs.status()
repltry:PRIMARY> rs.status()
{
	"set" : "repltry",
	"date" : ISODate("2014-10-12T08:57:02Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "192.168.56.101:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 8184,
			"optime" : Timestamp(1413096918, 284),  //ここと
			"optimeDate" : ISODate("2014-10-12T06:55:18Z"),
			"electionTime" : Timestamp(1413096243, 1),
			"electionDate" : ISODate("2014-10-12T06:44:03Z"),
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "192.168.56.102:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 7987,
			"optime" : Timestamp(1413096918, 284), // ここが一緒であれば終わってます。
			"optimeDate" : ISODate("2014-10-12T06:55:18Z"),
			"lastHeartbeat" : ISODate("2014-10-12T08:57:01Z"),
			"lastHeartbeatRecv" : ISODate("2014-10-12T08:57:00Z"),
			"pingMs" : 0,
			"syncingTo" : "192.168.56.101:27017"
		},
		{
			"_id" : 2,
			"name" : "192.168.56.103:27017",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 7987,
			"lastHeartbeat" : ISODate("2014-10-12T08:57:01Z"),
			"lastHeartbeatRecv" : ISODate("2014-10-12T08:57:01Z"),
			"pingMs" : 0
		}
	],
	"ok" : 1
}

SecondaryのInitial Sync

Tutorialを見ると、以下の様なことを行えば良いようです。

a. Stop the member’s mongod instance. To ensure a clean shutdown, use the db.shutdownServer() method from the mongo shell or on Linux systems, the mongod --shutdown option.

b. Delete all data and sub-directories from the member’s data directory. By removing the data dbPath, MongoDB will perform a complete resync. Consider making a backup first.

1. 正規方法でMongoを止める。
2. データディレクトリを削除する。

そして起動すればいいんですね。
やってみましょう。

repltry:SECONDARY> use admin
switched to db admin
repltry:SECONDARY> db.shutdownServer()
2014-10-12T09:20:18.817+0000 DBClientCursor::init call() failed
server should be down...
2014-10-12T09:20:18.818+0000 trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2014-10-12T09:20:18.819+0000 warning: Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2014-10-12T09:20:18.819+0000 reconnect 127.0.0.1:27017 (127.0.0.1) failed failed couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed
2014-10-12T09:20:18.836+0000 trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2014-10-12T09:20:18.839+0000 warning: Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2014-10-12T09:20:18.839+0000 reconnect 127.0.0.1:27017 (127.0.0.1) failed failed couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed

# そのころPrimaryでは...

repltry:PRIMARY> rs.status()
{
	"set" : "repltry",
	"date" : ISODate("2014-10-12T09:22:59Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "192.168.56.101:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 9741,
			"optime" : Timestamp(1413096918, 284),
			"optimeDate" : ISODate("2014-10-12T06:55:18Z"),
			"electionTime" : Timestamp(1413096243, 1),
			"electionDate" : ISODate("2014-10-12T06:44:03Z"),
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "192.168.56.102:27017",
			"health" : 0,
			"state" : 8,
			"stateStr" : "(not reachable/healthy)",
			"uptime" : 0,
			"optime" : Timestamp(1413096918, 284),
			"optimeDate" : ISODate("2014-10-12T06:55:18Z"),
			"lastHeartbeat" : ISODate("2014-10-12T09:22:59Z"),
			"lastHeartbeatRecv" : ISODate("2014-10-12T09:20:18Z"),
			"pingMs" : 0,
			"syncingTo" : "192.168.56.101:27017"
		},
		{
			"_id" : 2,
			"name" : "192.168.56.103:27017",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 9544,
			"lastHeartbeat" : ISODate("2014-10-12T09:22:59Z"),
			"lastHeartbeatRecv" : ISODate("2014-10-12T09:22:59Z"),
			"pingMs" : 0
		}
	],
	"ok" : 1
}

ちゃんと死んでますね。
ではデータを消しましょう。
データの場所は /etc/mongod.conf のdbpathに記述されています。

$cat /etc/mongod.conf
logpath=/var/log/mongodb/mongod.log

logappend=true

fork=true

dbpath=/var/lib/mongo

pidfilepath=/var/run/mongodb/mongod.pid
$ sudo rm -rf * /var/lib/mongo/*

これでおkかと。

では起動しましょう。

$ sudo service mongod start
$ mongo
repltry:STARTUP2>

STARTUP2となっていますね。
これでinitial syncが始まります。
Primaryの方で見てみると

repltry:PRIMARY> rs.status()
{
	"set" : "repltry",
	"date" : ISODate("2014-10-12T09:33:22Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "192.168.56.101:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 10364,
			"optime" : Timestamp(1413096918, 284),
			"optimeDate" : ISODate("2014-10-12T06:55:18Z"),
			"electionTime" : Timestamp(1413096243, 1),
			"electionDate" : ISODate("2014-10-12T06:44:03Z"),
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "192.168.56.102:27017",
			"health" : 1,
			"state" : 5,
			"stateStr" : "STARTUP2",
			"uptime" : 16,
			"optime" : Timestamp(0, 0),
			"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
			"lastHeartbeat" : ISODate("2014-10-12T09:33:20Z"),
			"lastHeartbeatRecv" : ISODate("2014-10-12T09:33:21Z"),
			"pingMs" : 12,
			"lastHeartbeatMessage" : "initial sync need a member to be primary or secondary to do our initial sync"
		},
		{
			"_id" : 2,
			"name" : "192.168.56.103:27017",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 10167,
			"lastHeartbeat" : ISODate("2014-10-12T09:33:21Z"),
			"lastHeartbeatRecv" : ISODate("2014-10-12T09:33:21Z"),
			"pingMs" : 0
		}
	],
	"ok" : 1
}
# 数秒後...
repltry:PRIMARY> rs.status()
{
	"set" : "repltry",
	"date" : ISODate("2014-10-12T09:34:01Z"),
	"myState" : 1,
	"members" : [
		{
			"_id" : 0,
			"name" : "192.168.56.101:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 10403,
			"optime" : Timestamp(1413096918, 284),
			"optimeDate" : ISODate("2014-10-12T06:55:18Z"),
			"electionTime" : Timestamp(1413096243, 1),
			"electionDate" : ISODate("2014-10-12T06:44:03Z"),
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "192.168.56.102:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 55,
			"optime" : Timestamp(1413096918, 284),
			"optimeDate" : ISODate("2014-10-12T06:55:18Z"),
			"lastHeartbeat" : ISODate("2014-10-12T09:34:00Z"),
			"lastHeartbeatRecv" : ISODate("2014-10-12T09:34:01Z"),
			"pingMs" : 0,
			"syncingTo" : "192.168.56.101:27017"
		},
		{
			"_id" : 2,
			"name" : "192.168.56.103:27017",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 10206,
			"lastHeartbeat" : ISODate("2014-10-12T09:33:59Z"),
			"lastHeartbeatRecv" : ISODate("2014-10-12T09:33:59Z"),
			"pingMs" : 1
		}
	],
	"ok" : 1
}

のようになっていました。
結構さくっと終わっちゃったので、早めにrs.status()を実行しないと見れません。
こんな感じでInitial Syncが出来るようです。
また色々と試してみようかなと思います。