Si quieres ejecutar un comando externo desde Ruby…
…como wkhtmltopdf para convertir un archivo HTML en un PDF.
Hay algunos métodos de Ruby que puedes usar.
Dependiendo del método que uses obtendrás diferentes resultados.
¡Exploremos juntos estos métodos!
El método del sistema de Ruby
El método del sistema de Ruby es la forma más sencilla de ejecutar un comando externo.
Se ve así:
system("ls")
Nota que system
imprimirá la salida del comando mientras sucede.
También el sistema hará que tu programa Ruby espere hasta que el comando haya terminado.
Prueba esto:
system("sleep 2")
Hay formas de ejecutar comandos en segundo plano como veremos más adelante.
El sistema puede devolver 3 posibles valores:
-
true
si el comando funcionó -
false
si el comando devuelve un código de error -
nil
si la ejecución del comando falla (comando no encontrado)
Puede obtener el código de estado de salida del último comando externo que ejecutó con la variable global $?
. Este código de estado puede darle más información acerca de por qué el comando falló.
¿Qué es la expansión del shell?
Cuando ejecute un comando externo con system
obtendrá el efecto de «expansión del shell».
La expansión del shell es cuando el shell (sh/bash/zsh) toma algunos caracteres especiales (*
, ?
, y ")# "best"
This will not change the current environment of your Ruby application.
%x / Kernel#`
If you want to get the output from the command you're running, instead of displaying it then you can use %x
o el método Kernel#`
.
Hacen lo mismo.
Aquí tienes un ejemplo:
`ls`
Otro con %x
:
%x|ls|
Estos dos ejemplos devolverán una cadena con la salida del comando ls
.
Nota que todavía tienes que esperar a que el comando termine a menos que lo ejecutes dentro de un hilo.
Cómo usar Fork + Exec para ejecutar comandos externos en un proceso separado
El fork hace una copia de tu proceso actual (tu aplicación Ruby) y luego puedes reemplazar esa copia con otro proceso usando exec.
Nota: El método fork no está disponible en Windows.
Este es un patrón popular en el mundo Unix.
Así es como funciona:
fork { exec("ls") }
Esto ejecutará ls
en otro proceso & mostrar su salida.
Debido a que este comando se ejecuta en otro proceso no bloqueará la ejecución de tu aplicación Ruby como el método system
o %x
.
Importante:
Si usas exec
sin fork
vas a reemplazar tu proceso actual.
Esto significa que tu programa Ruby terminará.
Cómo usar el método Popen para la comunicación bidireccional con un programa externo
Si necesitas:
- Más control sobre el proceso
- Comunicación bidireccional
Entonces el método IO.popen
es lo que estás buscando.
En el siguiente ejemplo utilizo el método popen para lanzar un proceso irb
, luego enviar alguna entrada a él & leer la salida.
Aquí el ejemplo:
r = IO.popen("irb", "r+")r.write "puts 123 + 1\n"3.times { puts r.gets }r.write "exit\n"
Esta variable r
es un objeto IO, esto significa que se puede escribir & leer de él como un archivo normal.
Usar popen
también significa que su comando externo se ejecutará en su propio proceso, por lo que no tiene que ejecutarlo en un hilo.
También hay un método popen3
en la biblioteca estándar.
La diferencia con el popen
regular es que dividirá los mensajes de error & de salida regular en objetos IO separados.
Conclusión
Has aprendido las diferentes formas en que puedes interactuar con comandos externos en Ruby.
¡Ten cuidado con estos!
No pases ningún tipo de entrada de usuario en estos comandos a menos que quieras un problema de seguridad en tu aplicación Ruby.