0

我在 Ruby 中创建了一个辅助方法,使用 open3 从 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使用ShellUtils.execute_cmd()和 JRuby 执行时,日志永远不会捕获错误消息,Invalid type. Valid ones are...我只看到错误日志的使用输出。我不明白为什么使用和错误消息来自import.bat. 我已经检查了outerr对象,它们都不包含错误字符串。

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

4

2 回答 2

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 ]
于 2012-04-19T19:40:01.563 回答
0

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

Open3.popen3 cmd do |stdin, stdout, stderr, thread|
  thread.join  # Wait for the process to finish
  output, error = stdout.read, stderr.read
  # ...
end
于 2012-04-19T16:18:44.220 回答