【问题标题】:Access STDIN of child process without capturing STDOUT or STDERR在不捕获 STDOUT 或 STDERR 的情况下访问子进程的 STDIN
【发布时间】:2013-08-27 15:31:04
【问题描述】:

在 Ruby 中,是否可以防止生成的子进程的标准输入附加到终端,而不必捕获同一进程的 STDOUTSTDERR

  • 反引号和 x 字符串(`...`%x{...})不起作用,因为它们捕获 STDIN。

  • Kernel#system 不起作用,因为它会将 STDIN 附加到 终端(拦截^C 之类的信号并阻止它们 到达我的程序,这是我试图避免的)。

  • Open3 不起作用,因为它的方法捕获 STDOUTSTDOUTSTDERR

那我应该用什么?

【问题讨论】:

  • 你为什么不花时间展示一些你正在尝试做的事情的例子。不要让我们猜测或尝试设想您的代码。那是浪费时间。见sscce.org
  • @theTinMan 我不明白这在这种情况下如何适用。我没有要修复的损坏的代码,我有一个关于 Ruby 的 API 的特定问题需要回答。我已经列出了三个不起作用的例子。你想让我把这些例子放在上下文中并证明它们不起作用吗? :困惑:
  • open3 那样捕获 STDOUT 和 STDERR 是什么,你想避免吗?如果它们没有被父进程捕获和管理,你希望它们去哪里?
  • @NeilSlater 我希望他们去任何父进程的STDOUTSTDERR 去的地方;就像Kernel#system一样。
  • 父进程默认将 STDOUT 连接到 TTY 设备。使用> /dev/tty 重定向孩子的STDOUT 将像父母一样,阻止父母看到或捕获输出。您可以使用| tee /dev/stdout /dev/tty 将输出返回到父级并同时输出到终端/tty 设备。操作系统的tty 命令也很有用。 /dev 设备必须小心使用,但有些设备对于这种技巧很方便。这不是 Ruby 的东西,而是 *nix 的东西。

标签: ruby ruby-1.9 ruby-2.0


【解决方案1】:

如果您在支持它的平台上,您可以使用 pipeforkexec 执行此操作:

# create a pipe
read_io, write_io = IO.pipe

child = fork do
  # in child

  # close the write end of the pipe
  write_io.close

  # change our stdin to be the read end of the pipe
  STDIN.reopen(read_io)

  # exec the desired command which will keep the stdin just set
  exec 'the_child_process_command'
end

# in parent

# close read end of pipe
read_io.close

# write what we want to the pipe, it will be sent to childs stdin
write_io.write "this will go to child processes stdin"
write_io.close

Process.wait child

【讨论】:

  • 嗯。该解决方案是非常特定于平台的,但它确实可以满足我的需求。太糟糕了 Windows 不支持 fork 或 exec。 :( 似乎没有任何独立于平台的解决方案,所以我现在就这样做。
猜你喜欢
  • 2020-06-23
  • 2014-10-14
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多