ラベル 備忘録 の投稿を表示しています。 すべての投稿を表示
ラベル 備忘録 の投稿を表示しています。 すべての投稿を表示

2010年9月30日木曜日

SQLite3-RubyでのSQL文のexecuteについて

よく考えずに適当にSQL文をexecuteするだけでそれなりのものは作れてしまうので、私の場合、ロクに考えずに作ってしまいがちになる。しかし、それなりに大きなもの、重要なものを作ろうとするとそういう訳にはいかないので、executeの基本的な使い方を纏めてみる。


今回サンプルとして利用するテーブルは以下の通り。

db = SQLite3::Database.new("test.db")
db.execute(<<EOS
CREATE TABLE IF NOT EXISTS Vocaloid
(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name CHAR UNIQUE NOT NULL,
Ver INTEGER NOT NULL
);
EOS
)



普通にexecuteする


毎度SQL文を組み立て、executeする。
SQLインジェクション対策を全て手動で行わなければならない為、非効率。

db.execute(<<EOS
INSERT INTO Vocaloid
(Name, Ver)
VALUES ('miku', 2 )

)



引数を渡し、executeする


引数に?に対応する値を順番に渡す。
quote等も自動的に処理してくれる模様。

sql = <<EOS
INSERT INTO Vocaloid
(Name, Ver )
VALUES (?, ?)
EOS
db.execute(sql, "miku", 2)



ハッシュ引数を渡し、executeする



sql = <<EOS
INSERT INTO Vocaloid
(Name, Ver )
VALUES (:Name, :Ver)
EOS
db.execute(sql, :Name => "miku", :Ver => 2)



prepareを利用する


SQL文をテンプレートとして用意しておいて、execute時に変数として渡す。

pre = db.prepare(<<EOS
INSERT INTO Vocaloid
(Name, Ver)
VALUES (?, ? )

)

pre.execute("miku", 2)
pre.execute("rin", 2)
pre.execute("meiko", 1)



prepareでハッシュ引数を使う



pre = db.prepare(<<EOS
INSERT INTO Vocaloid
(Name, Ver)
VALUES (:Name, :Ver)
EOS
)

pre.execute(:Name=>"miku", :Ver=>2)
pre.execute(:Name=>"rin", :Ver=>2)
pre.execute(:Name=>"meiko", :Ver=>1)



・参考

http://sqlite-ruby.rubyforge.org/sqlite3/faq.html


http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html

2010年9月8日水曜日

みくった〜♪のWindows版をMinGWでビルドしてみた

みくった〜♪は、全てのミク廃、そしてTwitter中毒者へ贈る、至高のTwitter Clientを目指すTwitter Client…として@toshi_a氏が開発しているソフトウェアである。

みくった〜♪

