下面的代码有两个问题。任何人都可以帮忙吗?
如何返回[captured_stdout,captured_stderr]的值?
当在popen3中使用puts时,ruby在打印后不会返回提示。 我该如何解决这个问题?
== code
#!/bin/env ruby
require 'open3'
require 'etc'
def as_user(user, &block)
u = Etc.getpwnam(user)
Process.fork do
Process.uid = u.uid
block.call(user)
end
end
def run_cmd(cmd)
as_user "oracle" do |user|
puts("In block as #{user} (uid=#{Process.uid}), pid is #{Process.pid}")
Open3.popen3(cmd) do |i,o,e,wait_thr|
stdout = o.read
stderr = e.read
[stdout, stderr]
end
end
end
output = run_cmd("/bin/date")
puts output
==输出
[root@test]# ./x2.rb
24810
In block as oracle (uid=1001), pid is 24810
[root@test]#
答案 0 :(得分:0)
我不认为你应该从方法返回,直到popen方法调用(包括你指定的块)完成。如果这是真的,那么您需要在调用popen
之前声明这些返回变量,然后仅在popen
完成后返回它们。像这样:
def run_cmd(cmd)
as_user "user1" do |user|
puts("In block as #{user} (uid=#{Process.uid}), pid is #{Process.pid}")
captured_stdout = captured_stderr = nil # just to declare them
Open3.popen3(cmd) do |i,o,e,wait_tnr|
captured_stdout = o.read
captured_stderr = e.read
i.close
o.close
e.close
end
[captured_stdout, captured_stderr]
end
end
顺便问一下,你确定要使用Ruby 1.8吗?它现在非常古老,并且在很长一段时间内都没有得到支持。
考虑到这一点,删除本地captured_
变量和close
调用可以大大简化:
def run_cmd(cmd)
as_user "user1" do |user|
puts("In block as #{user} (uid=#{Process.uid}), pid is #{Process.pid}")
Open3.popen3(cmd) { |i,o,e,wait_tnr| [o.read, e.read] }
end
end
为了加强这一点,您可能希望添加一个线程连接,以便在命令关闭其stdout然后需要运行一段时间之后,它会有时间完成其工作:
def run_cmd(cmd)
as_user "user1" do |user|
puts("In block as #{user} (uid=#{Process.uid}), pid is #{Process.pid}")
Open3.popen3(cmd) do |i,o,e,wait_tnr|
stdout = o.read
stderr = e.read
wait_thr.join
[stdout, stderr]
end
end
end