thor:run命令而无需捕获stdout或stderr,并且失败了错误



我正在编写一个thor脚本来运行其他工具,即运行shell命令。我希望从命令中的stdout和stderr连续流入我的控制台。

第一次尝试只是使用反击,但自然而然地未打印出stdout/stderr(而不是在返回值中捕获stdout)。

desc "mytask", "my description"
def mytask
  `run-my-tests.sh`
end

我的下一个方法是使用Open3,如:

require "open3"
desc "mytask", "my description"
def mytask
  Open3.popen3("run-my-tests.sh") do |stdin, stdout, stderr|
    STDOUT.puts(stdout.read())
    STDERR.puts(stderr.read())
  end
end

但是,上述方法将从Stdout和stderr获得整个输出,并且仅在末尾打印。我的用例,我宁愿看到失败和通过测试的输出。

来自http://blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html,我看到我们可以通过gets()而不是read()读取块的流。例如:

require "open3"
desc "mytask", "my description"
def mytask
  Open3.popen3(command) do |stdin, stdout, stderr|
    while (out = stdout.gets()) || err = (stderr.gets())
      STDOUT.print(out) if out
      STDERR.print(err) if err
    end
    exit_code = wait_thr.value
    unless exit_code.success?
      raise "Failure"
    end
  end
end

看起来像是最好,最干净的方法?这是我必须在 stderr之前手动尝试打印stdout 的问题吗?

我正在使用IO.popen进行类似任务,例如: IO.popen([env, *command]) do |io| io.each { |line| puts ">>> #{line}" } end 要捕获stderr,我将其重定向到stdout command = %w(run-my-tests.sh 2>&1)

更新我已经使用Open3::popen3构建了一个脚本来分别捕获Stdout和Stderr。显然,它有很多房间形式的改进,但希望很明显。

require 'open3'
command = 'for i in {1..5}; do echo $i; echo "$i"err >&2; sleep 0.5; done'
stdin, stdout, stderr, _command_thread = Open3.popen3(command)
reading_thread = Thread.new do
  kilobyte = 1024
  loop do
    begin
      stdout.read_nonblock(kilobyte).lines { |line| puts "stdout >>> #{line}" }
      stderr.read_nonblock(kilobyte).lines { |line| puts "stderr >>> #{line}" }
    rescue IO::EAGAINWaitReadable
      next
    rescue EOFError
      break
    end
    sleep 1
  end
end
reading_thread.join
stdin.close
stdout.close
stderr.close

在我看来,就像运行shell命令的最简单方法,而不是尝试捕获stdout或stderr(而是让它们在来时冒出起泡)就像:

def run *args, **options
  pid = spawn(*args, options)
  pid, status = Process.wait2(pid)
  exit(status.exitstatus) unless status.success?
end

Backticks或system()的问题是前者捕获了Stdout,而后者仅返回命令是否成功。spawn()system()的更有益的替代方法。我宁愿让我的Thor脚本工具失败,好像它只是那些外壳命令的包装器。

以防万一,因为您只想失败错误,就可以将abort_on_failure: true选项添加到run命令中,因此:

run "bundle install", abort_on_failure: true

相关内容

  • 没有找到相关文章

最新更新