2017-12-12 7 views
0

Terraform에 대한 래퍼를 개발 중입니다. 실행 중 어느 시점에서 사용자 입력을 요청할 수 있습니다. 그래서, 내 응용 프로그램은 stdin에 입력 된 모든 것을 하위 프로세스 '표준으로 전달해야합니다. 다음 솔루션은 리눅스에서 작동하지만 Windows에서 하위 프로세스 (Terraform) 입력을받지 않을 것으로 보인다 : Terraform 다른 사용자의 입력을 요청하는 일부 응용 프로그램을 실행할 때이 솔루션은 실제로 윈도우에서 작동Ruby on Windows에서 stdin을 하위 프로세스로 전달

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') 

. 하지만 다음 두 구현 (Go 및 Python)은 Windows에서 Terraform으로 표준을 포워딩 할 수 있습니다. 따라서 Ruby 코드에 문제가 있거나 Windows 용 Ruby 구현에 프로세스 실행 및 입력 전달을 처리 할 때 약간의 제한이있을 수 있습니다.

누구나 이러한 제한 사항을 알고 있습니까?

파이썬 예 :

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) 
} 
+1

[면책 조항 : 코드를 보지 못했습니다.] JRuby를 사용해 볼 수도 있습니다. 아이러니하게도, 그것은 Windows에서 YARV (일명 "Ruby")보다 Ruby와 더 많이 호환되며, 더 많은 "native"입니다. 그 이유는 YARV의 I/O 및 프로세스 관리 구현은 POSIX를 감싸는 얇은 래퍼 일 뿐이며 다른 작업 (또는 전혀 작동하지 않는 작업)은 실제로 예상되며 버그로 간주되지 않기 때문입니다. JRuby OTOH *는 Java 플랫폼에서 호스트되기 때문에 모든 것을 에뮬레이트해야하므로 * 모든 플랫폼에서 일관되게 작동하고 Linux에서의 YARV 동작과 거의 일치하도록 시도합니다. –

+0

@ JörgWMittag 실제로 JRuby에서 작동합니다 ... YARV에서이 문제를 해결하려는 시도조차 없을 것이라고 추측합니다. 맞습니까? – betabandido

+0

시도해도 좋지 않습니까? "open3"은 POSIX open에 의존하고 Windows는 POSIX가 아니라 Windows 대신 cygwin 또는 Bash와 같은 POSIX 환경을 사용하십시오. –

답변

0

IO.popen에 따라 다음 코드가 작동하는 것 같다. 명령을 실행하고 출력을 포함하는 배열로 명령 출력을 리턴합니다. 선택적으로 출력도 stdout에 기록됩니다.

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 
관련 문제