popen3在使用popen3执行脚本时挂起

时间:2016-06-24 01:18:24

标签: ruby bash output deadlock

我有下一个代码

 def execute_bash(cmd)
  puts "Executing: [#{cmd}]"
  exit_code = Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
    stdin.close
    stdout.each { |line| puts line }
    stdout.close
    stderr.each { |line| puts line }
    stderr.close
    wait_thr.value.exitstatus
  end
  return exit_code
end

我使用此函数运行的命令是流浪的,这会产生大量输出。我有很多食谱,所以我需要逐行实时监测它的输出。

我还有另一个脚本可以确保以前的脚本运行良好并且没有崩溃。所以我有另一个脚本以与前一个相同的方式运行bash命令。所以我喜欢跑步(在第二个剧本中):

execute_bash "./vagrant_up.rb"

这样的结果导致我死锁或某事:在某些时候输出停止。我可以等很多时间,但不会继续。

当我在控制台中运行流浪汉时 - 一切都很好。

在另一个popen3中使用popen3运行ruby脚本是一个问题吗? 是否有正确的方法来处理popen3中的死锁(如果它死锁,我不确定)?

1 个答案:

答案 0 :(得分:0)

如果没有看到vagrant_up.rb的详细信息,很难说真正的问题是什么,但请考虑以下内容。

这里我有一个小的bash脚本:

#!/bin/sh
#out.sh
echo "about to sleep"
sleep 3
echo "just woke up"

另一个:

#!/bin/sh
#err.sh
echo "about to sleep" 1>&2
sleep 3
echo "just woke up" 1>&2

使用您的代码,运行execute_bash("out.sh")会产生一些可能与您的期望相符的内容。它说“即将入睡”然后3秒后它说“刚刚醒来”。但是,运行execute_bash("err.sh")会有点令人惊讶。等待3秒然后打印“即将入睡”和“刚刚醒来”。

所以,对于你的情况,这是我的猜测。你的命令可能会产生很多输出到stderr,你只是没有看到它。事实上,在命令完成之前你不会看到它(因为Open3进程的stdout流在此之前不会被关闭)。

你能将stderr重定向到stdout吗?如果这不能解决问题,你能评论一下吗?

execute_bash("./vagrant_up.rb 2>&1")