首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用popen3正确处理STDOUT和STDERR输出?

无法使用popen3正确处理STDOUT和STDERR输出?
EN

Stack Overflow用户
提问于 2013-11-25 12:25:28
回答 1查看 790关注 0票数 0

我正在编写一个函数来执行shell命令,并返回它的退出代码STDOUT和STDERR。

问题是,此函数无法正确捕获STDOUT和STDERR输出。

代码语言:javascript
复制
def sh(*args)
  options = args[-1].respond_to?(:to_hash) ? args.pop.to_hash: {}
  options = { :timeout => 0, :sudo => false }.merge(options)
  cmd = options[:sudo] == false ? args[0] : "sudo " << args[0]

  begin
    stdin, stdout, stderr, wait_thr = Open3.popen3(cmd)
    pid = wait_thr[:pid]
    out_buf = ""
    err_buf = ""
    start = Time.now

    # Manually ping the process per 0.2 second to check whether the process is alive or not
    begin
      out_buf << stdout.read_nonblock(4096)
      err_buf << stderr.read_nonblock(4096)
      # kill the process if it timeouts
      if options[:timeout] != 0 && (Time.now - start) > options[:timeout]
        Process.kill("KILL", pid)
        Process.detach(pid)
        raise RuntimeError, "process with pid #{pid} timed out with #{options[:timeout]} seconds."
      end
      sleep 0.2
    rescue IO::WaitReadable, EOFError
    end while wait_thr.alive?

  rescue => e
    NtfLogger.warn("sh '#{args}' executed with failure: #{e}")

  ensure
    if wait_thr.nil?
      return 1, out_buf, err_buf
    else
      return wait_thr.value.exitstatus, out_buf, err_buf
    end
  end
end # end of sh

有人能帮我找出问题出在哪里吗?

EN

回答 1

Stack Overflow用户

发布于 2013-11-25 13:25:05

我对popen3文档的理解是,最好在块中进行处理:

代码语言:javascript
复制
Open3.popen3([env,] cmd... [, opts]) do |stdin, stdout, stderr, wait_thr|
  pid = wait_thr.pid # pid of the started process.
  ...
  exit_status = wait_thr.value # Process::Status object returned.
end

在非块形式中,文档注意到流必须关闭:

代码语言:javascript
复制
stdin, stdout, stderr, wait_thr = Open3.popen3([env,] cmd... [, opts])
pid = wait_thr[:pid]  # pid of the started process.
...
stdin.close  # stdin, stdout and stderr should be closed explicitly in this form.
stdout.close
stderr.close
exit_status = wait_thr.value  # Process::Status object returned.

http://www.ruby-doc.org/stdlib-2.0.0/libdoc/open3/rdoc/Open3.html#method-c-popen3

最后,顺便说一句,这里有一个围绕capture3的包装器,我在我的一端使用它。如果sh实用程序中与线程相关的部分并不重要,您可以很容易地将其扩展为添加一个sudo选项:

代码语言:javascript
复制
#
# Identical to Open3.capture3, except that it rescues runtime errors
#
# @param env optional (as `Kernel.system')
# @param *cmd the command and its (auto-escaped) arguments
# @param opts optional a hash of options (as `Kernel.system')
#
# @return [stdout, stderr, success] | [$/, $/, nil] on error
#
def system3(*cmd)
  begin
    stdout, stderr, status = Open3.capture3(*cmd)
    [stdout, stderr, status.success?]
  rescue
    [$/, $/, nil]
  end
end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20184731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档