dRuby遊びのメモ。いや、遊びじゃないんだけど、いずれにしても「もう一度
dRuby本[rakuten]を読んできなさいよ」という話なのだと思う。というわけで、はい、落ち着いたらもう一度読み返します。
require 'etc'
require 'drb/unix'
$name = File.basename($0)
class Foo
include DRbUndumped
def initialize(name)
@name = name
@peer = peer
@remote = nil
end
def ping(obj)
puts "#{@name}: ping: #{obj.inspect}"
if @peer
@remote = obj
@peer.ping(self)
else
obj.pong
end
end
def pong
@remote.pong if @remote
end
attr_accessor :peer
end
def ls_l(patt)
Dir.glob(patt) do |f|
stat = File.stat(f)
printf("%04o\t%8s %8s\t%s\n",
stat.mode, Etc.getpwuid(stat.uid).name,
Etc.getgrgid(stat.gid).name, f)
end
end
proc_a = fork do
Process.gid = Process.egid = Etc.getgrnam("grp_ab").gid
Process.uid = Process.euid = Etc.getpwnam("usr_a").uid
obj = Foo.new("a")
DRb.start_service(
"drbunix:/tmp/#{$name}_a", obj, {:UNIXFileMode => 0660})
puts
puts "[process a]"
ls_l("/tmp/drb*")
begin
sleep
rescue SignalException
ensure
DRb.stop_service
end
end
sleep 1
proc_b = fork do
obj = Foo.new("b")
sv_a = DRb.start_service("drbunix:/tmp/#{$name}_b_a", nil,
{:UNIXFileMode => 0660,
:UNIXFileOwner => "usr_b", :UNIXFileGroup => "grp_ab"})
sv_c = DRb.start_service("drbunix:/tmp/#{$name}_b_c", obj,
{:UNIXFileMode => 0660,
:UNIXFileOwner => "usr_b", :UNIXFileGroup => "grp_bc"})
DRb.primary_server = sv_a
puts
puts "[process b]"
ls_l("/tmp/drb*")
Process.gid = Process.egid = Etc.getgrnam("grp_ab").gid
Process.uid = Process.euid = Etc.getpwnam("usr_b").uid
robj = DRbObject.new_with_uri("drbunix:/tmp/#{$name}_a")
obj.peer = robj
obj.ping(nil)
begin
sleep
rescue SignalException
ensure
DRb.stop_service
end
end
sleep 2
proc_c = fork do
Process.gid = Process.egid = Etc.getgrnam("grp_bc").gid
Process.uid = Process.euid = Etc.getpwnam("usr_c").uid
robj = DRbObject.new_with_uri("drbunix:/tmp/#{$name}_b_c")
DRb.start_service("drbunix:/tmp/#{$name}_c", nil,
{:UNIXFileMode => 0660})
puts
puts "[process c]"
ls_l("/tmp/#{$name}_*")
robj.ping(nil)
end
Process.wait(proc_c)
Process.kill('HUP', proc_a, proc_b)
Process.wait(proc_a)
Process.wait(proc_b)
このスクリプトを以下の準備作業を行った上で実行する。
# groupadd grp_ab # groupadd grp_bc # useradd -g grp_ab usr_a # useradd -g grp_bc usr_c # useradd -g users -G grp_ab,grp_bc usr_b
すると104行目をきっかけに次のようなエラーになる。
(drbunix:/tmp/drbtest2.rb_b_c) (drbunix:/tmp/drbtest2.rb_a) /usr/lib/ruby/1.8/drb/drb.rb:724:in `open': drbunix:/tmp/drbtest2.rb_b_c - #<Errno::EACCES: Permission denied - /tmp/drbtest2.rb_b_c> (DRb::DRbConnError)
で、こうする。
--- drbtest2.rb 2005-01-24 21:24:40.000000000 +0900
+++ drbtest3.rb 2005-01-24 21:24:55.000000000 +0900
@@ -16,3 +16,3 @@
@remote = obj
- @peer.ping(self)
+ Thread.new {@peer.ping(self)}.join
else
するとエラーが出なくなる。