主にLinux向けとして開発されているようだが、初公開の時点で「Windows版無いの(´・ω・`)?」と言われたように、Windows版の需要がやはりそれなりに存在する。
そこで、MinGW使ってRuby/GTK2環境を整え、Windowsでもみくった〜♪を動作させることはできないものか?と考え、実際にやってみた。

※ただ使ってみたいだけ、という方はみくった〜♪ for Windowsのページかみくった〜♪ for Windows 毎日0,12時に自動ビルドされるバージョンからどうぞ。



ビルドに必要なソフトウェアやライブラリは以下の通り。
MinGW GCC 4.5.0
ftp://ftp.jaist.ac.jp/pub/sourceforge/m/project/mi/mingw/Automated%20MinGW%20Installer/mingw-get-inst/mingw-get-inst-20100831/mingw-get-inst-20100831.exe

ruby 1.8.7-p302
ftp://ftp.ruby-lang.org/pub/ruby/ruby-1.8.7-p302.tar.bz2

ruby-gtk2-0.19.4
http://ftp.jaist.ac.jp/pub/sourceforge/r/project/ru/ruby-gnome2/ruby-gnome2/ruby-gnome2-0.19.4/ruby-gtk2-0.19.4.tar.gz

ruby-hmac-0.3
http://deisui.org/~ueno/ruby/hmac.html
http://deisui.org/~ueno/ruby/ruby-hmac-0.3.tar.gz

iconv
ftp://ftp.gnu.org/gnu/libiconv/libiconv-1.13.1.tar.gz

GTK+
http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.20/gtk+-bundle_2.20.0-20100406_win32.zip

Win32 OpenSSL
http://www.slproweb.com/products/Win32OpenSSL.html
http://www.slproweb.com/download/Win32OpenSSL-0_9_8o.exe

Microsoft Visual C++ 2008 SP1 再頒布可能パッケージ (x86) OpenSSL用
http://www.microsoft.com/downloads/details.aspx?familyid=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2&displaylang=ja

可能な限りソースからビルドするようにしたが、OpenSSLとGTK+は面倒だったので、とりあえずWindows用バイナリを利用することにした。…OpenSSLをMinGWでビルドすれば、MSVC++ランタイム要らなくなるのだが…。



MinGWによるビルド環境の構築


以前はMinGW(コンパイラ)とMSYS(サブシステム)を個別に用意し、セットアップする必要があったが、現在はmingw-get-instパッケージに纏められた模様。これをダウンロードし、普通のソフトウェアのインストーラと同じようにウィザードを進めていくだけでビルド環境が整う。
デフォルトでは、Windowsのパス変数もMSYSのパス変数として登録されてしまい、混乱の原因となるので、PATH変数を変更しておく。

$ PATH="/mingw/bin:/usr/local/bin:/bin"




iconvのビルド


一番最初にiconvをビルドする。といっても、普通に

$ ./configure --prefix=/mingw
$ make
$ make install

のような感じでおk。
本当なら/usr/localあたりにprefixを置いて、そこにインストールすべきな筈なのだが、私のCFLAGSやLDFLAGSの認識がおかしいのか、rubyのiconvライブラリのextconf.rbが/usr/localに置いたiconvを見つけられないため、諦めて/mingwにprefixを置く。



必要なライブラリの展開


GTK+のアーカイブを解凍し、そのまま全て/mingwに展開する。
OpenSSLは、インストーラを実行しインストールした先にあるディレクトリを、GTK+同様に/mingwに展開する。
また、OpenSSLを利用するために必要なMicrosoft Visual C++ 2008 SP1 再頒布可能パッケージ (x86)もインストールしておく。



Rubyのビルド


いつも通りRubyをビルドする。

$ ./configure --prefix=/ruby
$ make
$ make install

prefixを/rubyにしたが、make installする際にMSYSの/を飛び越えるため(コンパイルしたRubyがインストールに使用されるから?)、Windows側の\rubyにインストールされるので注意が必要。
そして、Windows側にインストールされたRubyを、MinGWの/usr/localあたりに移動しておく。



Ruby/GTK2のビルド


Ruby/GTK2のアーカイブを解凍し、extconf.rbを先程作成したRubyで実行する。

$ /usr/local/bin/ruby extconf.rb

そして後はmake、make installするだけの筈なのだが、MinGWでRuby/GTK2をビルドすると何故か毎度gtkのビルドでコケる。
どうやらこれからビルドされる筈のgtk2.soを、ビルド前にリンクしようとするかららしい。
そこで、gtkのMakefileを編集する。
何らかのエディタでgtk/src/Makefileを開き、LIBS = $(LIBRUBYARG_SHARED)...で始まる行の、-lgtk2を削除。

後はいつも通り。

$ make
$ make install


この時点で、Ruby/GTK2自体の開発/実行環境は整っていることになる。
MSYSでの作業はここで終了。



必要なファイルのみを纏め、最小限のRuby/GTK実行環境を作成


MSYSの/usr/localにはRuby/GTKの実行環境が整っている(ライブラリは足りないが)ので、これを適当なディレクトリにコピーし、rubyディレクトリとする。
rubyディレクトリのbinに、iconv、OpenSSL、GTK+の*.dllをコピー。
そして、RubyのLOAD_PATHのどこかにruby-hmacを展開。
後はみくった〜♪をダウンロードして展開、普通に起動できれば、みくった〜♪実行環境完成となる。



mikutter.exeを作成


毎度コマンドラインでruby mikutter.rbとしたり、バッチファイルを実行するのはどことなく落ち着かない。
また、Rubyの環境すべてがrubyディレクトリに入っているので、配布するにしてもかなりのサイズになってしまう。
そこで、更に必要なファイルだけを纏め、Windowsの実行ファイル形式で配布する形をとる。
exeファイル化には、exerbを利用する。
exerbの使用方法は、
・mkexy mikutter.rbでレシピファイルmikutter.exyを自動生成
・exerb mikutter.exyとすると、mikutter.exeが作成される
という感じである。
ここで作成されたバイナリは、Ruby環境無しで動作するものなので、あとはmikutterのディレクトリ階層とdllの配置をするだけ。

exerbの詳しい使用方法、レシピファイルの書式については、
公式ページ http://exerb.sourceforge.jp/
やmikutter for Windows付属のmikutter.exyを参照して欲しい。



みくった〜♪ 本家
http://toshia.dip.jp/
http://mikutter.d.hachune.net/

みくった〜♪ for Windowsのページ
http://append.hachune.net/mikutter.html

みくった〜♪ for Windows 毎日0,12時に自動ビルドされるバージョン
http://file.hachune.net/mikutter/

2010年6月30日水曜日

RubyのYAMLライブラリで2バイト文字をそのまま扱う

RubyのYAMLライブラリでは、標準では日本語などの2バイト文字列をバイナリとして扱うようになっている。しかし、これでは人間が直接修正するのが非常に面倒である。

技術評論社のYAML解説ページには、Rubyのソースにパッチを当てビルドする方法や、ya2yamlを使用する方法が書いてあった。しかし、パッチを当てた環境をすべてに適用するのは非常に面倒であり、ya2yamlについては標準ライブラリではない上に、少々遅いという問題がある。

そこで、どうにかする方法はないものかとYAMLのソースを眺めていたところ、以下の方法であっさり解決してしまった。



#!/usr/bin/env ruby
# -*- encoding: utf-8 -*-

require "yaml"
require "yaml/encoding"

# String.is_binary_data?で必ずfalseを返すように書き換える
class String
def is_binary_data?
return false
end
end

data = {"はつね"=>"みく", "はちゅね"=>"みく", "かがみね"=>"りん・れん", "めぐりね"=>"るか"}

# 通常どおり表示
puts "Escape:"
puts yaml = YAML.dump(data)

# アンエスケープして表示
puts "Unescape:"
puts yaml = YAML.unescape(yaml)


一度エスケープされたものをまた戻すという、面倒なことになっているが、ソース修正するよりマシかな…と。
これで、YAMLで書き出して手動で編集…なんてことがやりやすくなるかもしれない。

2010年6月3日木曜日

RubyでWebサーバを作る(ベーシック認証/ダイジェスト認証)

WEBrickでベーシック認証を行うには、以下のようにする。


#!/usr/ruby1.9/bin/ruby1.9
#-*- encoding: utf-8 -*-

require "webrick"

# HTTPServerを作成
httpd = WEBrick::HTTPServer.new(:Port => 3939)

# Basic認証の設定(引数にはパスワードファイルへのパスを渡す)
pswd = WEBrick::HTTPAuth::Htpasswd.new("dot.passwd")
pswd.set_passwd("mikubox", "miku", "mikumiku") #realm, user, passwd
auth = WEBrick::HTTPAuth::BasicAuth.new(:UserDB => pswd, :Realm => "mikubox")

# HTTPServerの/loginにBasic認証を設定
httpd.mount_proc("/login"){|req, res|
# 認証
auth.authenticate(req, res)
res.body = "<html><head><title>みくかわいいよみく</title></head><body><p>OK.</p></body></html>"
}

# INTシグナルでサーバを停止
trap("INT"){httpd.stop}
# サーバを開始
httpd.start()



ベーシック認証では、パスワードが簡単に復号可能な状態でネットワーク上を流れるため、重要なものに利用するのは非常に危険。
そこで、ダイジェスト認証を利用する。


#!/usr/ruby1.9/bin/ruby1.9
#-*- encoding: utf-8 -*-

require "webrick"

# HTTPServerを作成
httpd = WEBrick::HTTPServer.new(:Port => 3939)

# ダイジェスト認証の設定(引数にはダイジェスト認証用のデータベースのパスを渡す)
pswd = WEBrick::HTTPAuth::Htdigest.new("dot.digest")
if pswd.get_passwd("mikubox", "miku", false) == nil
pswd.set_passwd("mikubox", "miku", "mikumiku") # realm, user, passwd
pswd.flush # ファイルに書き込む
end
auth = WEBrick::HTTPAuth::DigestAuth.new(:UserDB => pswd, :Realm => "mikubox")

# HTTPServerの/loginにダイジェスト認証を設定
httpd.mount_proc("/login"){|req, res|
# 認証
auth.authenticate(req, res)
res.body = "<html><head><title>みくかわいいよみく</title></head><body><p>OK.</p></body></html>"
}

trap("INT"){httpd.stop}
httpd.start()



どちらも比較的簡単に認証を実現することができた。
ベーシック認証はHTTPAuth::HtpasswdとHTTPAuth::BasicAuth、
ダイジェスト認証はHTTPAuth::HtdigestとHTTPAuth::DigestAuthと覚えておけば良いかと思う。



※ 追記
もっと簡単にベーシック認証を行う方法があった。

#!/usr/ruby1.9/bin/ruby1.9
#-*- encoding: utf-8 -*-
require "webrick"

httpd = WEBrick::HTTPServer.new(:Port => 3939)
httpd.mount_proc('/login') {|req, res|
WEBrick::HTTPAuth.basic_auth(req, res, "mikubox") {|user, pass|
user == 'miku' && pass == 'mikumiku'
}
res.body = "<html><head><title>みくかわいいよみく</title></head><body><p>OK.</p></body>
</html>"
}
trap("INT"){httpd.stop}
httpd.start

2010年5月30日日曜日

RubyでWebサーバを作る

最近全然書いてないな~ということで、RubyでWebサーバを簡単に作れるライブラリ、WEBrickについて書いてみる。


Ruby 1.8以上なら、


require "webrick"
WEBrick::HTTPServer.new(:Port => 3939, :DocumentRoot => ENV["HOME"]).start


たったこれだけで、TCPポート3939番に自分のHOMEディレクトリを公開してしまう、とんでもないWebサーバが出来上がる。Ruby on Railsで有名になったライブラリだが、Apacheを使うまでもない、実験用Webサーバが欲しい時などにもとっても便利。



・ CGIを利用する
拡張子を.cgiとしたファイルに実行属性を加えるだけ。

http.mount(Webサーバ上でのパス, WEBrick::HTTPServlet::CGIHandler, CGIとして実行するファイルのパス)

としてマウントすることもできる。


・VirtualHostを利用する
メインのHTTPServerに、別のServerNameを設定したオブジェクトをvirtual_hostとして渡す。
メイン以外のホストは、:Portをnil、:DoNotListenをtrueとする。

http = WEBrick::HTTPServer.new(:ServerName => "miku.hachune.net", :DocumentRoot => "miku/")
http.virtual_host(WEBrick::HTTPServer.new(:ServerName => "append.haachune.net", :DocumentRoot => "append/", :Port => nil, :DoNotListen => true))
http.start



・各ユーザのホームディレクトリの特定のディレクトリを公開する
/home/$USER/public_htmlを公開する場合、DocumentRootOptionsのUserDirを設定する。

:DocumentRootOptions => {
:UserDir => "public_html"
}



・MimeTypeを追加する
デフォルトで設定されているMimeTypesにマージする。

newmime = {"wav"=>"Audio/wav"}
mime = WEBrick::HTTPUtils::DefaultMimeTypes.merge(newmime)
WEBrick::HTTPServer.new(:DocumentRoot => ENV[HOME], :MimeTypes => mime).start



・indexが存在しない場合の、ファイル一覧を表示しないようにする

:DocumentRootOptions => { :FancyIndexing => false }



・最大クライアント数を制限する

:MaxClients => クライアント数



・アクセスできるファイル/ディレクトリを制限する
DocumentRootOptionsのNondisclosureNameに、公開したくないファイル/ディレクトリ名を配列で指定する。
ワイルドカードが使用可能。

:DocumentRootOptions => {
:NondisclosureName => [".ht*", "*~", ".svn"]
}



・他のURLに転送する

http = WEBrick::HTTPServer.new(:Port => 3939)
http.mount_proc("/"){|req, res|
res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, 'http://hachune.net/')
}



・Cookieを渡す

http = WEBrick::HTTPServer.new(:Port => 3939)
http.mount_proc("/"){|req, res|
res["Set-Cookie"] = "hatsune=miku;Max-Age=3600;"
res.body = "<p>Cookieです。</p>"
}



・erb(組み込みRuby)を使う
WEBrickでは、HTMLファイルにRubyスクリプトを埋め込み、実行することも簡単にできる。

まず、MimeTypeにrhtmlをtext/htmlとして追加する。

:DocumentRootOptions =>{
:MimeTypes => WEBrick::HTTPUtils::DefaultMimeTypes.merge({"rhtml"=>"text/html"})
}

後は、拡張子をrhtmlとしたファイルに、
<%= Time.now.to_s %>
のように、必要な場所に埋め込む。


・指定された拡張子(cgi、rhtml)以外のファイル(rb、html)でCGIやerbを有功にする
require "webrick"の下あたりに以下の内容を記入しておく。
拡張子に合わせて、MimeTypeの設定も必要かもしれない。

module WEBrick::HTTPServlet
WEBrick::HTTPServlet::FileHandler.add_handler('rb', WEBrick::HTTPServlet::CGIHandler)
WEBrick::HTTPServlet::FileHandler.add_handler('html', WEBrick::HTTPServlet::ERBHandler)
end



他にもいろいろあるけれど、とりあえず一番必要とされそうな所だけ。
そのうちlogに関して等も追記する…と思う。

2010年3月22日月曜日

RubyでUDPなServer/Clientを作ってみた

なにやらUDPを使ったアプリケーションを作成することになりそうなので、各クライアントから来た要求を全クライアントに返すサーバと、送信/受信を行うクライアントを作成してみた。

UDPなので、相手に届いているかを保証することはできない。
よって、このサーバ/クライアントでは「伝えること」より「リアルタイムで発信すること」を重視する。


まずはサーバ側を作成。

#!/usr/bin/env ruby
#-*- encoding: utf-8 -*-

require "socket"

SERVERIP = "192.168.0.105"
SERVERPORT = "62000"

clientList = Array.new

sock = UDPSocket.new
# サーバとして待ち受けるアドレスとポートを指定 
sock.bind(SERVERIP, SERVERPORT)

while true
# sockに出力が来るのを待つ
# 来なかったらnilを返す
sel = IO::select([sock])
if sel != nil
sel[0].each {|s|
# 最大65535byte分のデータを受け取る。
# データは配列として渡される。
# ["文字列", ["アドレス種別", 送信元ポート番号, "送信元ホスト名", "送信元IPアドレス"]]
# ["192.168.0.105 :43433 miku > miku\n", ["AF_INET", 62000, "192.168.0.105", "192.168.0.105"]]
data = s.recvfrom_nonblock(65535)
string = data[0].chomp!
ip, port = data[1][3].to_s, data[1][1].to_i
clientList << {"ip"=>ip, "port"=> port}
clientList.uniq!
# 各クライアントに向けて返信する
clientList.each{|client|
printf("Server > %-15s:%5d %s\n", client["ip"], client["port"], string)
# 実際に返信する。send("文字列", フラグ, "送信先IPアドレス", "送信先ポート")
sock.send(sprintf("%-15s:%5d %s\n", client["ip"], client["port"], string), 0, client["ip"], client["port"])
}
}
end
end

sock.close


次にクライアント側を作成する。

#!/usr/bin/env ruby
#-*- encoding: utf-8 -*-

require "socket"

if ARGV[0] == nil
puts "ex) ./client.rb miku"
exit 1
end

NAME = ARGV[0]
SERVERIP = "192.168.0.105"
SERVERPORT = "62000"

# UDPのソケットを作成
sock = UDPSocket.new
# バインドするIPアドレスとポートを自動で割り当てる
sock.bind("0.0.0.0", 0)


# サーバからの情報を受け取り表示するスレッドを作成
thread = Thread.new {
while true
# sockに出力が来るのを5秒待つ。
# 来なかったらnilを返す。
sel = IO::select([sock], nil, nil, 5)
if sel != nil
sel[0].each{|s|
data = s.recvfrom_nonblock(65535)
puts data[0].chomp!
}
end
end
}

# サーバに情報を送信するループ
while true
string = STDIN.gets.chomp!
sock.send(sprintf("%-5s> %s\n", NAME, string), 0, SERVERIP, SERVERPORT)
end

sock.close



実際に使用すると、このようになった。
UDPサーバ/クライアント実行結果


これだけで、簡単なチャットサーバ/クライアントが作成できた。
Cで書いたものを見たあとだと、Rubyが簡単過ぎて泣ける。

2010年3月8日月曜日

Debian(PPC)でLinux-VServerを使ってみる

Debianでのchroot環境について調べていたところ、chrootよりずっといい感じのLinux-VServerなるものが見つかったので、忘れないように書いておく。
感じとしては、FreeBSDのJailと似たようなもの…な気がする。

・aptitudeでvserver用のカーネルとツールをインストール。
# aptitude install linux-image-2.6-vserver-powerpc \
> util-vserver \
> vserver-debiantools


・vserver用カーネルで起動するため、再起動。
# reboot


・vserver用ファイルを準備。
vserver名をmikuとし、ホスト名をmiku.v.hachune.net、ディレクトリツリーの場所を/vsv/miku、ネットワークインターフェースにeth2を使用、1番のエイリアス(eth2:1)として10.39.39.100/24を割り当てる。ループバックにはlo:1を使用する。
"--"以降はdebootstrapのオプション。ここではDebian Lennyをftp.jaist.ac.jpから取得するように設定する。

# vserver miku build \
> --hostname miku.v.hachune.net \
> --rootdir=/vsv/miku --context 39 \
> --interface 1=eth2:10.39.39.100/24 --interface 1=lo:127.0.0.1/8\
> -m debootstrap -- -d lenny -m ftp://ftp.jaist.ac.jp/pub/Linux/Debian/


…これだけ。
後は、通常のDebian同様、起動して入ってサーバを設定する。
日本語を使用したい場合はaptitude install localesするといい。
・vserverを開始
# vserver miku start
・vserverを停止
# vserver miku stop
・vserverに入る
# vserver miku enter
・vserverの状態を確認
# vserver miku status
・vserverを削除
# vserver miku delete


詳しくはmanのvserver、verver-build、vserver-statあたりを参考にすると良いらしい。
一部デバイスの関係で正しく動作しないアプリケーションがあるようだが、chrootだけよりいい感じ。
基本システムのみなので、インストール直後の容量が252MBと、かなり小さめなのも嬉しい。
Mac Mini G4では、XenやVMwareが使えないしな…。

linux-vserver.org
http://linux-vserver.org/


※追記
動くものと動かないものは以下のとおり。

動作確認:
bind9
apache

動作せず:
OpenVPN: /dev/net/tunが無いため不可。
dhcp3-server: eth2:1を正しく認識しない…?


その他必要そうな設定
・TimeZoneの設定
# dpkg-reconfigure tzdata

・digが必要な場合
# aptitude install dnsutils

2010年3月5日金曜日

OpenBSDのカーネルを再構築

これまた忘れそうなので書いておく。


・適当なところからカーネルのソース等を持ってきておく。
今回は、以下の4つを取得。
ftp://ftp.jaist.ac.jp/pub/OpenBSD/4.6/src.tar.gz
ftp://ftp.jaist.ac.jp/pub/OpenBSD/4.6/sys.tar.gz
ftp://ftp.jaist.ac.jp/pub/openBSD/4.6/ports.tar.gz
ftp://ftp.jaist.ac.jp/pub/OpenBSD/4.6/xenocara.tar.gz


・ダウンロードしたファイルを展開する。
# cd /usr/src
# tar xzf /home/miku/sys.tar.gz
# tar xzf /home/miku/src.tar.gz
# cd /usr
# tar xzf /home/miku/xenocara.tar.gz
# tar xzf /home/miku/ports.tar.gz


・カーネルをビルド
# cd /usr/src/sys/arch/i386/conf/
# cp GENERIC.MP HACHUNE
→カーネル設定の編集はここで。
MPカーネル(マルチプロセッサ用のカーネル)の設定は、殆どがGENERICカーネルをincludeしたものなので、細かい設定はGENERICを編集して変更する。

# config HACHUNE
Don't forget to run "make depend"
# cd ../compile/HACHUNE
# make depend
# make
→ EeePC(Atom N270、DDR2-667 2GB、20GB IDE-USB HDD)だと、大体20〜30分位で終了。

・Buildしたカーネルをインストール(古いものをbsd.oldとしてとっておく)
# mv /bsd /bsd.old
# cp bsd /bsd

・再起動
# reboot
→もしコケたらブートローダーでbsd.oldを指定して起動


・ユーザーランドのビルド
# cd /usr/src
# make obj
# make build
→ カーネルのビルドよりずーーっと時間が掛かるのでゆっくり待つ。

・再起動
# reboot



…と、ここまでやっていたHDDがクラッシュ。
実験用HDDだからまぁ良いのだが、やっぱり凹むな…

2010年2月28日日曜日

DebianでNFSサーバ&クライアント

ググれば大量に出てくるものを書いてもなんかなぁ...と思いつつも、
そんなことを考えていると全然Blogが書けないということに気がついたので、もう遠慮なく書くことにする。

今回は、かがみねサーバ(kagamine.h.hachune.net)の/home/mikuをめぐりねサーバ(megurine.h.hachune.net)の/home/mikuにマウントする。

まず、かがみねサーバ(NFS Server)の設定。
% sudo aptitude install nfs-kernel-server
% sudo vi /etc/exports
で、以下を追加する。
/home/miku *.h.hachune.net(ro,sync,no_subtree_check)


・ディレクトリをエクスポート(再エクスポート)する。
% sudo exportfs -ar
(nfs-kernel-serverを再起動する方法もある)

・公開できているか確認する。
% showmount -e


次に、めぐりねサーバ(NFS Client)の設定を行う。
/etc/fstabに以下を追加し、sudo mount -aする。
kagamine.h.hachune.net:/home/miku /home/miku nfs ro,sync 0 0

これでマウントできた。
サーバ側でshowmount -aコマンドを打つと、マウント状況が確認できる。
簡単だけれど、セキュアではないな…


/etc/exportsの書式は、man exports、
/etc/fstabのNFS関連の情報は、man nfs、
NFSエクスポートリスト操作コマンドexportfsの情報は、man exportfs
マウント情報確認コマンドshowmountの情報は、man showmount
を見ると良い。

Ruby1.9.1のcursesでUTF-8文字列を表示

RubyのCursesでプレイリスト操作ツールを作成しようとしたところ、文字化けして全然使い物にならないということが判明。ついでなので1.9.1にパッチを当ててビルドしてみることにする。

・ext/curses/curses.cを編集

追加:
+ #include "locale.h"

Init_curses関数内にsetlocaleを追加:
Init_curses()
{
+ setlocale(LC_ALL, "");


・ext/curses/extconf.rbを編集(ncurseswを探すようにする)

削除:
-if have_header(*curses=%w"ncurses.h") and have_library("ncurses", "initscr")
追加:
+if have_header(*curses=%w"ncurses.h") and
+ ( have_library("ncursesw", "initscr") or have_library("ncurses", "initscr") )
+ make=true
削除:
-elsif have_header(*curses=%w"ncurses/curses.h") and have_library("ncurses", "initscr")
追加:
+elsif have_header(*curses=%w"ncurses/curses.h") and
+ ( have_library("ncursesw", "initscr") or have_library("ncurses", "initscr") )
+ make=true


・ruby-1.9.1-p378.tar.bz2をダウンロード
・ libncursesw-devをaptからインストール
% sudo aptitude install libncursesw-dev

・ビルド。-O2だと何故か途中でコケるらしいので、-O3にする。
% optflags="-O3 -pipe" ./configure --prefix=/usr/ruby19 --program-suffix=19

2010年2月9日火曜日

CでOpenMPを使ってみる

せっかくマルチコアCPUがあることだし、全コアを全力で使えるプログラムを作ってみたいと考えていたが、いろいろ面倒で諦めがちだった。しかし、C/C++にはOpenMPという便利なものがあると聞いて、調べみたところ、本当に便利だったのでここに纏めてみる。


OpenMPを利用するには、GCC 4.2以降が必要で、コンパイル時に-fopenmpオプションを付ける必要がある。
% gcc openmp_test.c -o openmp_test -fopenmp

また、今回OpenMP関連で使用した関数とその役割は以下のとおり。
omp_get_thread_num() … 現在実行されているスレッドの番号を返す
omp_set_num_threads(10) … スレッド数を10に指定(通常はCPUコア数から自動的に割り振られる)


まずは一番簡単なスレッド作成方法。
スレッド処理したい関数の前に#pragma omp parallelを書くだけ。

#include<stdio.h>

int main(void){
int i;

#pragma omp parallel
for(i=0; i<20; i++){
printf("Thread %d : %d\n", omp_get_thread_num(), i);
}
return 0;
}


これをコンパイルし実行すると、

miku@kagamine:~/c-lang$ ./openmp_1
Thread 0 : 0
Thread 0 : 1
Thread 0 : 2
Thread 0 : 3
Thread 0 : 4
Thread 1 : 0
Thread 1 : 1
Thread 1 : 2
Thread 1 : 3
Thread 1 : 4

となったり、

miku@kagamine:~/c-lang$ ./openmp_1
Thread 1 : 0
Thread 1 : 1
Thread 1 : 2
Thread 1 : 3
Thread 1 : 4
Thread 0 : 0

となったりする。なにやら同時に処理されているように見え、スレッドの実験としては成功していることが分かる。
しかし、結果が安定していないため、このままではあまり使い物にならない。
開始したスレッド全てから変数iが参照され、変更されるためこうなってしまう。



そこで、変数iをスレッド内でプライベートに使うようにしてみる。

#include<stdio.h>

int main(void){
int i;

// 変数iをスレッド内プライベートとして渡し、スレッドを開始させる
#pragma omp parallel private(i)
for(i=0; i<3; i++){
printf("Thread %d : %d\n", omp_get_thread_num(), i);
}

return 0;
}

これを実行すると…

miku@kagamine:~/c-lang$ ./openmp_2
Thread 0 : 0
Thread 1 : 0
Thread 1 : 1
Thread 1 : 2
Thread 0 : 1
Thread 0 : 2

iの値はそのスレッド内のみの値として扱われ、
スレッド毎にi++されていることが分かる。



通常、全スレッドが全く同じ処理を繰り返しても意味が無い。
そこで、グローバルな変数iを操作するときのみ、排他処理を行わせる。

#include<stdio.h>

// 変数iをグローバルとして渡すが、printfとi++の部分を排他動作させる
int main(void){
int i;

i = 0;
#pragma omp parallel
while (i<10){
// 排他処理部分をブロックで指定
#pragma omp critical
{
printf("Thread %d : %d\n", omp_get_thread_num(), i);
i++;
}

sleep(1);
}
return;
}

これを実行すると…

miku@kagamine:~/c-lang$ ./openmp_3
Thread 1 : 0
Thread 0 : 1
Thread 1 : 2
Thread 0 : 3
Thread 1 : 4
Thread 0 : 5
Thread 1 : 6
Thread 0 : 7
Thread 1 : 8
Thread 0 : 9

iの値が、両スレッドで1づつ増えていっているのが分かる。

ただ、このテストプログラムには問題がある。
while (i<0)の判定後、whileループの中で別スレッドがiに値を追加し、
printf()するときにiの値が10または10以上になってしまうことがある(sleep(1)を外すと頻繁に発生する)。
この辺りを、正しく処理させるようにしないと、「数回に1回だけ何故かコケる」なんて厄介なバグになってしまうので、注意したい。



何でもかんでも排他処理させてしまうと、他の関数で実行中のスレッドにまで影響が及び、何かしらの問題(デッドロック等)が発生する可能性がある。
そこで、できる限り排他処理を使わないようにしてみる。
(ついでに、しっかり4コア使ってくれるのか確かめるため、dummy関数を用意した)

#include<stdio.h>
#include<unistd.h> // usleep()
#include<stdlib.h>


// ダミー処理関数(CPUに負荷を掛ける)
void dummy(int number){
int n, i, tmp;
int array[number];
for(i=0; i<number; i++){
array[i] = i;
}

for (n=0; n<number; n++){
for (i=0; i<number - 1; i++){
if (array[i] < array[i+1])
{
tmp = array[i];
array[i] = array[i+1];
array[i+1] = tmp;
}
}
}
return;
}


// 変数iをグローバルとして渡すが、printfとi++、dummy(10000)の部分をシングルスレッド動作させる
int main(void){
int i, while_count;

i = 0;
while_count = 0;

#pragma omp parallel
while (<<100){

// ブロック内をシングルスレッド動作させる
#pragma omp single
{
printf("Thread %d : %d\n", omp_get_thread_num(), i);
i++;
dummy(10000);
}
printf("Thread %d : loop...\n", omp_get_thread_num());
usleep(10);
while_count++;
}

printf("loop Count: %d\n", while_count);
return;
}



また、「ブロック内を他のスレッドが実行中なら、ブロック内の実行をスキップする」ということも可能。

#include<stdio.h>
#include<unistd.h> // usleep()
#include<stdlib.h>


// ダミー処理関数(CPUに負荷を掛ける)
void dummy(int number){
int n, i, tmp;
int array[number];
for(i=0; i<number; i++){
array[i] = i;
}

for (n=0; n<number; n++){
for (i=0; i<number - 1; i++){
if (array[i] < array[i+1])
{
tmp = array[i];
array[i] = array[i+1];
array[i+1] = tmp;
}
}
}
return;
}


// 変数iをグローバルとして渡すが、printfとi++、dummy(10000)の部分をシングルスレッド動作させる。
// もしその部分が別スレッドで処理中ならスキップする
int main(void){
int i, while_count;

i = 0;
while_count = 0;

#pragma omp parallel
while (i<100){

// single nowait : 他のスレッドがブロック内を実行中だったらスキップ
#pragma omp single nowait
{
printf("Thread %d : %d\n", omp_get_thread_num(), i);
i++;
dummy(10000);
}
printf("Thread %d : loop...\n", omp_get_thread_num());
usleep(10);
while_count++;
}
printf("loop Count: %d\n", while_count);
return;
}


#pragma omp singleと、#pragma omp single nowaitの場合を、
実際にコンパイルして実行、比較してみると、多分違いが分かる…と思う。
また、omp_set_num_threads(スレッド数)で、スレッド数を変更しながらいろいろ試してみるのも良い。


結構長い間やっていた筈なのに、C言語のBlog投稿は今回が初めて。
やっているけど書いていないことって、かなり多いな…。

2010年1月30日土曜日

様々なOSでRAMDiskを使ってみる

/ramに32MBのRAMDiskを作る、/etc/fstabの設定を比較してみた。
実験に使用したOSは、Linux(Debian 5.0 Lenny)、FreeBSD 8.0、OpenBSD 4.6の3つ。

Linux
tmpfs /ram tmpfs rw,size=32m 0 0

FreeBSD
md /ram mfs rw,-s32m 0 0

OpenBSD
swap /ram mfs rw,-s=65536 0 0


fstabの5列目は、「dumpが必要なファイルシステムであるか」、6列目は、「起動時にfsckを行う必要のあるファイルシステムであるか」であり、RamDiskにはどちらも必要ないので、0とする。

OpenBSDは、サイズで指定するのではなく、ブロック数で指定するので、直感的には分かりづらい感じ。
(試しに-s=32mとしてみたところ、そんなサイズ知らねぇよ、と言われた)
また、65535と1ブロック少ない値を設定したところ,
mount_mfs: reduced number of fragments per cylinder group from 8184 to 8112 to enlarge last cylinder group
と言われるので、おとなしく8192で割り切れる値にしておいた方が良さそう。


コマンドだと、こんな感じ。
Linux
# mount tmpfs -o rw,size=32m /ram

FreeBSD
# mount_mfs -s 32m -o rw md /ram

OpenBSD
# mount_mfs -s 65536 -o rw swap /ram

2009年12月13日日曜日

DebianとBIND9でDNSサーバを作成

サーバの台数が増え、/etc/hostsにいちいち書くのが流石に面倒になってきた。そこで、何度か挑戦して諦めることを繰り返していたBIND9をいい加減覚えようとやる気を出してみた。

今回は、できる限りデフォルト設定を利用し、基本のみを設定することを目標にして纏めてみる。
外部には公開せず、LAN内部のみで利用することを前提として作成する。よって、公開サーバを立てる場合は、これらの設定に加え、セキュリティ対策が必要となる。


サーバとして使用するのは、VPNサーバとしてもお世話になっているMac Mini(中身はDebian 5.03。ホスト名megurine)。
ネットワークの構造はこんな感じ。



ネットワークアドレス 192.168.0/24
ネットワーク名 h.hachune.net
router 192.168.0.1
hatsune 192.168.0.100
oldfox 192.168.0.101
hachune 192.168.0.102
360 192.168.0.103
megurine 192.168.0.104
kagamine 192.168.0.105


この中で、hatsune、hachune、kagamine、megurineには、それぞれmiku、eee、rin、lukaとCNAMEレコード(Alias)を付ける。
更に、megurineにはAレコードでnsとも付けておく。


1. BIND9をインストール


Debianなので
% sudo aptitude install bind9
で一発インストール可能。

この時、BINDを実行するグループ bindとユーザ bindが、自動的に追加される。


2. named.confの変更


…と思ったが、named.confで弄るところは無い模様。

一度設定したら滅多に変更することの無い、ルートサーバ、ループバックアドレス正引き・逆引きの設定がnamed.confに既に用意されていて、ドメイン設定はnamed.conf.local、BINDのオプションはnamed.conf.optionsに書くように、とのことらしい。

※named.confの内容(変更なし)

// This is the primary configuration file for the BIND DNS server named.
//
// Please read /usr/share/doc/bind9/README.Debian.gz for information on the
// structure of BIND configuration files in Debian, *BEFORE* you customize
// this configuration file.
//
// If you are just adding zones, please do that in /etc/bind/named.conf.local

include "/etc/bind/named.conf.options";

// prime the server with knowledge of the root servers
zone "." {
type hint;
file "/etc/bind/db.root";
};

// be authoritative for the localhost forward and reverse zones, and for
// broadcast zones as per RFC 1912

zone "localhost" {
type master;
file "/etc/bind/db.local";
};

zone "127.in-addr.arpa" {
type master;
file "/etc/bind/db.127";
};

zone "0.in-addr.arpa" {
type master;
file "/etc/bind/db.0";
};

zone "255.in-addr.arpa" {
type master;
file "/etc/bind/db.255";
};

include "/etc/bind/named.conf.local";


※/etc/bind/db.rootの内容(変更なし)

; This file holds the information on root name servers needed to
; initialize cache of Internet domain name servers
; (e.g. reference this file in the "cache . "
; configuration file of BIND domain name servers).
;
; This file is made available by InterNIC
; under anonymous FTP as
; file /domain/named.root
; on server FTP.INTERNIC.NET
; -OR- RS.INTERNIC.NET
;
; last update: Feb 04, 2008
; related version of root zone: 2008020400
;
; formerly NS.INTERNIC.NET
;
. 3600000 IN NS A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4
A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:BA3E::2:30
;
; formerly NS1.ISI.EDU
;
. 3600000 NS B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201
;
; formerly C.PSI.NET
;
. 3600000 NS C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12
;
; formerly TERP.UMD.EDU
;
. 3600000 NS D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET. 3600000 A 128.8.10.90
;
; formerly NS.NASA.GOV
;
. 3600000 NS E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10
;
; formerly NS.ISC.ORG
;
. 3600000 NS F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241
F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2f::f
;
; formerly NS.NIC.DDN.MIL
;
. 3600000 NS G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4
;
; formerly AOS.ARL.ARMY.MIL
;
. 3600000 NS H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET. 3600000 A 128.63.2.53
H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::803f:235
;
; formerly NIC.NORDU.NET
;
. 3600000 NS I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17
;
; operated by VeriSign, Inc.
;
. 3600000 NS J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30
J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:C27::2:30
;
; operated by RIPE NCC
;
. 3600000 NS K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129
K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fd::1
;
; operated by ICANN
;
. 3600000 NS L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42
;
; operated by WIDE
;
. 3600000 NS M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33
M.ROOT-SERVERS.NET. 3600000 AAAA 2001:dc3::35
; End of File


※/etc/bind/db.localの内容(変更なし)

; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA localhost. root.localhost. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS localhost.
@ IN A 127.0.0.1
@ IN AAAA ::1


※/etc/bind/db.127の内容(変更なし)

; BIND reverse data file for local loopback interface
;
$TTL 604800
@ IN SOA localhost. root.localhost. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS localhost.
1.0.0 IN PTR localhost.


※/etc/bind/db.0の内容(変更なし)

; BIND reverse data file for broadcast zone
;
$TTL 604800
@ IN SOA localhost. root.localhost. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS localhost.


※/etc/bind/db.255の内容(変更なし)

; BIND reverse data file for broadcast zone
;
$TTL 604800
@ IN SOA localhost. root.localhost. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS localhost.



3. named.conf.localの変更


ようやく設定ファイルを弄ることになる。
ここでは、/etc/bind/zones.rfc1918を参考にしながら、named.conf.localのみの変更を行う。
h.hachune.netの正引きと、そのネットワークの逆引き168.192.addr-arpaの設定を行う。

※zones.rfc1918の内容(変更なし)

zone "10.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };

zone "16.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "17.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "18.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "19.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "20.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "21.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "22.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "23.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "24.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "25.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "26.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "27.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "28.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "29.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "30.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
zone "31.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };

zone "168.192.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };


※named.conf.local(変更前)

//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";



※named.conf.local(変更後)

//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";


zone "h.hachune.net"{
type master;
file "/etc/bind/h.hachune.net/h.hachune.net.zone";
};

zone "0.168.192.in-addr.arpa"{
type master;
file "/etc/bind/h.hachune.net/h.hachune.net.rev";
};




4. /etc/bind/h.hachune.net/h.hachune.net.zoneの設定


h.hachune.netの正引きの設定を行う。
ここでは、/etc/bind/db.emptyを参考に、設定を行う。

※/etc/bind/db.emptyの内容(変更なし)

; BIND reverse data file for empty rfc1918 zone
;
; DO NOT EDIT THIS FILE - it is used for multiple zones.
; Instead, copy it, edit named.conf, and use that copy.
;
$TTL 86400
@ IN SOA localhost. root.localhost. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
86400 ) ; Negative Cache TTL
;
@ IN NS localhost.


※/etc/bind/h.hachune.net/h.hachune.net.zoneの内容

$TTL 86400
@ IN SOA ns.h.hachune.net. lefay.g.hachune.net.(
200912120 ;
3600 ;
900 ;
604800 ;
86400 ;
)
@ IN NS ns.h.hachune.net.
@ IN A 192.168.0.104

router IN A 192.168.0.1

hatsune IN A 192.168.0.100
miku IN CNAME hatsune

oldfox IN A 192.168.0.101

hachune IN A 192.168.0.102
eee IN CNAME hachune

360 IN A 192.168.0.103

megurine IN A 192.168.0.104
luka IN CNAME megurine
ns IN A 192.168.0.104

kagamine IN A 192.168.0.105
rin IN CNAME kagamine



5. /etc/bind/h.hachune.net/h.hachune.net.revの設定


正引きの設定と同様に、逆引きの設定も行う。

$TTL 86400

@ IN SOA ns.h.hachune.net. lefay.g.hachune.net.(
200912120 ;
3600 ;
900 ;
604800 ;
3600 ;
)

@ IN NS ns.h.hachune.net.
1 IN PTR router.h.hachune.net.
100 IN PTR hatsune.h.hachune.net.
101 IN PTR nec.h.hachune.net.
102 IN PTR hachune.h.hachune.net.
103 IN PTR 360.h.hachune.net.
104 IN PTR megurine.h.hachune.net.
105 IN PTR kagamine.h.hachune.net.


以上の設定が終了したら、BINDデーモンの再起動を行う。
% sudo /etc/init.d/bind9 restart
もしうまく起動しない場合は、% sudo tail /var/log/syslogして、どこでエラーが発生しているのか確認する。


6. 正しく設定が反映されているか確認


デーモンが正しく再起動出来たら、digコマンドを利用しレコードを確認する。

※正引きレコードの確認

master@megurine:/etc/bind$ dig @127.0.0.1 miku.h.hachune.net

; <<>> DiG 9.5.1-P3 <<>> @127.0.0.1 miku.h.hachune.net
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19223
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;miku.h.hachune.net. IN A

;; ANSWER SECTION:
miku.h.hachune.net. 86400 IN CNAME hatsune.h.hachune.net.
hatsune.h.hachune.net. 86400 IN A 192.168.0.100

;; AUTHORITY SECTION:
h.hachune.net. 86400 IN NS ns.h.hachune.net.

;; ADDITIONAL SECTION:
ns.h.hachune.net. 86400 IN A 192.168.0.104

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 13 02:41:46 2009
;; MSG SIZE rcvd: 107


※逆引きレコードの確認

master@megurine:/etc/bind$ dig @127.0.0.1 -x 192.168.0.100

; <<>> DiG 9.5.1-P3 <<>> @127.0.0.1 -x 192.168.0.100
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24508
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;100.0.168.192.in-addr.arpa. IN PTR

;; ANSWER SECTION:
100.0.168.192.in-addr.arpa. 86400 IN PTR hatsune.h.hachune.net.

;; AUTHORITY SECTION:
0.168.192.in-addr.arpa. 86400 IN NS ns.h.hachune.net.

;; ADDITIONAL SECTION:
ns.h.hachune.net. 86400 IN A 192.168.0.104

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 13 02:42:16 2009
;; MSG SIZE rcvd: 112


※キャッシュサーバの確認

master@megurine:/etc/bind$ dig @127.0.0.1 crypton.co.jp.

; <<>> DiG 9.5.1-P3 <<>> @127.0.0.1 crypton.co.jp.
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31873
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

;; QUESTION SECTION:
;crypton.co.jp. IN A

;; AUTHORITY SECTION:
crypton.co.jp. 892 IN SOA dns-b.iij.ad.jp. dns-managers.iij.ad.jp. 63 3600 1800 3600000 900

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Dec 13 02:46:34 2009
;; MSG SIZE rcvd: 93



以上で、とりあえずは使えるDNSサーバができた。
弄ったのは、named.conf.localとh.hachune.net.zone、h.hachune.net.revのみ。
…ここまではそんなに難しくはないんだが…('A`)


