dRuby連鎖
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
するとエラーが出なくなる。