2010-07-01 20 views

Respuesta

13

Hay algunas formas de ejecutar comandos de sistema en 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" 

Pero si usted necesita para llevar a cabo realmente la entrada y salida con la entrada estándar/salida estándar del comando, es probable que desee para mirar el método IO::popen, que ofrece específicamente esa instalación.

+0

popen funciona bien si su aplicación sólo tiene salida estándar. Si necesita más interacción o desea hacer algo diferente con stdout, stdin y particularmente stderr, también querrá consultar open3: http://ruby-doc.org/core/classes/Open3.html –

180

Sí. Hay varias formas:


a. Uso%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) 

Estos métodos devolver la salida estándar, y redirigir stderr al programa de.


b. Uso system:

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

Este método devuelve true si el comando se ha realizado correctamente. Redirige todo el resultado al programa.


c. Uso 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. 

que reemplaza el proceso actual con el creado por el comando.


d. (rubí 1,9) utiliza spawn:

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

Este método no espera a que el proceso para salir y devuelve el 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"'. 

Este método devolverá un objeto IO que reperesents los nuevos procesos de entrada/salida. También es actualmente la única forma que conozco de dar la entrada del programa.


f. Use Open3 (en 1.9.2 y más tarde)

require 'open3' 

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

Open3 tiene varias otras funciones para conseguir acceso explícito a las dos corrientes de salida. Es similar a popen, pero le da acceso a stderr.

+0

Brilliant summary Adrian , Gracias por compartir esta información. – KomodoDave

+0

Truco de bonificación: 'io = IO.popen 'cat> out.log', 'r +' '; escribe las salidas del comando en "out.log" – Narfanator

+1

¿Cuáles son los pro y los contras para cada uno? ¿Cómo decido cuál usar? ¿Qué le parece usar 'FileUtils' [http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html]? – Ava

2

Sí, esto es factible, pero el método de implementación depende de si el programa de "línea de comando" en cuestión opera en "Pantalla completa" o modo de línea de comando. Los programas escritos para la línea de comando tienden a leer STDIN y escribir en STDOUT. Se pueden llamar directamente dentro de Ruby utilizando los métodos estándar de retroceso y/o las llamadas al sistema/ejecución.

Si el programa funciona en modo "Pantalla completa" como pantalla o vi, el enfoque debe ser diferente. Para programas como este, debe buscar una implementación Ruby de la biblioteca "esperar". Esto le permitirá programar lo que espera ver en la pantalla y lo que debe enviar cuando vea esas cadenas en particular en la pantalla.

Es poco probable que sea el mejor enfoque y probablemente deba ver lo que está tratando de lograr y encontrar la biblioteca/gema relevante para hacerlo en lugar de tratar de automatizar una aplicación existente de pantalla completa. Como ejemplo, "Need assistance with serial port communications in Ruby" se ocupa de las comunicaciones del puerto serie, un precursor para marcar si eso es lo que quiere lograr usando los programas específicos que mencionó.

+0

Una versión simple de Expect está disponible en Ruby usando su módulo integrado [Pty] (http://www.ruby-doc.org/stdlib-1.9.3/libdoc/pty/rdoc/PTY.html) . –

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

El método más utilizado es el uso de Open3 aquí está mi código de la versión del código anterior editado con algunas correcciones:

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 
Cuestiones relacionadas