akishin999の日記

調べた事などを書いて行きます。

RequestBin をインストールしてみる

発行された URL に対して送信された HTTP リクエストの内容を確認することが出来る Webサービス RequestBin ですが、ソースコードも MIT ライセンスで公開されている ようなので、今回は自前のサーバに立ててみました。
構築した環境は CentOS 6.5 x86_64 になります。

Python 2.7 のインストール

最初に CentOS 6 にデフォルトで入っていた Python 2.6.6 で試してみたのですが、インストールは出来たものの上手く動作してくれませんでした。
そのため、まずは Python 2.7 を入れるところから始めました。

まずはビルドに必要なライブラリをインストール。

# yum groupinstall -y "Development tools"
# yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel

必須ではないですが、ソースコードからインストールするので綺麗に消せるよう EPEL から paco も入れておきます。

# rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
# yum install -y http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
# yum install -y paco

2.7.6 をダウンロードして configure します。

# cd /usr/local/src
# wget http://www.python.org/ftp/python/2.7.6/Python-2.7.6.tgz
# tar xzf Python-2.7.6.tgz
# cd Python-2.7.6
# ./configure --prefix=/usr/local

SSL サポートを有効にするためここで一手間かけます。
まずはインストールされている OpenSSL の場所を確認。

# find / -name openssl
/usr/lib64/openssl
/usr/bin/openssl
/usr/include/openssl
/etc/pki/ca-trust/extracted/openssl

Setup ファイルを編集します。

# vi ./Modules/Setup

218 行目辺りからのコメントアウトを解除して、「SSL=/usr/local/ssl」のところを先ほど調べた OpenSSL インストールパス(/usr)に修正します。

218 SSL=/usr
219 _ssl _ssl.c \
220         -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
221         -L$(SSL)/lib -lssl -lcrypto

修正したら make して make altinstall します。
paco 経由で実行するのを忘れずに。

# make
# paco -D make altinstall

バージョンを確認します。

# python2.7 -V
Python 2.7.6

以下を実行してエラーが出なければ SSL サポートが有効になっています。

# python2.7 -c "import ssl"

setuptools をインストールしておきます。

# cd /usr/local/src
# wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
# python2.7 ez_setup.py
# easy_install-2.7 --version
setuptools 3.3

pip もインストールしておきます。

# easy_install-2.7 pip
# pip2.7 --version
pip 1.5.4 from /usr/local/lib/python2.7/site-packages/pip-1.5.4-py2.7.egg (python 2.7)

これで Python 2.7 環境の準備ができました。

RequestBin のインストール

libevent-devel が必要なのでインストールしておきます。

# yum install -y libevent-devel

/opt 以下に requestbin を clone し、pip で必要なライブラリをインストールします。

# cd /opt/
# git clone git://github.com/Runscope/requestbin.git
# cd requestbin/
# pip install -r requirements.txt

RequestBin はデフォルトではメモリ上にデータを保持しますが、今回は Redis を使うようにしたいと思います。
ここでは Redis インストール用に Remi リポジトリを追加しました。

# rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi
# yum install -y http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

リポジトリを追加したら Redis をインストールして起動しておきます。

# yum --enablerepo=remi install -y redis
# echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
# sysctl -p
# service redis start
# chkconfig redis on
# chkconfig --list redis
redis           0:off   1:off   2:on    3:on    4:on    5:on    6:off

RequestBin の設定ファイルを編集。

# vi requestbin/config.py

ROOT_URL の値を環境に合わせて修正します。

ROOT_URL = "http://192.0.2.1:4000"

STORAGE_BACKEND の値を RedisStorage を変更します。

STORAGE_BACKEND = "requestbin.storage.redis.RedisStorage"

これでインストール自体は完了ですが、起動・終了を簡単にするため、Supervisor で管理するようにしてみます。

Supervisor のインストール

easy_install コマンドから supervisor をインストールします。

# easy_install supervisor

設定ファイルを作成して編集。

# echo_supervisord_conf > /etc/supervisord.conf
# vi /etc/supervisord.conf

ファイル末尾に以下の追記します。

