2014-04-04 11 views
8

Sto usando il metodo Open3popen3 per avviare un processo che funziona in modalità console/REPL per accettare ripetutamente input e output di ritorno.ruby ​​popen3 - come scrivere ripetutamente per stdin e leggere lo stdout senza processo di riapertura?

Sono in grado di aprire il processo, invio di input, e ricevere l'uscita bene, con codice come questo:

Open3.popen3("console_REPL_process") do |stdin, stdout, stderr, wait_thr| 
    stdin.puts "a string of input" 
    stdin.close_write 
    stdout.each_line { |line| puts line } #successfully prints all the output 
end 

che voglio fare che molte volte di fila, senza riaprire il processo, poiché richiede molto tempo per l'avvio.

So che devo chiudere lo stdin in modo che lo stdout ritorni .. ma quello che non so è, come posso riaprire lo stdin in modo che possa scrivere più input?

Idealmente voglio fare qualcosa di simile:

Open3.popen3("console_REPL_process") do |stdin, stdout, stderr, wait_thr| 
    stdin.puts "a string of input" 
    stdin.close_write 
    stdout.each_line { |line| puts line } 

    stdin.reopen_somehow() 

    stdin.puts "another string of input" 
    stdin.close_write 
    stdout.each_line { |line| puts line } 
    # etc.. 
end 

soluzione

Grazie alla risposta di pmoo, sono stato in grado di elaborare una soluzione che utilizza PTY e expect, aspettandosi la stringa del prompt che il processo restituisce quando è pronto per ulteriori input, ad esempio:

PTY.spawn("console_REPL_process") do |output, input| 
    output.expect("prompt >") do |result| 
     input.puts "string of input" 
    end 
    output.expect("prompt >") do |result| 
     puts result 
     input.puts "another string of input" 
    end 
    output.expect("prompt >") do |result| 
     puts result 
     input.puts "a third string of input" 
    end 
    # and so forth 
end 

risposta

3

È possibile avere un po 'di successo utilizzando expect biblioteca e avere il processo figlio per marcare in modo esplicito alla fine di ogni uscita, come:

require 'expect' 
require 'open3' 

Open3.popen3("/bin/bash") do 
    | input, output, error, wait_thr | 
    input.sync = true 
    output.sync = true 

    input.puts "ls /tmp" 
    input.puts "echo '----'" 
    puts output.expect("----", 5) 

    input.puts "cal apr 2014" 
    input.puts "echo '----'" 
    puts output.expect("----", 5) 
end 

Come bonus, expect ha un'opzione timeout.

Problemi correlati