2010-07-01 14 views

risposta

13

Esistono alcuni modi per eseguire i comandi di sistema in Ruby.

irb(main):003:0> `date /t` # surround with backticks 
=> "Thu 07/01/2010 \n" 
irb(main):004:0> system("date /t") # system command (returns true/false) 
Thu 07/01/2010 
=> true 
irb(main):005:0> %x{date /t} # %x{} wrapper 
=> "Thu 07/01/2010 \n" 

Ma se è necessario eseguire effettivamente ingresso e uscita con del comando stdin/stdout, probabilmente si vorrà guardare il metodo IO::popen, che offre specificamente tale impianto.

+0

popen funziona bene se la vostra applicazione è appena standard out. Se hai bisogno di più interazione o vuoi fare qualcosa di diverso con stdout, stdin e in particolare stderr, ti consigliamo di aprire anche open3: http://ruby-doc.org/core/classes/Open3.html –

180

Sì. Ci sono diversi modi:


a. Usa %x o '`':

%x(echo hi) #=> "hi\n" 
%x(echo hi >&2) #=> "" (prints 'hi' to stderr) 

`echo hi` #=> "hi\n" 
`echo hi >&2` #=> "" (prints 'hi' to stderr) 

Questi metodi restituire lo stdout, e reindirizzare stderr al programma di.


b. Usa system:

system 'echo hi' #=> true (prints 'hi') 
system 'echo hi >&2' #=> true (prints 'hi' to stderr) 
system 'exit 1' #=> nil 

Questo metodo restituisce true se il comando ha avuto successo. Reindirizza tutti gli output a quelli del programma.


c. Usa exec:

fork { exec 'sleep 60' } # you see a new process in top, "sleep", but no extra ruby process. 
exec 'echo hi' # prints 'hi' 
# the code will never get here. 

che sostituisce il processo corrente con quello creato dal comando.


d. (Ruby 1.9) usa spawn:

spawn 'sleep 1; echo one' #=> 430 
spawn 'echo two' #=> 431 
sleep 2 
# This program will print "two\none". 

Questo metodo non aspetta che il processo di uscire e restituisce il PID.


e. Uso IO.popen:

io = IO.popen 'cat', 'r+' 
$stdout = io 
puts 'hi' 
$stdout = IO.new 0 
p io.read(1) 
io.close 
# prints '"h"'. 

Questo metodo restituirà un oggetto IO che reperesents nuovi processi input/output. Al momento è anche l'unico modo che conosco per fornire l'input del programma.


f. Utilizzare Open3 (in 1.9.2 e successive)

require 'open3' 

stdout,stderr,status = Open3.capture3(some_command) 
STDERR.puts stderr 
if status.successful? 
    puts stdout 
else 
    STDERR.puts "OH NO!" 
end 

Open3 ha diverse altre funzioni per ottenere l'accesso esplicito ai due flussi in uscita. È simile al popen, ma ti dà accesso a stderr.

+0

Sommario brillante Adrian , grazie per aver condiviso queste informazioni. – KomodoDave

+0

Trucco bonus: 'io = IO.popen 'cat> out.log', 'r +''; scrive gli output del comando su "out.log" – Narfanator

+1

Quali sono i pro ei contro per ciascuno. Come decido quale usare? Che ne dici di usare 'FileUtils' [http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html]? – Ava

2

Sì, questo è certamente fattibile, ma il metodo di implementazione varia a seconda che il programma "riga di comando" in questione funzioni in "Schermo intero" o in modalità riga di comando. I programmi scritti per la riga di comando tendono a leggere STDIN e scrivere a STDOUT. Questi possono essere chiamati direttamente all'interno di Ruby usando i metodi backtick standard e/o le chiamate di sistema/exec.

Se il programma funziona in modalità "Schermo intero" come schermo o vi, l'approccio deve essere diverso. Per programmi come questo dovresti cercare un'implementazione Ruby della libreria "expect". Questo ti permetterà di scrivere ciò che ti aspetti di vedere sullo schermo e cosa inviare quando vedi quelle stringhe particolari sullo schermo.

È improbabile che questo sia l'approccio migliore e probabilmente dovresti esaminare ciò che stai cercando di ottenere e trovare la libreria/gemma pertinente per farlo invece di provare ad automatizzare un'applicazione a schermo intero esistente. Ad esempio, "Need assistance with serial port communications in Ruby" si occupa delle comunicazioni della porta seriale, un pre-cursore per la selezione se questo è ciò che si desidera ottenere utilizzando i programmi specifici menzionati.

+0

Una versione semplice di Expect è disponibile in Ruby usando il modulo [Pty] (http://www.ruby-doc.org/stdlib-1.9.3/libdoc/pty/rdoc/PTY.html) integrato . –

6
folder = "/" 
list_all_files = "ls -al #{folder}" 
output = `#{list_all_files}` 
puts output 
0

Il metodo più usato è Utilizzando Open3 ecco il mio codice di versione del codice di cui sopra modificati con alcune correzioni:

require 'open3' 
puts"Enter the command for execution" 
some_command=gets 
stdout,stderr,status = Open3.capture3(some_command) 
STDERR.puts stderr 
if status.success? 
    puts stdout 
else 
    STDERR.puts "ERRRR" 
end