【问题标题】:Run shell command inside ruby, attach STDIN to command input在 ruby​​ 中运行 shell 命令,将 STDIN 附加到命令输入
【发布时间】:2014-04-20 22:35:37
【问题描述】:

我在 ruby​​ 脚本中运行一个长时间运行的 shell 命令,如下所示:

Open3.popen2(command) {|i,o,t|
  while line = o.gets
   MyRubyProgram.read line
   puts line
  end
}

所以我可以在 shell 窗口中查看命令输出。

如何将 STDIN 附加到命令输入?

【问题讨论】:

    标签: ruby shell


    【解决方案1】:

    你需要:

    1. 等待来自 STDIN 的用户输入
    2. 等待来自popen3 -- o的命令输出

    您可能需要IO.select 或其他IO 调度程序,或其他一些多任务调度程序,例如Thread

    这是Thread 方法的演示:

    require 'open3'
    
    Open3.popen3('ruby -e "while line = gets; print line; end"') do |i, o, t|
      tin = Thread.new do
        # here you can manipulate the standard input of the child process
        i.puts "Hello"
        i.puts "World"
        i.close
      end
    
      tout = Thread.new do
        # here you can fetch and process the standard output of the child process
        while line = o.gets
          print "COMMAND => #{line}"
        end
      end
    
      tin.join    # wait for the input thread
      tout.join   # wait for the output thread
    end
    

    【讨论】:

    • 我不愿意使用您的代码,因为我没有 Ruby 中线程同步的经验。基本上,我只是希望能够以编程方式处理输出并在我使用 shell 时与它进行交互。没有更简单的方法吗?如果我启动 shell 并将带有 tee 的输出副本重定向到我的程序会怎样?它能解决我的问题吗?
    • @ArtShayderov 我稍微更新了演示并添加了一些评论。您可以将其保存到 Ruby 文件并进行测试。现在应该清楚在哪里操作标准输入以及在哪里处理标准输出。
    • 所以我像STDIN.each_char {|c| i.puts c}那样把读取STDIN放在锡块里面?
    • @ArtShayderov 是的。确保 1) 在完成输入后,您通过 EOF 终止输入,即 Windows 上的 Ctrl-Z 或 Linux 上的 Ctrl-D。 2)在离开tin块之前关闭子进程的标准输入(i.close)。
    • 它有效。但我正在 linux 中测试不同的命令,其中一些命令(例如 top)失败并显示消息 failed tty get
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    • 2017-06-04
    • 2011-03-10
    • 2013-05-30
    相关资源
    最近更新 更多