2012-04-19 28 views
0

运行的进程,当检测到错误,我用open3执行从JRuby的DOS命令创建的helper方法,在Ruby中......如何使用Ruby和open3

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.batShellUtils.execute_cmd()和JRuby执行,日志从来没有捕获错误消息,Invalid type. Valid ones are...,我m只看到err日志的使用情况输出。我不明白为什么自使用和错误消息起源于import.bat。我已经检查了两个outerr对象,它们都不包含错误字符串。

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

+2

尝试运行在DOS import.bat时重定向标准输出和标准错误(import.bat ...> o.txt 2> e.txt),它仍然显示什么? – 2012-04-19 16:17:33

+0

是的,我在'e.txt'中看到错误信息'Invalid type ...',用法在'o.txt'中。 – raffian 2012-04-19 16:26:59

+0

@VictorMoroz那个测试证明了什么?我对Ruby很有新意,所以对此有所了解,thx – raffian 2012-04-19 17:00:52

回答

0

也许你的进程在那时还没有写入错误流。尝试等待它完成读取其输出之前:

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

在MacOSX中这不是必需的,因为'read'被阻塞,不知道Windows中会发生什么。 – 2012-04-19 16:36:48

+0

“加入”方法在JRuby 1.8中不可用? 'NoMethodError undefined method join'for nil:NilClass' – raffian 2012-04-19 17:39:25

+0

@RaffiM,in Ruby 1.8,['Open3 :: popen3'](http://www.ruby-doc.org/stdlib-1.8.7/libdoc/open3 /rdoc/Open3.html#method-c-popen3)方法不会将'Thread'传递给该块。额外的块参数隐式设置为'nil',它不会响应'join'。 [**使用Ruby 1.9 **](http://www.ruby-lang.org/zh/news/2011/10/06/plans-for-1-8-7/)。 – 2012-04-19 18:43:37

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 ] 
+0

另外我假设:err.each {| line | logger.error#{line}“}除非err.nil?应该是:err.each {| line | logger.error”#{line}“}除非err.nil?注意丢失的” – rainkinz 2012-04-19 21:00:18