・参考
@IT 実用 BIND9で作るDNSサーバ 第2回 すべての基礎、マスター・ゾーンサーバの設定
http://www.atmarkit.co.jp/flinux/rensai/bind902/bind902a.html

2009年8月13日木曜日

Windows 7 x64にMinGW x64環境を構築

折角Windows 7 x64を使っているのに、x86アプリばかり動かしている現状が嫌になったので、MinGW x64をインストールして、Windows x64ネイティブなバイナリを作れるようしようとしていた…のだが、なかなか設定が分からず苦戦していた。

ようやくlameがコンパイルできたので、環境構築手順を纏めてみる。



まず、MinGW-w64環境を構築する。

MinGW-w64のバイナリをhttp://sourceforge.net/projects/mingw-w64/から持ってくる。
私は、現時点の最新版である、mingw-w64-bin_i686-mingw_20090811.zipをダウンロードした。

ダウンロードが終わったら、アーカイブ(zip)を解凍する。
解凍先は、C:\MinGWなど、自分が分かりやすいパスを指定する。
私の場合は、D:\MinGWに解凍した。

解凍後、binフォルダに入っている
x86_64-w64-mingw32-addr2line.exe、x86_64-w64-mingw32-ar.exe......
というファイルを、全て
addr2line.exe、ar.exe......
となるようにリネームする。


