openSUSE 11.2 + rvm + ruby 1.9.1 p378 + atig.rb + god + tiarra

これだけ色々あったら動かない原因とか分からんよ!

rvmのインストール

git clone http://github.com/wayneeseguin/rvm.git
cd rvm
./install

パッケージ版Rubyとかも入れ出すと訳が分からなくなってくるので、githubから直接持ってくることにしました。

Ruby 1.9.1 p378のインストール

sudo zypper in libopenssl-devel zlib-devel readline-devel sqlite3-devel
rvm install 1.9.1

libopenssl-develはopenssl拡張ライブラリに、zlib-develはzlib拡張ライブラリに、readline-develはirb使うときに便利(というかないと超不便)なのでそれぞれ先に入れておきます。
あとatig.rbで使うsqlite3-rubyがsqlite3-develを必要とします。

必要gemのインストール

gem install rspec oauth sqlite3-ruby god

specを動かすためrspec入れていますが、openSUSEで動かす場合他の環境(Mac,Ubuntu,Debian)では出なかった問題で変になるのでやらなくてもいいかもです。修正めんどい。
sqlite3-rubyとgodはちょっとコンパイル入ります。

atig.rbのダウンロード

cd /opt
git clone http://github.com/mzp/atig

パスは /opt/atig だということにします。

atig.rbの修正

自分の環境の場合、spec動かすとこんなエラーが出ます。

rake spec
(in /opt/atig)
/opt/atig/atig/command/thread.rb:8:in `<module:Command>': uninitialized constant Atig::Command::Command (NameError)
        from /opt/atig/atig/command/thread.rb:7:in `<module:Atig>'
        from /opt/atig/atig/command/thread.rb:6:in `<top (required)>'
        from /opt/atig/atig/command/thread_spec.rb:4:in `require'
        from /opt/atig/atig/command/thread_spec.rb:4:in `<top (required)>'
        from /home/koutarou/.rvm/gems/ruby-1.9.1-p378/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:15:in `load'
        from /home/koutarou/.rvm/gems/ruby-1.9.1-p378/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:15:in `block in load_files'
        from /home/koutarou/.rvm/gems/ruby-1.9.1-p378/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:14:in `each'
        from /home/koutarou/.rvm/gems/ruby-1.9.1-p378/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:14:in `load_files'
        from /home/koutarou/.rvm/gems/ruby-1.9.1-p378/gems/rspec-1.3.0/lib/spec/runner/options.rb:133:in `run_examples'
        from /home/koutarou/.rvm/gems/ruby-1.9.1-p378/gems/rspec-1.3.0/lib/spec/runner/command_line.rb:9:in `run'
        from /home/koutarou/.rvm/gems/ruby-1.9.1-p378/gems/rspec-1.3.0/bin/spec:5:in `<main>'
rake aborted!

