Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Ruby on Windows中将stdin转发到子进程_Ruby_Windows_Io_Stdin - Fatal编程技术网

在Ruby on Windows中将stdin转发到子进程

在Ruby on Windows中将stdin转发到子进程,ruby,windows,io,stdin,Ruby,Windows,Io,Stdin,我正在为开发一个包装器,在执行过程中的某个时刻,它可能会请求用户输入。因此,我的应用程序必须将在其stdin上键入的所有内容转发到子进程的stdin。以下解决方案适用于Linux,但在Windows中,子进程(Terraform)似乎从未收到输入: require 'open3' def exec(cmd) Open3.popen3(cmd) do |stdin, stdout, stderr, thread| stdout_thread = Thread.new do

我正在为开发一个包装器,在执行过程中的某个时刻,它可能会请求用户输入。因此,我的应用程序必须将在其stdin上键入的所有内容转发到子进程的stdin。以下解决方案适用于Linux,但在Windows中,子进程(Terraform)似乎从未收到输入:

require 'open3'

def exec(cmd)
  Open3.popen3(cmd) do |stdin, stdout, stderr, thread|
    stdout_thread = Thread.new do
      IO.copy_stream(stdout, STDOUT)
    end

    stderr_thread = Thread.new do
      IO.copy_stream(stderr, STDERR)
    end

    stdin_thread = Thread.new do
      IO.copy_stream(STDIN, stdin)
    end

    puts "Return code: #{thread.value}"

    stdin_thread.join
    stdout_thread.join
    stderr_thread.join
  end
end

exec('terraform destroy')
当执行一些需要不同于Terraform的用户输入的应用程序时,此解决方案实际上可以在Windows上运行。但是,以下两种实现(在Go和Python中)能够将其stdin转发到Windows上的Terraform。因此,可能是我的Ruby代码有一些问题,或者Ruby的Windows实现在处理进程执行和输入转发时有一些限制

有人知道这样的限制吗

Python示例:

import subprocess
import sys

with subprocess.Popen(['terraform', 'destroy'],
                      stdin=sys.stdin, stdout=sys.stdout) as proc:
    proc.wait()
例如:

package main

import (
    "io"
    "log"
    "os"
    "os/exec"
)

func main() {
    cmd := exec.Command("terraform", "destroy")
    stdin, err := cmd.StdinPipe()
    if err != nil { log.Fatal(err) }

    stdout, err := cmd.StdoutPipe()
    if err != nil { log.Fatal(err) }

    stderr, err := cmd.StderrPipe()
    if err != nil { log.Fatal(err) }

    go func() {
        defer stdout.Close()
        io.Copy(os.Stdout, stdout)
    }()
    go func() {
        defer stderr.Close()
        io.Copy(os.Stderr, stderr)
    }()
    go func() {
        defer stdin.Close()
        io.Copy(stdin, os.Stdin)
    }()

    err = cmd.Run()
    log.Printf("Command finished with error: %v", err)
}

以下基于
IO.popen
的代码片段似乎有效。它执行命令,并将命令输出作为包含输出行的数组返回。也可以选择将输出写入标准输出

def run(cmd, directory: Dir.pwd, print_output: true)
  out = IO.popen(cmd, err: %i[child out], chdir: directory) do |io|
    begin
      out = ''
      loop do
        chunk = io.readpartial(4096)
        print chunk if print_output
        out += chunk
      end
    rescue EOFError; end
    out
  end

  $?.exitstatus.zero? || (raise "Error running command #{cmd}")

  out.split("\n")
     .map { |line| line.tr("\r\n", '') }
end
@贝塔班迪多 这同样有效

def run(cmd, directory: Dir.pwd, print_output: true)
  out = IO.popen(cmd, err: %i[child out], chdir: directory) do |io|
    io.readlines
  end
  raise "Error running command #{cmd}" unless $?.exitstatus.zero?
  print out if print_output
  out
end

[免责声明:我甚至没有看你的代码。]你可能想试试JRuby。具有讽刺意味的是,它在Windows上与Ruby的兼容性比YARV(又名“Ruby”)本身更高,而且更“原生”。原因是YARV的I/O和流程管理的实现只是POSIX的一个薄薄的包装,工作方式不同(或者根本不一样)实际上是预期的,而不是一个bug。JRuby OTOH无论如何都必须模拟一切,因为它托管在Java平台上,因此在所有平台上都能一致工作,并试图与Linux上YARV的行为紧密匹配。@JörgWMittag它确实与JRuby一起工作。。。所以,你的猜测是,如果有报道,YARV甚至不会有人试图解决这个问题,对吗?尝试没有坏处,是吗?您只需准备好获得“
open3
依赖于POSIX
open
,而Windows不是POSIX,请使用诸如cygwin或Bash for Windows之类的POSIX环境”作为答案。这非常有效。当我将笔记本电脑从一个工作环境移动到另一个工作环境时,我将它与Vagrant一起使用,以使桥接网络适应现有环境。看到这个了吗