一つずつリネームするのが面倒なら、以下の内容のバッチファイルをbinフォルダに作成し、実行すると楽かもしれない。
@echo on
rename x86_64-w64-mingw32-addr2line.exe addr2line.exe
rename x86_64-w64-mingw32-ar.exe ar.exe
rename x86_64-w64-mingw32-as.exe as.exe
rename x86_64-w64-mingw32-c++.exe c++.exe
rename x86_64-w64-mingw32-c++filt.exe c++filt.exe
rename x86_64-w64-mingw32-cpp.exe cpp.exe
rename x86_64-w64-mingw32-dlltool.exe dlltool.exe
rename x86_64-w64-mingw32-dllwrap.exe dllwrap.exe
rename x86_64-w64-mingw32-g++.exe g++.exe
rename x86_64-w64-mingw32-gcc-4.5.0.exe gcc-4.5.0.exe
rename x86_64-w64-mingw32-gcc.exe gcc.exe
rename x86_64-w64-mingw32-gccbug gccbug
rename x86_64-w64-mingw32-gcj.exe gcj.exe
rename x86_64-w64-mingw32-gcov.exe gcov.exe
rename x86_64-w64-mingw32-gfortran.exe gfortran.exe
rename x86_64-w64-mingw32-gprof.exe gprof.exe
rename x86_64-w64-mingw32-jcf-dump.exe jcf-dump.exe
rename x86_64-w64-mingw32-ld.exe ld.exe
rename x86_64-w64-mingw32-nm.exe nm.exe
rename x86_64-w64-mingw32-objcopy.exe objcopy.exe
rename x86_64-w64-mingw32-objdump.exe objdump.exe
rename x86_64-w64-mingw32-ranlib.exe ranlib.exe
rename x86_64-w64-mingw32-readelf.exe readelf.exe
rename x86_64-w64-mingw32-size.exe size.exe
rename x86_64-w64-mingw32-strings.exe strings.exe
rename x86_64-w64-mingw32-strip.exe strip.exe
rename x86_64-w64-mingw32-windmc.exe windmc.exe
rename x86_64-w64-mingw32-windres.exe windres.exe
pause