これは atig/command/ 以下のクラス類が全て atig/command/command.rb で定義されている Atig::Command::Command を継承しているのにも関わらず、require の順序のせいで NameError が出ているっぽいです。
ちなみに spec を動かさずに直で ruby atig.rb としても同様のエラーが出るので、 atig/command/*rb を require する前段階で atig/command/command.rb を require してやれば解決します。 spec では解決していませんので、もっとちゃんとした対応するべきかもしれません。
17行目から20行目辺りまでを抜粋。

require 'atig/twitter'
require 'atig/scheduler'
require 'atig/command/command'

ちなみにこの問題、MacUbuntuDebianで同様にrvmで入れたRuby 1.9.1 p378を使った場合は再現しません。何が問題なのかは分かりませんが、openSUSEでビルドしたRubyは他のものと若干挙動が異なるようです。と理解するしかない。

tiarraのダウンロード

cd /opt
svn co http://svn.coderepos.org/share/lang/perl/tiarra/trunk/ tiarra

パスは /opt/tiarra だということにします。

tiarraの設定

networks {
  (snip)
  name: atig
  (snip)
}

atig {
  server: localhost 16668
  name: from_kyushu sid
}

クライアントオプションを付けていますが、これはお好みで。
あと tiarra のパスワードもお忘れなく。

tiarra --make-password

出てきたものを general ブロックの tiarra-password に書いておきます。

tiarraの起動

./tiarra --quiet

godの設定ファイル作成

なんか色々やるの面倒だったので、とりあえずバックグラウンドで起動するものです。監視している意味は一切ありませんので、なんか好きなようにアクションを書き加えてください。

God.watch do |w|
  w.name = "atig.rb"
  w.interval = 30.seconds
  w.start = "ruby /opt/atig/atig.rb -h '127.0.0.1' -l /opt/atig/atig.log"

  w.start_if do |start|
    start.condition(:process_running) do |c|
      c.running = false
    end
  end
end

ミソは -h オプション。これないとダメっぽいです。ちゃんと指定しましょう。

atig.rbの起動

god -c atig.god

oauth

#oauth@atig で示されたURLを開いて認証してください。もしURLも何も示されていなかった場合、 god の設定の atig.rb 起動しているオプションに -d を加えて、ログに出力されたURLを使用してください。
あとは #twitter@atig できゃっきゃうふふするといいと思います。

LinodeのopenSUSEを11.2にアップグレードする

LinodeではopenSUSEVMとして選択できるのですが、11.0のままです。調べてみたら11.1は動くとの情報があったので11.2も動くはずだと思い、やってみることにしました。

11.0から11.1へ

11.1から11.2へのライブアップグレードはサポートされているので、まずは11.1にアップグレードします。参考: openSUSE 11.1 on Linode ala zypper dup – Aaron Bockover

  • openSUSE 11.0をデプロイし、ブートする
  • sshを用いてrootでログインする
  • 11.0のレポジトリリストを削除する: /etc/zypp/repos.d
rm /etc/zypp/repos.d/*

これでやりました。ただ、こっちが動くならzypperの機能だしこっちがいいかも。

zypper modifyrepo --all --disable
  • 11.1のレポジトリを追加する
zypper ar http://download.opensuse.org/distribution/11.1/repo/oss openSUSE-11.1

参考ページでは -f オプションついているけど、unknown optionとして怒られてしまったので削除しました。削除していても問題なし。

  • zypperを先にアップデートする
zypper in zypper
  • レポジトリをアップデート
zypper refresh

必ずしも必要ではなさそうですが、やっていて損はないでしょう。

  • 11.1へアップグレード
zypper dup

ディスク容量が不安な人はこちらで先にパッケージだけダウンロードしておいて、ディスクを確認の上やってみるといいかも。

zypper dup -d
zypper dup
  • ここで一度再起動。
  • 再起動後、アップデートレポジトリを追加する
zypper ar -f http://download.opensuse.org/update/11.1/ openSUSE-11.1-Updates

ここでは -f オプションは怒られませんでした。

  • 11.1の最新版にアップデートする
zypper up

11.2へのライブアップグレードのために最新版に上げておく必要があるようです。

11.1から11.2へ

この作業はopenSUSEWikiに日本語で情報があるので、こっちを参考にするといいかもです。SDB:システムアップグレード - openSUSE Wiki
まぁ、ほぼ11.0から11.1への作業と一緒のようです。ぶっちゃけ11.0から11.2に直でやってもよかったのかもしれません。

ちなみに、ここまでやって転送量は約700MB程度でした。Linodeは月200GBなので、これを多いと見るか少ないと見るかは用途次第かと思います。自分は自分用のサービスしか動かしていないので全く問題ありませんが。

Windows7にcoLinuxをインストールする

お久しぶりです。ずいぶんと長い間更新していませんでしたが、またメモ書き程度に更新しようと思います。
使用するイメージはDebian Lennyで、coLinuxのインストールパスとディスクイメージを置くパスは違うところにしています。

coLinux及びディスクイメージをダウンロード

sourceforgeからcoLinux-0.7.6.exeとDebian-5.0r2-lenny.7zをダウンロードします。coLinuxはC:\Program Files\coLinuxに、ディスクイメージはD:\opt\colinux_imagesに置きます。配置する際はlenny.imgにリネームしました。confファイルは違うパスに置いていいか分からなかったのでcoLinuxのインストールパスに置いておきます。

ファイル配置

swap用イメージ、リサイズ用イメージの準備

sourceforgeで配布されているディスクイメージは2GBなので、色々していたらすぐいっぱいになります。なので早いところサイズ変更を行おうと思います。とりあえず10GBほど準備してみました。
swap用のイメージも一緒に準備します。今回は512MB準備します。
イメージの準備にはfsutilを使いますが、これを使うには管理者権限が必要なので管理者権限付でcmdを起動します。スタートボタンの"プログラムとファイルの検索"にcmdで検索して、出てきたものを右クリックして"管理者として実行(A)"をすればOKです。

d:
cd D:\opt\colinux_images
fsutil file createnew lenny_10gb.img 10737418240
fsutil file createnew swap.img 536870912

ただ、このままだとlenny_10gb.imgとswap.imgはAdministrator所有のものになるので、取り扱いがやや面倒。なので所有者を自分のアカウントに指定します。参考:http://www.atchfactory.com/mvt/archives/2009/10/windows7-9.html

ターゲットフォルダを右クリック→プロパティ

セキュリティ タブの中にある [詳細設定] をクリック

セキュティの詳細設定 が開くので、所有者 タブの中にある [編集] をクリック

所有者の変更 の枠内から自分のアカウントを選び、下の方にある サブコンテナーとオブジェクトの所有者を置き換える にチェックを入れて [適用]

参考にしたところではフォルダを指定していますが、今回の対象はファイルなので一番最後のサブコンテナー云々は不要です。

ファイル配置

lenny.confの編集

lenny.confを弄るには管理者権限が必要なので、管理者権限で実行したエディタで編集する必要があります。自分はGVim使っているので、管理者権限付で実行したGVimから開きました。そして以下のように編集しました。

kernel=vmlinux
cobd0="D:\opt\colinux_images\lenny.img"
cobd1="D:\opt\colinux_images\swap.img"
cobd2="D:\opt\colinux_images\lenny_10gb.img"
root=/dev/cobd0
ro
initrd=initrd.gz
mem=256
eth0=pcap-bridge,"Local Network"

cobd云々は使用するディスクイメージを使用する分だけ指定します。例えば/homeだけ別イメージにするのでしたらそれを更に増やしてください。ここで指定したcobd0などは/dev/cobd0などになるので、それをマウントすれば使えるようになります。
memにメモリを指定します。増やしたければその分増やしてください。今回は256MB指定にしました。
eth0にはネットワークの接続方法を指定します。tuntapを指定するのが定番っぽいのですが、今回はWinPcapを使ったブリッジ接続を行うのでこのような感じにしました。要WinPcap。複数のネットワークアダプタがあるので使用するアダプタ名を指定していますが、アダプタがひとつしかない場合は自動で認識してくれるらしいので指定は不要です。もし指定する際は名称はマルチバイト文字が使えないらしいので適当にリネームしてください。

coLinuxの起動

colinux-daemon.exe @lenny.conf

無事ログイン画面が表示されたら成功。rootでログインする場合、パスワードはcolinuxになっているのでログイン後にさっさと変更しておきます。

ネットワークの確認

ifconfig
eth0      Link encap:Ethernet  HWaddr 00:ff:3c:5e:f0:00
          inet addr:192.168.1.10  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::2ff:3cff:fe5e:f000/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:124362 errors:0 dropped:0 overruns:0 frame:0
          TX packets:57939 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:147246696 (140.4 MiB)  TX bytes:4469694 (4.2 MiB)
          Interrupt:10

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

デフォルトではDHCPで取得するようになっています。IP固定にする場合なんかは /etc/network/interfaces を適当に編集します。この辺coLinuxでなくてDebianの領域なのでパス。
coLinux -> WindowsWindows -> coLinux 双方でping投げて繋がっているかを確認しておくと更に安全かと思います。

データのコピー及びswapの準備

lenny.imgの内容をlenny_10gb.imgに移動します。dd便利。参考:Free Dynamic DNS(DDNS) by POP3,IMAP4,FTP,HTTP-BASIC for Home Server, VPS | MyDNS.JP

dd if=/dev/cobd0 of=/dev/cobd2
e2fsck -f /dev/cobd2
resize2fs -p /dev/cobd2

次はswapの準備。

mkswap /dev/cobd1

そして /etc/fstab を以下のようにする。

# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
/dev/cobd0      /               ext3    errors=remount-ro 0       1
/dev/cobd1      swap            swap    defaults        0       0

再度lenny.confの編集

lenny.imgの中身はlenny_10gb.imgの中に入ったのでlenny.imgは不要になりました。lenny.imgを削除してlenny_10gb.imgをlenny.imgにリネーム、cobd2の設定を削除します。これで容量10GBのディスクイメージができあがりました。

ファイル配置

サービス登録

要管理者権限。

colinux-daemon.exe @lenny.conf --install-service

[コントロールパネル] -> [システムとセキュリティ] -> [管理ツール] -> [サービス] でサービスの設定が出るので、適当にほげほげします。

これで大体準備は整ったので、あとはssh入れてputtyでつないで、adduserでユーザー作って、きゃっきゃうふふするといいと思います。

mixiボイスに書き込むスクリプト

とりあえずRuby1.9.1とRuby1.8.7で動いたので載せる。特に設計とか考えずに書いたのでまだ改善の余地あり。

# vim:set fileencoding=UTF-8:

require 'net/http'
require 'uri'

class MixiVoice
  def initialize mail,pass,key
    @cookie = ""
    @key = key
    @req = Net::HTTP.start "mixi.jp"
    login mail,pass
  end

  def login mail,pass
    res = @req.post "/login.pl", "email=#{mail}&password=#{pass}&next_url=/home.pl"
    @cookie = res["set-cookie"].split(",").join(";")
  end

  def add_echo text
    res = @req.post "/add_echo.pl", "body=#{encode_text(text)}&post_key=#{@key}&redirect=recent_echo", "cookie" => @cookie
    res.code
  end

  def encode_text text
    euc = ""
    if RUBY_VERSION > "1.9"
      euc = text.encode "EUC-JP"
    else
      require 'kconv'
      euc = Kconv.toeuc text
    end
    URI.encode(euc)
  end
end

if __FILE__ == $0
  require "rubygems"
  require "pit"

  conf = Pit.get "mixi"
  vo = MixiVoice.new conf["mail"],conf["pass"],conf["post_key"]
  res = vo.add_echo "Hello,world!"
  puts res
end

MixiVoice#add_echoは302が返ってきたらOKです。200だと失敗。

gem serverをlaunchdで動かしておく

Rubyで、gem installした後、ざっとドキュメントを見たいとき、どうするのが良いでしょうか?
(→解決しました「gem serverを動かして、表示されたURLをブラウザで見る」らしいです)

Rubyで、gem installした後、ざっとドキュメントを見たいとき、どうするのが良いでしょうか?→gem serverで解決 - rubyco(るびこ)の日記

というエントリを見て、割と便利に使っているのですがあんまりみんなが使ってないのかもしれない方法があるのでご紹介。

launchdでサービスとして動かす

Macにはlaunchdというものがあります。おいらもman読んだぐらいしか知識がないので説明はうまくできません。大体Linuxで言うinitみたいなもんです。第1回 initを置き換えるlaunchd【前編】 (1/3) - ITmedia エンタープライズ第2回 initを置き換えるlaunchd【後編】 (1/3) - ITmedia エンタープライズという記事もありますので併せてご一読ください。
で、このlaunchdで予めgem serverをサービスとして動かしておくとちょくちょくgemに含まれているrdocを読む際には結構便利になります。

設定ファイルの置き場所

  • $HOME/Library/LaunchAgents
  • /Library/LaunchAgents
  • /Library/LaunchDaemons
  • /System/Library/LaunchAgents
  • /System/Library/LaunchDaemons

この辺りらしいです。

LaunchAgentsとLaunchDaemonsの違い

 launchdが起動するサービスは大きく分けて2つ、AgentとDaemonに分類される。
 Daemonはいわゆるデーモンであり、root権限での動作を前提としている。これはログインしているユーザーが誰であるか、そもそもログインしているユーザーがいるかといったこととは関係を持たないサービスを意味する。
 一方AgentはDaemonとは異なり、現在ログインしているユーザーごとに起動される各ユーザー向けのサービスを意味する。例えば「ことえり」やATOKのような入力プログラム、iCaliTunesのヘルパープログラムといったユーザーごとに実行されるバックエンドサービスを起動するのに使用できる。

第1回 initを置き換えるlaunchd【前編】 (2/3) - ITmedia エンタープライズ

という訳でとりあえず自分のところだけで動かしたいので $HOME/Library/LaunchAgents に置きましょう。

設定ファイル launchd.plist を書く

おいらが使っているのは以下。名前は org.rubygems.server.plist とか適当に名付けています。

<?xml version="1.0" encoding="UTF-8"?>                
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>                                                
  <key>Label</key>                                    
  <string>org.rubygems.server</string>                
  <key>OnDemand</key>                                 
  <false/>                                            
  <key>ProgramArguments</key>                         
  <array>                                             
    <string>/opt/local/bin/gem</string>               
    <string>server</string>                           
    <string>--daemon</string>                         
  </array>                                            
</dict>                                               
</plist>

launchctlで設定ファイルを読み込み起動する

上のplistをorg.rubygems.server.plistで保存した場合

launchctl load -w org.rubygems.server.plist
launchctl start org.rubygems.server
load
launchctl load [-w] launchd.plist

wオプションは強制読み込み

unload
launchctl unload [-w] launchd.plist

wオプションは強制的に無効に

start
launchctl start jobname

jobname = launchd.plistのLabel要素で指定したもの

stop
launchctl stop jobname

jobname = launchd.plistのLabel要素で指定したもの

ブラウザで表示してみる

start した状態で http://localhost:8808 を表示して表示を確認する。表示できれば成功。

[おまけ] Firefoxのスマートキーワードに検索ボックスを登録しておく

Firefoxのスマートキーワードを設定しておくと、rdoc表示がさらに素早く行えます。おいらは gems というキーワードで登録しています。
Let's Enjoy!

[Ruby] TwitterBot制作妄想中

まだ形になっていないどころか実現可能かすらも考えていないのだけど、適当に考えている事を挙げてみるよ。

予め登録された情報を指定日時に呟く告知用Bot

Googleカレンダーか独自の入力フォームにするかは考えていないのだけども、指定された日時に指定された文章を呟くBotはそれなりに便利そうだなー、と思う。繰り返し設定をすると指定日時まで繰り返し呟くとか。繰り返し呟く場合は1日1,2度ぐらいにしておかないとアレげ
考えるべきは以下

  • 連投規制
    • 同一人物によるつぶやきをちょっとだけ時間をずらしてひたすら呟かれたら迷惑なので、この辺りどうにか考える。
      • Twitter IDも登録して、IDごとに1日に呟ける回数を制限するとか?
      • SPAMとかに利用されたらアレなのでブラックリスト作成も考えるべきかも
        • @replyが飛ばないように@の入った文章は解析する必要あり?
        • メアド登録ができないよう規制もしたい
  • 予定入力方法
    • 独自に入力フォームを作るのは面倒なのでGoogleカレンダーの公開カレンダーに入力してもらおうかなー、とか考えている。でも自分でフォーム作った方が便利ではある。
      • @replyによる登録とかも良いかもしれない。書式を指定して、その書式にそって正規表現なんかでぶった切るとイケそう。

上と下のつぶやきを合体させるBot

2chである「上と下のスレタイを合体させる」とかその辺みたいな。followingの呟きを一定時間で取得して、ランダムで組み合わせてみるみたいな。
考えるべきは以下

  • followingの作り方
    • こっちから一方的にfollowするのはアレげかなぁとか思う
      • でもそれなりにfollowingの数がないと楽しくないかなとも思う
      • followされたらfollowし返す感じでどうにかなるかなぁ
        • さすがにfollowしていない人の呟きをあれこれするのってマズいよね?
        • Protectedな人の呟きは使えないようにしないとマズいよねT
  • 特定IDの呟き合体
    • followingの中からランダムでIDをひとつ取り上げて、その人の呟きをいくつか取ってきて合体させるみたいな
    • @replyを受けたらその人のIDから呟きを取ってきて合成して@replyし返すのも良いかも
  • 呟きの合成の仕方

RTランキングBot

これ妄想した後にちょっと探したら見つかった。
@RT_report

follow観測Bot

「@hogehogeが@fugafugaをfollowしました」みたいな感じのことを呟く。これはもちろんfollowing/followersの中の人に限定する。不特定多数に広げたら酷いことになる。
考えるべきは以下

  • follow情報を保存して良いものなのか
    • このBotをfollowする時点で承認したものとして考えて良いのだよね、多分
  • follow数推移のグラフとか出せると面白いのかなぁ
    • でも正直グラフ出力とか考えるのが面倒でもあります

適当に羅列してみたのは良いのだけど

どれも作るとは限りません。おいら自身はどれも完成には至らないに3000点。

MacのJDK6で文字コードをUTF-8にする

JDK5だとUTF-8なのですが、JDK6だとSJISになります。Terminalの文字コードUTF-8なので、ちょくちょく書く時に問題が出てしまいます。JDK5を使えばいいのでしょうが、JDK6が必要になったときに困ります。なので環境変数JAVA_OPTIONSにこのように設定しました。

export JAVA_OPTIONS="-Dfile.encoding=UTF-8"

ひとまずこれで良しとします。

ちなみにJDK6を使用した理由ですが、以前どっかの本でAndroid SDKを使うにはJDK6にしないといけないとか読んだ気がするからです。ですが今 http://developer.android.com/sdk/1.5_r2/requirements.html を読んだら

JDK 5 or JDK 6 (JRE alone is not sufficient)

と書いてあって

Note: If JDK is already installed on your development computer, please take a moment to make sure that it meets the version requirements listed above. In particular, note that some Linux distributions may include JDK 1.4 or Gnu Compiler for Java, both of which are not supported for Android development.

とあるので、JDK5以上だったらとりあえずは大丈夫っぽい。