2017-09-25 4 views
0

私は別のツール、すなわちシェルコマンドを実行していくつかのテストを実行するThorスクリプトを作成しています。私はコマンドからstdoutとstderrが私のコンソールに連続的に流出したいと思います。Thor: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から、read()の代わりにgets()を使用してストリームを読み取ることができました。例:

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を使用してい
+0

stdoutとstderrを監視するには 'IO.select'を使うべきです。 – Stefan

答えて

0

:私はちょうどcommand = %w(run-my-tests.sh 2>&1)

を標準出力にリダイレクトしたい標準エラー出力をキャプチャするには IO.popen([env, *command]) do |io| io.each { |line| puts ">>> #{line}" } end 更新 私は標準出力をキャプチャするOpen3::popen3を使用してスクリプトを構築してきましたと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 
+0

stdoutとstderrの区別は便利ですが、コンソールに出力されるときに一緒に読むこともできます。私。適切なstderrストリームを持つことを犠牲にしないだろう:( – jleeothon

0

最も簡単なシェルコマンドを実行する方法と標準出力や標準エラー出力をキャプチャしない試みは、(彼らが来るとして代わりに、彼らはバブルアップしましょう)のようなものだったように私には思える:

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

バックチックまたはsystem()の問題は、前者がstdoutを取り込み、後者がコマンドの成功の有無だけを返すことです。 system()の代わりに、spawn()が有益です。私はThorスクリプトツールを、あたかもそれらのシェルコマンドのラッパーであるかのように失敗させたいのです。

関連する問題