(最初からgcc.exeのようなファイル名になっている、/mingwフォルダや/x86_64-w64-mingw32フォルダに入っているものを使用しようとすると、コンパイル時に

hatsune@HATSUNE-SERVER ~
$ gcc -v time.c
Using built-in specs.
Target: x86_64-w64-mingw32
Configured with: ../../../build/gcc/gcc/configure --target=x86_64-w64-mingw32 --
prefix=/c/buildbot/vista64-mingw32/mingw-x86-x86_64/build/build/root --with-sysr
oot=/c/buildbot/vista64-mingw32/mingw-x86-x86_64/build/build/root --enable-langu
ages=all,obj-c++ --enable-fully-dynamic-string --disable-multilib
Thread model: win32
gcc version 4.5.0 20090806 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-v' '-mtune=generic'
cc1 -quiet -v -iprefix d:\mingw\mingw\bin\../lib/gcc/x86_64-w64-mingw32/4.5.0/
time.c -quiet -dumpbase time.c -mtune=generic -auxbase time -version -o S:\UserT
emp\hatsune\ccd8FXk1.s
gcc.exe: CreateProcess: No such file or directory

とエラーが発生してしまい、コンパイルできない問題にハマってしまった)





次に、MinGWを使用する上で必要なMSYS環境を構築する。
MSYSバイナリをhttp://sourceforge.net/projects/mingw/から持ってくる。
現時点の最新版である、MSYS-1.0.11.exeをダウンロードした。

