如何使用Ruby和open3运行进程时检测错误

时间:2012-04-19 16:04:44

标签: ruby process jruby dos

我使用open3在Ruby中创建了一个帮助器方法来执行JRuby的DOS命令......

   def ShellUtils.execute_cmd(cmd)
        $ERRORS = ['Invalid type','Invalid path']
        out = nil
        err = nil
        Open3.popen3(cmd) {|stdin, stdout, stderr, wait_thr|
            out = stdout.read
            err = stderr.read
            unless err.nil?
                err = $ERRORS.detect {|e| err.include? e }
            end
            out.each {|line| logger.info "#{line}"} unless out.nil?
            err.each {|line| logger.error #{line}"} unless err.nil?

        }        
        return out, err
    end

如果正在执行的进程的任何部分无效,则会输出错误消息及其用法。下面是在DOS中执行进程时的正常错误输出,没有涉及JRuby或Ruby ......

C:\PROJECTS\bin>import.bat -su -types ws,v
Invalid type. Valid ones are: folder, datasource...
Usage:
  import -f path-to-file [-s servers-file | -h server...

但是当我使用import.bat和JRuby执行ShellUtils.execute_cmd()时,日志永远不会捕获错误消息Invalid type. Valid ones are...,我只看到错误日志的使用输出。我不明白为什么因为使用和错误消息来自import.bat。我检查了outerr对象,但都没有包含错误字符串。

我只需要检测错误消息以向调用者发出进程失败的信号,但是在错误日志中没有该字符串时,很难知道发生了什么。

2 个答案:

答案 0 :(得分:1)

编辑:

看了一下你的方法后我觉得你错了。你能试试这个:

def ShellUtils.execute_cmd(cmd)
  out = nil
  err = nil
  Open3.popen3(cmd) {|stdin, stdout, stderr, wait_thr|
    out = stdout.read
    err = stderr.read

    unless err.nil?
      err = err.split("\n")
      puts err.inspect
      err = err.select {|e| e =~ /Invalid/ }
    end

    out.each {|line| logger.info "#{line}"} unless out.nil?
    err.each {|line| logger.error "#{line}"} unless err.nil?

  }

  return out, err
end

与其说是一种解决方案。您可能想尝试systemu。对于我来说,这对jruby非常有用:

require 'rubygems'
require 'systemu'

cmd = "#{File.expand_path('../', __FILE__)}/import.bat -su -types ws,v "

status, stdout, stderr = systemu cmd
p [ status, stdout, stderr ]

答案 1 :(得分:0)

也许您的进程尚未写入错误流。在阅读输出之前尝试等待它完成:

Open3.popen3 cmd do |stdin, stdout, stderr, thread|
  thread.join  # Wait for the process to finish
  output, error = stdout.read, stderr.read
  # ...
end