簡體   English   中英

雷神:運行命令而不捕獲標准輸出或標准錯誤,並且由於錯誤而失敗

[英]Thor: run command without capturing stdout or stderr, and fail on error

我正在編寫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 IO.popen([env, *command]) do |io| io.each { |line| puts ">>> #{line}" } end IO.popen([env, *command]) do |io| io.each { |line| puts ">>> #{line}" } end要捕獲stderr,我將其重定向到stdout command = %w(run-my-tests.sh 2>&1)

更新我已經使用Open3::popen3構造了一個腳本來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

反引號或system()的問題在於前者捕獲了stdout,而后者僅返回命令是否成功。 spawn()system()的更豐富的替代方法。 我寧願讓我的Thor腳本工具失敗,好像它只是這些shell命令的包裝器一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM