Cómo llamar a los comandos de shell desde Ruby

ruby shell interop


¿Cómo llamo a los comandos de shell desde el interior de un programa Ruby? ¿Cómo puedo entonces obtener la salida de estos comandos de nuevo en Ruby?




Answer 1 Steve Willard


Esta explicación se basa en un script Ruby comentado de un amigo mío. Si desea mejorar el script, no dude en actualizarlo en el enlace.

Primero, tenga en cuenta que cuando Ruby llama a un shell, generalmente llama a /bin/sh , no a Bash. Alguna sintaxis de Bash no es compatible con /bin/sh en todos los sistemas.

Aquí hay formas de ejecutar un script de shell:

cmd = "echo 'hi'" # Sample string that can be used
  1. Kernel#` , comúnmente llamado `cmd`

    Este es como muchos otros lenguajes,incluyendo Bash,PHP y Perl.

    Devuelve el resultado (es decir,la salida estándar)del comando shell.

    Documentos: http://ruby-doc.org/core/Kernel.html#method-i-60

    value = `echo 'hi'`
    value = `#{cmd}`
  2. Sintaxis incorporada, %x( cmd )

    Después del carácter x hay un delimitador, que puede ser cualquier carácter. Si el delimitador es uno de los caracteres ( , [ , { o < , el literal consiste en los caracteres hasta el delimitador de cierre correspondiente, teniendo en cuenta los pares de delimitadores anidados. Para todos los demás delimitadores, el literal comprende los caracteres hasta el siguiente aparición del carácter delimitador. Se permite la interpolación de cadena #{ ... } .

    Devuelve el resultado (es decir,la salida estándar)del comando shell,al igual que los retrocesos.

    Documentos: https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Percent+Strings

    value = %x( echo 'hi' )
    value = %x[ #{cmd} ]
  3. Kernel#system

    Ejecuta la orden dada en una subcapa.

    Devuelve true si el comando se encontró y se ejecutó correctamente, false caso contrario

    Documentos: http://ruby-doc.org/core/Kernel.html#method-i-system

    wasGood = system( "echo 'hi'" )
    wasGood = system( cmd )
  4. Kernel#exec

    Reemplaza el proceso actual ejecutando el comando externo dado.

    No devuelve ninguno,el proceso actual es reemplazado y nunca continúa.

    Documentos: http://ruby-doc.org/core/Kernel.html#method-i-exec

    exec( "echo 'hi'" )
    exec( cmd ) # Note: this will never be reached because of the line above

Aquí hay algunos consejos adicionales: $? , que es lo mismo que $CHILD_STATUS , accede al estado del último comando ejecutado por el sistema si usa los backticks, system() o %x{} . Luego puede acceder a las propiedades exitstatus y pid :

$?.exitstatus

Para más lectura ver:




Answer 2 Ian


Aquí hay un diagrama de flujo basado en " Cuándo usar cada método para iniciar un subproceso en Ruby ". Consulte también " Engañar a una aplicación para que piense que su stdout es un terminal, no una tubería ".

enter image description here




Answer 3 cynicalman


La forma en que me gusta hacer esto es usar el literal %x , lo que hace que sea fácil (¡y legible!) Usar comillas en un comando, así:

directorylist = %x[find . -name '*test.rb' | sort]

Que,en este caso,llenará la lista de archivos con todos los archivos de prueba bajo el directorio actual,que puede procesar como se espera:

directorylist.each do |filename|
  filename.chomp!
  # work with file
end



Answer 4 Mihai A


Aquí está el mejor artículo en mi opinión sobre la ejecución de scripts de shell en Ruby: " 6 formas de ejecutar comandos de Shell en Ruby ".

Si sólo necesitas conseguir la salida,usa palos de espalda.

Necesitaba cosas más avanzadas como STDOUT y STDERR,así que usé la gema Open4.Tienes todos los métodos explicados allí.




Answer 5 anshul


Mi favorito es Open3

  require "open3"

  Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }