2009-08-01 16 views
16

Sto usando IO.popen in Ruby per eseguire una serie di comandi da riga di comando in un ciclo. Quindi ho bisogno di eseguire un altro comando al di fuori del ciclo. Il comando al di fuori del ciclo non può essere eseguito finché tutti i comandi nel ciclo non sono terminati.Come attendere il completamento del processo utilizzando IO.popen?

Come si fa in modo che il programma attenda che ciò accada? Al momento il comando finale è in esecuzione troppo presto.

Un esempio:

for foo in bar 
    IO.popen(cmd_foo) 
end 
IO.popen(another_cmd) 

Quindi tutto cmd_foos bisogno di tornare prima another_cmd viene eseguito.

risposta

4

Penso che dovresti assegnare i risultati delle chiamate IO.popen all'interno del ciclo alle variabili e continuare a chiamare read() su di esse finché eof() non diventa vero su tutti.

Quindi sai che tutti i programmi hanno terminato la loro esecuzione e puoi iniziare another_cmd.

+2

Proprio come una nota aggiuntiva: Utilizzando il modulo di blocco di metodi di IO di solito è più sicuro. Inoltre, nella 1.9 si ottiene una maggiore robustezza perché le variabili di blocco hanno ambiti diversi che impediscono la modifica delle stesse variabili con nome al di fuori del blocco (e si guadagna un avvertimento). –

6
for foo in bar 
    out = IO.popen(cmd_foo) 
    out.readlines 
end 
IO.popen(another_cmd) 

Leggere l'output su una variabile, quindi chiamare out.readlines. Penso che out.readlines debba attendere che il processo finisca prima che ritorni.

Credito a Andrew Y per avermi indicato nella giusta direzione.

+0

Ho provato la stessa identica cosa e sono finito con zombi (defunto), quindi non ideale – nhed

+0

Manca fuori.chiudere –

3

ti suggerisco di usare Thread.join per sincronizzare l'ultima chiamata popen:

t = Thread.new do 
    for foo in bar 
     IO.popen(cmd_foo) 
    end 
end 

t.join 

IO.popen(another_cmd) 
1

Avete bisogno l'uscita di popen? In caso contrario, si desidera utilizzare Kernel#system o qualche altro comando?

18

di utilizzare il modulo di blocco e leggere tutti i contenuti:

IO.popen "cmd" do |io| 
    # 1 array 
    io.readlines 

    # alternative, 1 big String 
    io.read 

    # or, if you have to do something with the output 
    io.each do |line| 
    puts line 
    end 

    # if you just want to ignore the output, I'd do 
    io.each {||} 
end 

Se non leggere l'output, può essere che i blocchi di processo in quanto il tubo di collegamento l'altro processo e il processo è piena e nessuno legge da esso.

+0

'IO.popen ('cmd'). Chiudi' funziona quando si elimina lo stdout? I documenti dicono che imposta '$?' (Quindi aspetta), ma non sono sicuro che scarti anche tutti gli stdout senza bloccare. –

+0

Cosa intendi esattamente con "scartare lo stdout"? Il codice che mostri non elimina nulla. Se vuoi semplicemente eseguire qualcosa e non fare nulla di speciale con il sistema di output() è più appropriato, –

+0

di "scarto stdout" intendevo "leggere l'output", che potrebbe essere necessario per impedire il blocco. –

16

A quanto pare il canonical way per fare questo è:

Process.wait(popened_io.pid) 
+0

Questa risposta è la più corretta. Nessun effetto collaterale (come con io.read), e molto ovvio cosa sta facendo. – siannopollo

Problemi correlati