[include]
files = /etc/supervisord.d/*.conf

指定したディレクトリを実際に作成。

# mkdir /etc/supervisord.d

Supervisor 用の起動スクリプトを配置します。

# cd /usr/local/src/
# git clone git://github.com/Supervisor/initscripts.git
# cp initscripts/redhat-init-jkoppe /etc/init.d/supervisord
# cp initscripts/redhat-sysconfig-jkoppe /etc/sysconfig/supervisord
# chkconfig --add supervisord

このままだと supervisord コマンドのパスが若干異なるため上手く動かないので、起動スクリプトを修正します。

# vi /etc/init.d/supervisord

スクリプト内のコマンドのパスを以下のように修正します。

  • /usr/bin/supervisord を /usr/local/bin/supervisord に変更。
  • /usr/bin/supervisorctl を /usr/local/bin/supervisorctl に変更。

次に以下のファイルを編集します。

# vi /etc/sysconfig/supervisord

PIDFILE のパスを /etc/supervisord.conf の内容に合わせて以下のように修正します。

PIDFILE=/tmp/supervisord.pid

これで Supervisor 自体の準備はできたので、いよいよ RequestBin 用の設定ファイルを作成します。

# vi /etc/supervisord.d/requestbin.conf

以下のような内容にしました。

[program:requestbin]
directory=/opt/requestbin
command=/usr/local/bin/python2.7 web.py
user=requestbin
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/requestbin.log
stopasgroup=true

RequestBin の場合、「stopasgroup=true」が無いと上手くプロセスを終了できないようなので注意してください。
指定した起動用ユーザを作成。

# useradd -s /sbin/nologin -M requestbin

supervisord サービスを起動します。
自動的に requestbin も起動したことがわかります。

# service supervisord start
Starting supervisord:
requestbin                       STARTING

これでブラウザで対象サーバのポート 4000 番にアクセスすると RequestBin を使用することができます。

Nginx の設定

ここまででも問題なく使用できるのですが、毎回ポート番号を指定してアクセスするのも面倒なので、Nginx 経由でアクセスするようにしてみます。
まずは Nginx をインストール。

# yum install -y http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
# yum install -y nginx

設定ファイルを編集します。

# vi /etc/nginx/conf.d/default.conf

location / の設定を以下のように変更しました。

location / {
  proxy_pass         http://localhost:4000;
  proxy_redirect     off;

  proxy_set_header   Host              $host;
  proxy_set_header   X-Real-IP         $remote_addr;
  proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
  proxy_set_header   X-Forwarded-Proto $scheme;
}

Nginx を起動します。

# service nginx start

これでポート番号を指定しなくても RequestBin へアクセスできるようになります。

Webサービスとして公開されているし、Heroku を使うならもっと簡単に動かせるようですが、外部に公開されていない環境に自前で一つ立てておくと気軽に使えるのでそれはそれで便利なんじゃないかなー、と思います。

参考サイト

How to install Python 2.7 and Python 3.3 on CentOS 6 | Too Much Data
http://toomuchdata.com/2014/02/16/how-to-install-python-on-centos/

Codrspace - Run RequestBin locally to debug restful APIs by glenbot
http://codrspace.com/glenbot/run-requestbin-locally-to-debug-restful-apis/

GracefulExit - Running Flask App and Celery with Supervisor on Vagrant
http://papaeye.tumblr.com/post/76624602909/running-flask-app-and-celery-with-supervisor-on-vagrant

Ruby から Sentry を使う

前回インストールした Sentry に Ruby からイベントを登録してみます。
Ruby から Sentry を使うには、プロジェクトの設定画面の Ruby のところにも書いてあるように sentry-raven という gem を使います。

getsentry/raven-ruby
https://github.com/getsentry/raven-ruby

インストール

gem から入れる場合は以下。

# gem install sentry-raven --no-rdoc --no-ri

bundler から入れる場合は Gemfile を作成。

# bundle init
# vi Gemfile

以下を追記します。

gem "sentry-raven"

bundle install します。

# bundle install

Ruby から使う

以下のような Ruby コードを記述します。

require 'raven'

Raven.configure do |config|
  config.dsn = 'http://6e874f2d864c4925b2049069f5e8af86:04756c0af5154d69aee463018cef97c0@192.0.2.1/2'
end

Raven.capture do
  1 / 0
end

config.dsn には Sentry 上で [設定]-[APIキー] のところに表示されている値を使用します。

実行してみます。

 % ruby sentry01.rb 
I, [2014-03-23T17:08:18.060929 #10369]  INFO -- : ** [Raven] Raven 0.7.1 ready to catch errors
D, [2014-03-23T17:08:18.062539 #10369] DEBUG -- : ** [Raven] Sending event 18180a944cdd445799d8de694e7691e8 to Sentry
D, [2014-03-23T17:08:18.068214 #10369] DEBUG -- : ** [Raven] Raven HTTP Transport connecting to http://192.0.2.1
sentry-ex01.rb:8:in `/': divided by 0 (ZeroDivisionError)
    from sentry-ex01.rb:8:in `block in <main>'
    from /home/akishin/.anyenv/envs/rbenv/versions/2.0.0-p353/lib/ruby/gems/2.0.0/gems/sentry-raven-0.7.1/lib/raven.rb:89:in `call'
    from /home/akishin/.anyenv/envs/rbenv/versions/2.0.0-p353/lib/ruby/gems/2.0.0/gems/sentry-raven-0.7.1/lib/raven.rb:89:in `capture'
    from sentry-ex01.rb:7:in `<main>'

例外が発生しました。
Raven.capture に指定したブロックの内部で例外が発生すると自動的に Sentry に通知されます。

実行後に Sentry 上ストリームを見ると以下のようにエラーが通知されているはずです。

また、例外を自分で処理した上で通知を行いたい、という場合には capture_exception が使用できます。

begin
  raise ArgumentError.new("test")
rescue ArgumentError => e
  Raven.capture_exception(e)
end

例外ではない、任意のイベントを通知したい場合には capture_message を使用します。

Raven.capture_message("test event", {
  level: 'debug',
  logger: 'debug',
  extra: { foo: "123", bar: "abc" },
})

Rails から使う

Rails から使う場合は、まずは作成した Rails プロジェクトの Gemfile に sentry-raven を追記して bundle install します。
インストールすると以下の rake タスクが追加されます。

 % bundle exec rake -T | grep raven   
rake raven:test[dsn]                    # Send a test event to the remote Sentry server

このタスクに Sentry の画面で確認した dsn を指定することで Sentry の動作確認を行う事ができます。
実行して以下のような感じで event ID が取得できていれば Sentry サーバとの通信は成功しています。

 % bundle exec rake "raven:test[http://6e874f2d864c4925b2049069f5e8af86:04756c0af5154d69aee463018cef97c0@192.0.2.1/2]"
Client configuration:
-> server: http://192.0.2.1
-> project_id: 2
-> public_key: 6e874f2d864c4925b2049069f5e8af86
-> secret_key: 04756c0af5154d69aee463018cef97c0

Sending a test event:
-> event ID: e09165be7fb741a18ebe214139430c39

Done!

Sentry 画面のストリームからもこのテストイベントを確認することが出来ます。

テストが問題なければ、Rails から sentry-raven を使うための設定ファイルを作成します。

% vi config/initializers/raven.rb

以下のような内容を記述します。
Raven-Ruby はデフォルトでは development 環境の時にイベントの送信を行わないので、ここでは確認のため config.environments で対象に含めるよう設定しています。

Raven.configure do |config|
  config.dsn = 'http://6e874f2d864c4925b2049069f5e8af86:04756c0af5154d69aee463018cef97c0@192.0.2.1/2'
  config.environments = %w[ development ]
end

これで設定は完了です。
Rails で使う場合はこれだけで処理されなかった例外が全て Sentry へ通知されるようになります。
Controller 内などで適当に例外を投げてみれば Sentry へ通知される事が確認できると思います。

まとめ

エラー管理ツールについては実際に試してみるまでは「ログ見ればいいじゃん」などと思っていましたが、使ってみると本番環境でしか発生しなかったり、たまにしか発生しなかったりするようなエラーまでその発生箇所や発生頻度を一元管理することができるようになり、その有用性が理解できました。

また、Sentry ではエラーだけでなく、任意のイベントを管理する事もできるため、どの処理がどれくらい呼ばれているか、などといった事も簡単に調べる事ができるので、プロダクトの品質向上に一役買ってくれそうです。

ちなみに、他のサービスなどとの連携についてはプラグイン方式を取っているようです。
対応しているサービスは以下のページの [3rd Party Extensions] にまとまっています。

Plugins
https://sentry.readthedocs.org/en/latest/plugins/index.html

これらのサービスと連携させる事でより効果的に活用することができそうです。

Sentry をインストール

商用サービスもあるオープンソースのイベントログ収集ツール Sentry をインストールしてみたのでメモ。

getsentry/sentry
https://github.com/getsentry/sentry

AirbrakeオープンソースErrbit 辺りと同じ系統のサービスな感じです。

インストールした環境は CentOS 6.5 x86_64 です。

MySQL のインストール

まずは MySQL をインストール。
5.1 で試したら途中 sentry upgrade 実行時にエラーになったので、公式リポジトリから 5.6 を入れました。

yum リポジトリを追加してインストール。

# yum install -y http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
# yum install -y mysql-community-server mysql-community-devel

設定ファイルを変更。

# vi /etc/my.cnf

mysqld セクションに以下を追記します。

[mysqld]
character-set-server = utf8

mysqld を起動。

# service mysqld start

起動したら mysql_secure_installation を実行し root パスワードの設定などを行っておきます。

# mysql_secure_installation

mysql_secure_installation の実行が終わったら設定したパスワードでログインします。

# mysql -uroot -p

sentry 用の DB とユーザを作成します。
パスワード等は適宜変更して下さい。

mysql> CREATE DATABASE IF NOT EXISTS sentry DEFAULT CHARACTER SET utf8;
mysql> GRANT ALL PRIVILEGES ON sentry.* TO sentry@localhost IDENTIFIED BY 'sentry';
mysql> FLUSH PRIVILEGES;
mysql> exit

Sentry のインストール

setuptools をインストール。

# yum install -y python-devel python-setuptools

easy_install コマンドを使って Sentry をインストールします。

# easy_install -UZ sentry[mysql]

インストール完了までそれなりに時間がかかるので、しばらく待ちます。

インストールが完了したら、以下のコマンドを実行して設定ファイルを作成。

# sentry init /etc/sentry.conf.py

作成した設定ファイルを編集します。

# vi /etc/sentry.conf.py

以下の箇所を先ほど作成したデータベース接続情報に変更します。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'sentry',
        'USER': 'sentry',
        'PASSWORD': 'sentry',
        'HOST': 'localhost',
        'PORT': '3306'
    }
}

また、設定ファイル内の SENTRY_URL_PREFIX の値をインストールしたサーバのホスト名または IP アドレスに変更します。

#SENTRY_URL_PREFIX = 'http://sentry.example.com'  # No trailing slash!
SENTRY_URL_PREFIX = 'http://192.0.2.1'  # No trailing slash!

設定ファイルを保存したら DB のマイグレーションなどを実行する upgrade コマンドを作成した設定ファイルを指定して実行します。

# sentry --config=/etc/sentry.conf.py upgrade

createsuperuser サブコマンドを実行して管理用のユーザを作成します。

# sentry --config=/etc/sentry.conf.py createsuperuser

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! SENTRY_URL_PREFIX is not configured !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Username: akishin
Email address: akishin@example.com
Password:
Password (again):
Superuser created successfully.

これでインストールは完了です。
以下のコマンドでサーバを起動するとポート 9000 番で Sentry が起動します。

# sentry --config=/etc/sentry.conf.py start

軽く試すだけならこのままでも問題ないと思いますが、このままだと起動・終了が面倒なので、supervisord でプロセスを管理するよう設定します。
起動が確認できたら一旦 Ctrl-C などで sentry サーバを停止しておきます。

sentry を supervisor で管理する

以下のコマンドで supervisor をインストールします。

# easy_install supervisor

設定ファイルを作成。

# echo_supervisord_conf > /etc/supervisord.conf

作成した設定ファイルを編集します。

# vi /etc/supervisord.conf

ファイル末尾の以下の行をアンコメントし、ディレクトリパスを修正します。

[include]
files = /etc/supervisord.d/*.conf


設定ファイルで指定したディレクトリを作成。

# mkdir /etc/supervisord.d

supervisor 用の起動スクリプトを clone して設置します。

# cd /usr/local/src/
# git clone git://github.com/Supervisor/initscripts.git
# cp initscripts/redhat-init-jkoppe /etc/init.d/supervisord
# cp initscripts/redhat-sysconfig-jkoppe /etc/sysconfig/supervisord
# chkconfig --add supervisord

このままではデフォルトの設定ファイルと pid ファイルの場所が異なるので、以下を編集します。

# vi /etc/sysconfig/supervisord

ここでは /etc/supervisord.conf 側に合わせたので、以下のように変更しました。

#PIDFILE=/var/run/supervisord.pid
PIDFILE=/tmp/supervisord.pid

これで supervisor の準備は出来たので、Sentry 用の設定ファイルを作成します。

# vi /etc/supervisord.d/sentry.conf

以下のような内容にしました。

[program:sentry-web]
command=/usr/bin/sentry --config=/etc/sentry.conf.py start http
user=sentry
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/sentry-web.log

指定した起動用ユーザを作成します。

# useradd -s /sbin/nologin -M sentry

supervisord を起動します。

# service supervisord start
Starting supervisord:
sentry-web                       STARTING

これで supervisord 経由で sentory の起動・停止が出来るようになりました。

Nginx の設定

このままでは 9000 番ポートを指定してアクセスする必要があります。
80 番ポートでアクセスできるようにするため、Nginx 経由で Sentry にアクセスできるように設定します。

まずは Nginx をインストール。

# yum install -y http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
# yum install -y nginx

設定ファイルを編集します。

# vi /etc/nginx/conf.d/default.conf

location / の設定を以下のように変更しました。

location / {
  proxy_pass         http://localhost:9000;
  proxy_redirect     off;

  proxy_set_header   Host              $host;
  proxy_set_header   X-Real-IP         $remote_addr;
  proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
  proxy_set_header   X-Forwarded-Proto $scheme;
}

設定したら Nginx を起動します。

# service nginx start

以上で Sentry のインストールは完了です。

これでブラウザからポート 9000 を付けなくても Sentry にアクセス出来るようになります。
アクセスするとログイン画面が表示されるので、作成したユーザ情報でログインします。

ログインすると、初回ログインではチームの作成画面が表示されます。

チームを作成すると次はプロジェクト作成画面が表示されます。

プロジェクトを作成すると以下のような設定画面が表示されます。

商用サービスもあるだけあって大部分日本語化されているようです。
使い易そうですね。

ちょっと長くなったので、実際の使い方はまた次回にでもまとめたいと思います。

Packer で Vagrant の Box を作る

テンプレートを自分で作るのがどうにも面倒に感じてなかなか手を出せずにいた Packer ですが、調べてみたら結構テンプレートを公開してくれている方がいるようです。

misheska/basebox-packer
https://github.com/misheska/basebox-packer

shiguredo/packer-templates
https://github.com/shiguredo/packer-templates

hnakamur/my-packer-template-files
https://github.com/hnakamur/my-packer-template-files

nickchappell/packer-templates
https://github.com/nickchappell/packer-templates


という訳で今更ながら試してみました。
環境は Windows7 64bit です。

インストール

Downloads - Packer
http://www.packer.io/downloads.html

上記ページ内の [Windows] のところの [amd64] のリンクをクリックしてダウンロードします。
ダウンロードした際のバージョン 0.5.2 でした。

ダウンロードした 0.5.2_windows_amd64.zip を適当なフォルダに解凍し、フォルダを環境変数 PATH に追加します。
コマンドプロンプトから以下のようにバージョンが確認できればインストールは完了です。

>packer --version
Packer v0.5.2

Box の作成

まずは適当なフォルダに移動して、テンプレートを clone します。
ここでは以下のテンプレートを使用させて頂きました。

misheska/basebox-packer
https://github.com/misheska/basebox-packer

>git clone git://github.com/misheska/basebox-packer.git

CentOS 6.5 を入れてみます。
CentOS 用のテンプレートのあるフォルダまで移動します。

>cd basebox-packer\template\centos\

配布されているテンプレートでは言語設定やキーボードなどが US になっているので、以下のファイルを変更します。

  • basebox-packer\template\centos\http\ks.cfg

上記ファイルをエディタ等で開いて、以下の部分を変更しました。

lang ja_JP.UTF-8
keyboard jp106
timezone Asia/Tokyo

作成する Box のメモリやディスク容量などは以下のファイルで変更できます。

今回は以下のように変更しました。

・・・
"builders": [{
  "vm_name": "centos65",
  "type": "vmware-iso",
  ・・・
  "disk_size": 30420,
  "vmx_data": {
    "memsize": "1024",
    "numvcpus": "2",
    "cpuid.coresPerSocket": "1"
  }
},
{
  "vm_name": "centos65",
  "type": "virtualbox-iso",
  ・・・
  "disk_size": 30420,
  "vboxmanage": [
    ["modifyvm", "{{.Name}}", "--memory", "1024"],
    ["modifyvm", "{{.Name}}", "--cpus", "2"]
  ]
  ・・・

もし VirtualBox 用の box しか作成しない、というような場合は変更するのは「"type": "virtualbox-iso"」側の該当箇所だけで OK なはずです。

準備が出来たので Box を作成します。
VirtualBox 用の box だけ作成すればいいので、「-only=virtualbox-iso」オプション付きでビルドします。

>packer build -only=virtualbox-iso centos65.json

これでしばらく待つと「basebox-packer\virtualbox」フォルダの下に Box ファイルが作成されます。

ちなみに上記の「misheska/basebox-packer」にある centos510.json のテンプレートを使った場合、手元の環境では build 中に「Unknown command unsupported_hardware」エラーになってしまいました。
その場合、ks.cfg 内の「unsupported_hardware」の行をコメントアウトしてから再度実行したら上手く行ったので、参考までに。


公開されているテンプレートを使うとかなり簡単に Box が作成できていいですね。
ありがたく使わせて頂きたいと思います。

Ruby から Windows の共有フォルダにアクセスする

Linux 上で Samba マウントせずに Windows の共有フォルダにアクセスしたかったので、Ruby の sambal というライブラリを使ってみました。

johnae/sambal
https://github.com/johnae/sambal

試した環境は以下です。

  • CentOS 6.4 / 6.5(どちらも x86_64)
  • Ruby 2.0.0p247
  • bundler 1.5.3

Ruby が 2.0 なのは単に手元で 2.1 の RPM をまだ作成していないだけです^^;

インストール

sambal は smbclient コマンドのラッパーなので、動作には smbclient コマンドが必要になります。
smbclient は yum から samba-client コマンドを実行するとインストールできます。

# yum install -y samba-client

インストールしたら Windows の共有フォルダにアクセスできるかを確認。

$ smbclient //PC001/Share "shakiyamain" -U akishin -p 445

smb: \> というプロンプトが表示されていれば接続は成功です。
ls と打つと共有フォルダ内のファイルを確認する事が出来ます。
プロンプトは exit で抜ける事ができます。

smb: \> ls
  .                                   D        0  Tue Feb 18 22:43:37 2014
  ..                                  D        0  Tue Feb 18 22:43:37 2014
  test.txt                            A        0  Tue Feb 18 22:43:36 2014

                62499 blocks of size 16777216. 33957 blocks available
smb: \> exit

ちなみに WORKGROUP ではなくドメインに参加している場合は以下のような感じ。

$ smbclient //PC001.example.co.jp/Share "p@ssword" -W example.co.jp -U akishin -p 445

これで sambal を使う準備は整いました。
ここでは bundler でインストールするので、まずは Gemfile を作成します。

$ bundle init

実行したディレクトリ内に Gemfile が生成されるので編集します。

$ vi Gemfile

本来なら配布されている gem を使えばいいので「gem 'sambal'」と書けばいいのですが、試したところ CentOS では以下のようなエラーになってしまい上手く動きません。

$ bundle exec ruby sambal_example.rb
Failed to connect
Unknown Process Failed!! (exit): "exit"
/root/vendor/bundle/ruby/2.0.0/gems/sambal-0.1.2/lib/sambal.rb:70:in `exit'
/root/vendor/bundle/ruby/2.0.0/gems/sambal-0.1.2/lib/sambal.rb:70:in `initialize'
sambal_example.rb:9:in `new'
sambal_example.rb:9:in `<main>'

どうも smbclient コマンドのプロンプト文字列をパースしている正規表現が若干異なるようです。
仕方ないので取りあえず Fork してエラーにならないように修正したものを使用しました。

https://github.com/akishin/sambal

上記を使う場合、 Gemfile には以下のように記述します。

gem 'sambal', github: "akishin/sambal"

bundle install 実行。

bundle install --path=vendor/bundle

これで sambal のインストールは完了です。

使ってみる

以下のような感じで接続して ls を実行してみます。

require 'sambal'

begin
  HOST   = 'PC001'
  DIR    = 'Share'
  USER   = 'akishin'
  PASS   = 'p@ssword'

  client = Sambal::Client.new(host:     HOST,
                              share:    DIR,
                              user:     USER,
                              password: PASS)
  puts client.ls
  client.close
rescue => e
  puts e
end

ドメインに参加している Windows に接続する場合は以下のようにしてドメインを指定します。

require 'sambal'

begin
  DOMAIN = 'example.co.jp'
  HOST   = 'PC001.example.co.jp'
  DIR    = 'Share'
  USER   = 'akishin'
  PASS   = 'p@ssword'

  client = Sambal::Client.new(domain:   DOMAIN,
                              host:     HOST,
                              share:    DIR,
                              user:     USER,
                              password: PASS)
  puts client.ls
  client.close
rescue => e
  puts e
end

実行すると以下のような結果が表示されました。

$ bundle exec ruby sambal_example.rb
{"."=>{:type=>:directory, :size=>"0", :modified=>2014-02-18 22:43:37 +0900}, ".."=>{:type=>:directory, :size=>"0", :modified=>2014-02-18 22:43:37 +0900}, "test.txt"=>{:type=>:file, :size=>"0", :modified=>2014-02-18 22:43:36 +0900}}

ちゃんと共有フォルダの内容が読み取れているようです。

次は何かファイルを置いてみます。
Sambal::Client#put メソッドでローカルのファイルを共有フォルダに配置することができます。

require 'sambal'

begin
  HOST   = 'PC001'
  DIR    = 'Share'
  USER   = 'akishin'
  PASS   = 'p@ssword'

  client = Sambal::Client.new(host:     HOST,
                              share:    DIR,
                              user:     USER,
                              password: PASS)
  client.put('/home/akishin/image.png', 'image.png')    # <- 追記
  puts client.ls
  client.close
rescue => e
  puts e
end

実行すると以下のように image.png が結果に含まれている事がわかります。
また、実際に共有フォルダを確認するとファイルが配置されていました。

$ bundle exec ruby sambal_example.rb
{"."=>{:type=>:directory, :size=>"0", :modified=>2014-02-18 23:06:46 +0900}, ".."=>{:type=>:directory, :size=>"0", :modified=>2014-02-18 23:06:46 +0900}, "image.png"=>{:type=>:file, :size=>"29618", :modified=>2014-02-18 23:06:46 +0900}, "test.txt"=>{:type=>:file, :size=>"0", :modified=>2014-02-18 22:43:36 +0900}}

当然ですが Windows の共有フォルダに接続ユーザで書込み権限が必要なので、もし上手く行かない場合には確認してみて下さい。


というわけで、こんな感じでわざわざマウントしなくても Windows の共有フォルダに簡単にアクセスする事が出来ました。
Windows, Linux が混在しているような環境でスクリプトを書く際には結構重宝しそうです。

CentOS 6.5 に kippo をインストールしてみる

digitalOceanクラウド上に安く簡単にkippoハニーポットを構築する | 徳丸浩の日記
http://blog.tokumaru.org/2014/01/digitaloceankippo.html

sshハニーポットをkippoで作ってみる - ろば電子が詰まっている
http://d.hatena.ne.jp/ozuma/20130829/1377703104

さくらのVPSに来る悪い人を観察する その2
http://www.slideshare.net/ozuma5119/vps-28984029

この辺りの記事を読んでとても面白そうだったので、SSH ハニーポットkippoCentOS 6.5 環境にインストールしてみました。

依存ライブラリのインストール

まずは kippo を動かすためのライブラリ等をインストールしていきます。
yum から gcc, python-devel, setuptools をインストール。

# yum install -y gcc python-devel python-setuptools

setuptools を入れると使えるようになる easy_install コマンドで pip をインストールします。

# easy_install pip

pip から pyasn1, pycrypto, twisted パッケージをインストール。

# pip install pyasn1 pycrypto twisted

これで必要なライブラリは一通り入りました。

SSH ポート番号の変更

SSH の標準ポート 22 番は kippo で使用したいので、本来の sshd が使用するポート番号を変更します。

# vi /etc/ssh/sshd_config

ここでは徳丸さんの記事に習って 10022 番ポートに変更しました。

#Port 22
Port 10022

変更したら sshd を再起動します。

# service sshd restart

※ 手元の TeraTerm ではここで sshd を再起動しても特に問題なく作業を続行できましたが、VPS などで試している場合、もし不安なら先に以下を実行して、iptables で変更後の SSH ポートを空けておいた方が無難かも知れません。

iptables の設定

iptables で変更後の sshd 用ポートと kippo の LISTEN ポートを開放します。
ここでは CentOS のデフォルトのルールをそのままにしてあるので、-A で末尾に追加しても上手く動きません。
なので -I で先頭にルールを追しています。

# iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 2222 -j ACCEPT
# iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 10022 -j ACCEPT

ポート 22 を kippo のデフォルトポート 2222 にリダイレクトするように以下のルールを追加します。

# iptables -t nat -A PREROUTING -p tcp --dport 22 -j REDIRECT --to-port 2222

kippo のインストール

いよいよ kippo をインストールします。
まずは kippo の起動用ユーザを追加します。

# useradd kippo

作成した kippo ユーザになり、ダウンロードして展開します。

# su - kippo
$ wget https://kippo.googlecode.com/files/kippo-0.8.tar.gz
$ tar xzf kippo-0.8.tar.gz
$ cd kippo-0.8

ログを有効にするため、設定ファイルを編集します。

$ vi kippo.cfg

ファイル末尾の以下の行のコメントアウトを解除。

[database_textlog]
logfile = kippo-textlog.log

また、kippo でログインを可能とするユーザが以下のファイルで定義されています。

$ cat data/userdb.txt
root:0:123456

デフォルトでは上記のように root ユーザがパスワード「123456」で定義されています。
このファイルを変更することでユーザを追加したり、パスワードを変更したりといった事ができます。

準備ができたら kippo を起動してみます。

$ ./start.sh
Starting kippo in background...Loading dblog engine: textlog
Generating RSA keypair...
done.

無事起動できました。

起動で来たら先ほど設定ファイルで有効にした以下のログを tail しておきます。

$ tail -f ./kippo-textlog.log

この状態で別の SSH クライアントを起動してポート 22 に接続し、root / 123456 でログインすることができます。
ログイン後、コマンドを実行してみると kippo-textlog.log に以下のように何を実行したかが記録されている事が分かります。

$ tail -f ./kippo-textlog.log
b52fc974918911e3b432000c29ca5f43 [2014-02-09 21:57:18]: New connection: 192.168.81.1:50270
b52fc974918911e3b432000c29ca5f43 [2014-02-09 21:57:26]: Login succeeded [root/123456]
b52fc974918911e3b432000c29ca5f43 [2014-02-09 21:57:26]: Terminal size: 150x45
b52fc974918911e3b432000c29ca5f43 [2014-02-09 21:57:29]: Command [w]
b52fc974918911e3b432000c29ca5f43 [2014-02-09 21:57:32]: Command [ls]
b52fc974918911e3b432000c29ca5f43 [2014-02-09 21:57:37]: Command [ls -l]

取りあえず試したのはここまで。
CentOS でも結構簡単に導入出来る事が分かったので、いろいろ遊んでみたいと思います。

Vagrant 1.4.0 で private_network を指定しているとエラーになる件

Vagrant 1.4.0 で追加された Docker provisioner などを試してみたいと思い、勇んでアップデートしてみたところ vagrant up でエラー。

・
・
・
[default] Configuring and enabling network interfaces...
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

/sbin/ifdown eth1 2> /dev/null

Stdout from the command:



Stderr from the command:

どうも CentOS などの Redhat 系 OS を使っている場合に private_network を指定してるとなるっぽい・・・。
以下の Issue が上がっていました。

"Configuring and enabling network interfaces" fails with ssh error · Issue #2614 · mitchellh/vagrant
https://github.com/mitchellh/vagrant/issues/2614

この Issue で上げられていた以下のパッチで直るみたいです。

Merge pull request #2628 from makern/ifdown-fix · 70b662e · mitchellh/vagrant
https://github.com/mitchellh/vagrant/commit/70b662e3073c5a6aed2374ca289f8818f8ef8ed1

取りあえずすぐ動かしたかったので、アップデートのリリースを待たずに当ててみました。
Windows だと該当のファイルはデフォルトでは以下の場所にあります。

C:\HashiCorp\Vagrant\embedded\gems\gems\vagrant-1.4.0\plugins\guests\redhat\cap\configure_networks.rb

コード量も多くなかったのと面倒だったので元のファイルをバックアップしておいて、直接編集してしまいました。
上の URL の [View file] をクリックして次の画面で [RAW] をクリック。

https://raw.github.com/mitchellh/vagrant/70b662e3073c5a6aed2374ca289f8818f8ef8ed1/plugins/guests/redhat/cap/configure_networks.rb

この内容をコピーして、先ほど見つけた該当のファイルに貼り付けるだけ。
これで一応手元の環境では無事起動できるようになりました。

それにしても久しぶりにバージョンアップ時の地雷踏んだなー。