ダウンロード後、インストーラーを実行し、MSYSのインストールパスを指定、インストールすると、コマンドプロンプトが開き、
This is a post install process that will try to normalize between your MinGW install if any as well as your previous MSYS installs if any. I don't have any traps as aborts will not hurt anything.
Do you wish to continue with the post install? [yn ]

と出るので"y"を入力。

すると、
Do you have MinGW installed? [yn ]
と出るので、これも"y"を入力。

次に、
Please answer the following in the form of c:/foo/bar.
Where is your MinGW installation?

と出るので、MinGWをインストールしたパスを指定する。
私の場合は、D:/MinGWを指定した。
ここでパスを指定する際に、パスの区切りを"\(円記号・バックスラッシュ)"ではなく"/(スラッシュ)"にする必要があるので注意する。

MSYS Setup

後は、てきとうなCのソースコードを持ってきて、MSYS上でコンパイルして実行する。
lameなら、いつも通り

$ ./configure
$ make
$ make install

とするだけで、コンパイルできる。

タスクマネージャーでそのプロセスを見て、"*32"がプロセス名に付いていなかったら、x64のバイナリが作成・実行出来ているということになる。
lame x64


手順並べるとこんなに簡単なのに、何故あんなに苦労したんだ…('A`)

2009年8月3日月曜日

Win32-Serviceが欲しかったのでRubyGemsをインストール

RubyでWindowsサービスを作成しようと、Win32-Serviceをインストールしようとしたところ、RubyGemsが無いと面倒くさそうだったので、まずはRubyGemsをインストールすることにした。


09.08.03時点で最新のrubygems-1.3.5.zipをダウンロードしてきて解凍する。
コマンドプロンプトを開き、setup.rbを実行。
C:\Users\hatsune\Desktop\rubygems-1.3.5> ruby setup.rb


バージョンを確認して、
C:\Users\hatsune\Desktop\rubygems-1.3.5> gem -v
1.3.5

となれば、インストールに成功していると思われる。

あとは、好きなライブラリをgemsから持ってくることが出来る。
C:\> gem install win32-service



…と思っていても、上手くいかないことがあるのが普通。


今回は、zlibとsslのライブラリが足りないと言われた。
Ruby-mswin32をそのまま使用している場合はまず発生すると思われる。

Ruby-mswin32のインストールを読むと、
「http://jarp.does.notwork.org/win32/にライブラリがあるので、これをインストールしろ」とのこと。


仕方が無いので、ライブラリをインストール。
openssl-0.9.8d-1-mswin32.zipと
zlib-1.1.4-1-mswin32.zipをダウンロードしてくる。
これを、フォルダ階層を維持しつつ、Rubyのバイナリがインストールしてあるフォルダにコピーする。
(\binはC:\Ruby\binへ、\libはC:\Ruby\libへ…という感じに)


これで実行できる…と思い、再度実行すると、今度はssleay32.dllが見つからないと言われた。
"ssleay32.dll"でググったところ、自分でOpenSSLをコンパイルするか、
OpenSSLのWindows用バイナリを配布してくれているサイトから持ってきて、
ssleay32.dllをコピーすればいいらしい。
(コンパイルするのは面倒なので、http://curl.haxx.se/download/openssl_w32vc6-0.9.8g.7zをダウンロード、インストールした。)


これでようやくRubyGemsが動き、Win32-Serviceをインストールすることが出来た。

2009年7月17日金曜日

Rubyで端末のサイズを得る

マルチスレッド対応〜プログラムを作っていて、一覧表示時を行う為に、Rubyで端末のサイズを得るにはどうしたら良いのか、という問題に直面した。

LinuxやBSDでは、stty sizeコマンドを実行して、それを解析し取得する方法もあるが、OSに依存するため使えない。
Sorarisなど、同じコマンドがあっても微妙に結果が違ったりするものもあるので…


以前のバージョンでは、cursesを使って獲得していた。

require "curses"
def gettermsize
Curses::init_screen
x = Curses::cols
y = Curses::lines
Curses::close_screen
return {"x"=>x.to_i, "y"=>y.to_i}
end


この方法も、RubyにCursesライブラリが入っていないと駄目という問題が。
しかも、環境によって、標準出力のバッファリングがおかしくなることがあるという謎の現象が…
標準出力がおかしい件

これを回避するには、標準出力を同期モードにしてやればよいようだった。

STDOUT.sync = true

これをcurses読み込み前に書いておけば、標準出力がプログラムの流れと同期して表示されるようになった。


もっと効率が良く、どのプラットフォームでも同じ結果が得られるものは無いのだろうか…

2009年7月12日日曜日

Google Appsを使ってみる

Googleには、GmailやGoogleサイトといったサービスがあるが、通常はgoogle@gmail.comといった感じに、gmail.comドメインのみを使用することになる。
gmail.comドメインだと、「フリーメールお断り」などといった制限に引っ掛かったり、ローカル部(google@gmail.comのgoogleの部分)に、好きな文字列を使用できないことがある、などの問題がある。

そこで、独自ドメインを使用し、Googleの様々なサービスを使用できるGoogle Appsを使ってみようと思う。

Google Appsを使うメリットとして、
・無料
・独自ドメインを使用できる(MXレコードを設定できれば、ダイナミックDNSサービスのものでも可。CNAMEレコードも設定できれば楽な上に、Googleサイトで独自ドメインが使えるようになる)
・自宅サーバーを運用する必要が無くなる
・セキュリティ等にあまり悩まされなくなる
・固定IPを持っていなくても、安定してメールを受け取ることが出来る(非固定IPの場合、ドメインにIPアドレスを関連付け直すのにある程度の時間が必要なので、その間メールが正しく配送されない状態になってしまう)

などがある。

欠点は、
・Googleがサービスを停止したら終わり
・Gmailの広告がいろんな意味で怖い
・容量がStandard Editionで7.3GB(09/07/12現在)

といったところだろうか。

エディション別機能詳細などは、http://www.google.com/a/help/intl/ja/users/user_features.htmlやhttp://www.google.com/a/help/intl/ja/admins/editions_spe.htmlなどで見れる。
まぁ普通の人はStandard Editionで問題無いと思う。




まず最初に、http://www.google.co.jp/apps/intl/ja/group/index.htmlにアクセスし、使用するドメイン名を入力する。自分の持っているドメインであれば、サブドメインでも構わない。
ここでは、hachune.netのサブドメイン、g.hachune.netを入力する。
取りたいドメインさっさと決めろって言われて…
.com以外空いてたんでつい…(´・ω・`)

apps-1



アカウント管理者と組織の情報の入力を行う。
メールアドレスは、現在使用出来ているアドレスにする必要がある。gmailでも大丈夫だった。
apps-2



管理者アカウントの設定を行った後、利用規約をよく読んで同意する。
apps-3



同意すると、ドメイン管理画面に進む。
まずは、ドメイン所有権の確認を行う。
apps-4



ドメイン所有権の確認方法には、CNAMEレコードの変更と指定されたHTMLファイルのアップロードの二通りある。
CNAMEレコードの変更では、DNSサーバーにgooglexxxxxxxxxxxxxxx.hachune.net(xx…の部分はドメイン名によって違う)というCNAMEレコードを設定して、所有権を確認する。
apps-6

value-domain.comでドメイン名を取得し、value-domain.comのDNSサーバーを使用しているなら、value-domainにログインし、DNSレコード/URL転送の変更の設定フィールドに、
cname googlexxxxxxxxxxxxxxx google.com.
と設定を書き込み、保存する。
google.comの最後にピリオドを付けるのを忘れると、google.com.hachune.netを参照してしまうので注意する。
私の場合は、サブドメインgを使っているので、
cname googlexxxxxxxxxxxxxxx.g google.com.
となる。
適用されるまで少々時間が掛かる場合もあるが、気長に待ってね(´・ω・`)

CNAMEレコード ルックアップは以下で行える。
http://www.google.com/support/a/bin/answer.py?hl=jp&answer=93595
この確認ツールで確認すると、設定が間違っていなければ、
apps-7
のように表示される。


HTMLファイルのアップロードでは、自宅サーバーにApacheやIISを導入し、Google Appsで使用するドメインのルートに、指定された内容を書き込んだgooglehostedservice.htmlを用意する必要がある。CNAMEレコードを変更できない場合は、こちらを行う。
apps-5



ドメイン所有権の確認が終われば…
apps-8
アクティブキタ――(゚∀゚)――!!




次に、今回の主要目的、メールの設定を行う。
メールを有効にするをクリックすると、MXレコードについての説明が表示される。
apps-9
valuedomainで、サブドメインgに来たメールを、指定されたGoogleのサーバーへ転送する場合、
mx ASPMX.L.GOOGLE.COM. 10 g
mx ALT1.ASPMX.L.GOOGLE.COM. 20 g
mx ALT2.ASPMX.L.GOOGLE.COM. 20 g
mx ASPMX2.GOOGLEMAIL.COM. 30 g
:
:
といった感じに設定する。
適用されるまでCNAMEレコード同様少々時間が掛かるが、気長に待つ。

使用できるサーバーと優先順位は、以下の通り。

ASPMX.L.GOOGLE.COM. 10
ALT1.ASPMX.L.GOOGLE.COM. 20
ALT2.ASPMX.L.GOOGLE.COM. 20
ASPMX2.GOOGLEMAIL.COM. 30
ASPMX3.GOOGLEMAIL.COM. 30
ASPMX4.GOOGLEMAIL.COM. 30
ASPMX5.GOOGLEMAIL.COM. 30


設定が正しければ、
apps-10
Googleのサーバーをアップデートしています…というメッセージが出る。
そして数十分後、
apps-11
キタ━ヽ(ヽ(゚ヽ(゚∀ヽ(゚∀゚ヽ(゚∀゚)ノ゚∀゚)ノ∀゚)ノ゚)ノ)ノ━!!!!




この状態でも独自メールアドレスにアクセスできるが、
アカウントのページを開くときにはhttp://mail.google.com/a/g.hachune.netという感じの、長いアドレスになってしまうのが微妙ということで、このアドレスも変更してみる。
apps-12
「URLを変更」をクリックし、メールのログインページにリダイレクトするアドレスを入力。
apps-13
再び、CNAMEレコードの設定を行う。
apps-14
mail.g.hachune.netをghs.google.comのCNAMEとするので、value-domainのDNSサーバー設定の場合は、
cname mail.g ghs.google.com.
とする。ここでもghs.google.com.の最後のピリオドを忘れないように気を付ける。




あとで設定するのも面倒なので、ここでGoogleサイトやGoogleカレンダー、Googleドキュメントのドメインも設定した。
apps-15

全ての設定が終わると、value-domainのDNSレコードは、

a g 220.108.47.247
cname googlefffffffffb909140.g google.com.
cname mail.g ghs.google.com.
cname site.g ghs.google.com.
cname cal.g ghs.google.com.
cname docs.g ghs.google.com.
mx ASPMX.L.GOOGLE.COM. 10 g
mx ALT1.ASPMX.L.GOOGLE.COM. 20 g
mx ALT2.ASPMX.L.GOOGLE.COM. 20 g
mx ASPMX2.GOOGLEMAIL.COM. 30 g
mx ASPMX3.GOOGLEMAIL.COM. 30 g
mx ASPMX4.GOOGLEMAIL.COM. 30 g
mx ASPMX5.GOOGLEMAIL.COM. 30 g

となった。



※おまけ Google Appsのアカウントでpidginを使う
「アカウント」タブ→Manage Accounts→Add...
pidgin-1
プロトコル: Google トーク
ユーザー名: Appsのユーザー名
ドメイン名: Appsに登録したドメイン名
パスワード: Appsと同じパスワード


次に「拡張」タブを開き、
pidgin-2
サーバーへ接続: talk.google.com
とする。
それ以外はデフォルト設定。
これで使える…ハズ。



…しかし、以前記事でとりあえず使ったhachune.netドメインを、本当に取ることになるとは…'`,、('∀`) '`,、
Googleで"hachune.net"を検索したところ、
hachune.netの検索結果 2 件中 1 - 2 件目 (0.06 秒)
で、出てきたのは自分のブログだけだったので…使っちゃっていいんだよね…(;´д`)?

2009年7月4日土曜日

VMware Server 2をUbuntuにインストール

長い間、期限の切れたVMware Workstationで仮想マシンイメージを作成し、VMware Playerで起動という、激しく面倒くさいことをしていた。だが、ホストOSが起動したら、自動で仮想ゲストOSも起動する機能が必要になってきたので、VMware Serverを使ってみることにした。




まずは、VMware Server 2のLinux版をダウンロードしてくる。

http://www.vmware.com/jp/products/server/を開き、ダウンロードをクリック、"Register for your FREE Download"とあるので、名前とメールアドレスを入力、その他の情報を入力し、ユーザー登録するとダウンロードできる。
登録したメールアドレスにVMware Serverのアクティベーションに関する情報が送られてくるので、正しいメールアドレスを登録するように注意する。

今回はUbuntu x86_64に環境を構築する、ということなので、The core application needed to run VMware Server 2, 64-bit versionをダウンロードしてくる。



ダウンロードが終了したら、書庫を解凍、管理者権限でvmware-install.plを実行する。
インストール時、基本的には全部そのままEnter(デフォルト設定)で構わないが、
The current administrative user for VMware Server is ''. Would you like to
specify a different administrator?

と、VMware Serverの管理環境にログインするユーザーをどうするか聞かれる。
デフォルトでrootに設定されているが、Ubuntuでは通常rootアカウントにパスワードが設定されておらず、管理環境にはsudoを使ってログインということもできない為(Firefox等のブラウザ上で操作)、この設定だけ変更する必要があった。(デフォルト(root)のままでも、rootパスワードを変更(% sudo passwd root)すればVMware Serverの管理環境へログインできるが…)




何も問題が発生せずにインストールが終了したら、https://localhost:8333/にアクセス(httpsを使用したくないならhttp://localhost:8222/)する。

httpsでアクセスすると、

といった感じに怒られて、アクセスできない。
仕方が無いので、Firefox3の編集→設定→詳細タブ→証明書を表示→サーバー証明書→例外を追加…を開き…


https://localhost:8333/を入力、証明書を取得し、この証明書のセキュリティ例外を承認する。




こんな感じの画面が表示されれば、たぶん大丈夫…だと思う。
ここで、先ほど設定したユーザー名と、そのユーザーのログインパスワードを入力し、VMWareServerのログインを行う。

このとき使用するブラウザは、Firefoxが一番無難だと思われる。

それ以外のブラウザ(Operaなど)だと、コンソールが表示できない等の問題が発生して、まともに使用することができない。

Operaダメなのか…(´・ω・`)





Create Virtual Machineから、VMware Workstation等と同じ感じで、ゲストOSを設定できる。
Permisssionsタブから、管理環境でのアクセス権を設定することも可能。
間違ってrootで入るように設定してしまった場合も、ここで修正できる。




設定後、コンソールを開こうとすると、The VMware Remote Console Plug-in is not installed or could not be found.Please install the VMware Remote Console Plug-in to access this virtual machine's console.と、怒られてしまう。
install plug-inをクリックし、Firefox用のアドオンをインストールし、Firefoxを再起動する。


この時、「あなたのコンピューターを保護するため、Firefoxはこのサイト(localhost)はソフトウェアのインストールを要求出来ない設定になっています」と出るが、そのまま許可するしかないので、許可。



後は、VMware Playerと大体同じ感覚で、OSのセットアップ、管理を行える。





その他に分かった事は、
・ホストOS起動時のゲストOSの挙動は、Edit Virtual Machine Startup/Shutdown Settingsから行うことができる。
・仮想環境構築に必要なファイル(OSのisoイメージなど)は、指定したデータストア(デフォルトでは/var/lib/vmware/Virtual Machines)からのみ読み込める。ネットワークドライブなども指定可能。
ということ位か。

ネットワークを使用してサーバーのハードウェアを管理できるのは、予想以上に便利。
WindowsのVMware Playerも、VMware Serverに切り替えるか…('A`)

2009年3月26日木曜日

Ruby 1.91がなかなか厄介な件

1月にRubyのバージョンが0.1上がり、1.91になった…のは良いのだが、
ところどころ微妙に変更されていて、大変なことに…。

とりあえず、Stringクラスのsizeメソッドの変更が、地味に痛い。
#-*- coding: windows-31j -*-

str = "あいう"
puts str.size


このスクリプトを、Ruby1.8で実行すると、
C:\Users\hatsune\Desktop>test.rb
6


となっていたのだが、
Ruby1.9で実行すると、
C:\Users\hatsune\Desktop>ruby19 test.rb
3


のように、sizeメソッドで文字列strの中の2バイト文字を認識して、それを1文字として扱ってくれるようになった。
余計な御世話な気がしなくもないが、代わりにbytesizeメソッドを使用すれば、1.8時代と同じように動作させることができるので、なんとか問題にならなかった。


今回のバージョンアップで一番困ったのは、文字コード関係。
#-*- coding: windows-31j -*-

str = "あいう"

puts str[0].to_i
puts str[0]


を実行すると、1.8までは
C:\Users\hatsune\Desktop>test.rb
130
130


となっていたのに対し、1.9では、
C:\Users\hatsune\Desktop>ruby19 test.rb
0
あ


となってしまい、
str[0].to_iのようにして、文字コード(10進数)を取得しようとしても、取得できない問題が発生してしまう。
これは、ただ文字コードを取得するだけなら、ordメソッドを使用する(例: puts str[0].ord)だけでできる("あ"の場合"33440"が返ってくる)
だが、マルチスレッド対応 lameフロントエンド (もどき) v2.0aでは、1バイトずつコードを取得して("あ"の場合"130"と"160")、この値のいずれかが92(\の文字コード)になったとき、Shift-JISのダメ文字として処理していた(本当は2バイト目だけで良いのだが…)ので、処理を見直すハメに…

他にも、#-*- coding: windows-31j -*-を、2バイト文字を使用した全てのライブラリに追加しなければならなかったり、かなり面倒…。


バージョンが変わるたびに、Stringクラスメソッドのような、基本の部分がやたら変わるというのは、どうなんだろうか。
プログラムをソースで配布するのが基本になっているRubyでは、互換性のためだけに、ユーザーにv1.8環境とv1.9環境の両方を用意させる、とか、更新の度にソースを大幅に修正する、ということをしなくてはならなくなるのだが…
RubyScript2Exeも、見事にv1.9では動作しないようだし…

2009年2月26日木曜日

Debian5.0でkeymapを英語から日本語へ

Mac OSXが微妙だったので、結局5日でDebianに変更。
2月15日に5になったばかりのようなので、それの確認も兼ねて…

ということで、PPC版をインストールしたのだが、インストール時に何故か日本語106キーボードが選択できなかったので、設定しなおすことに。
…が、kbd-configコマンドを管理者で実行し、日本語106キーボードを選択しても、全然反映されず。

ここで30分ほど悩んだが、/etc/X11/xorg.confに何か設定があったことを思い出した。

以下の項目を、
Section "InputDevice"
Identifier "Generic Keyboard"
Driver "kbd"
Option "XkbRules" "xorg"
Option "XkbModel" "pc104"
Option "XkbLayout" "us"
EndSection


このように書き換え、再ログインすれば良い模様。
Section "InputDevice"
Identifier "Generic Keyboard"
Driver "kbd"
Option "XkbRules" "xorg"
Option "XkbModel" "jp106"
Option "XkbLayout" "jp"
EndSection


ウインドウマネージャーにxfceを選択したら、非力なMac Miniでも、結構ぬるぬる動作してくれて(゚Д゚)ウマー