2010-01-26 23 views
5

Estoy tratando de ejecutar algunos scripts de terceros desde dentro de mi programa Ruby.¿Cómo puedo generar variables de entorno para un shell de comandos en un script de Ruby?

Antes de poder ejecutarlos, me requieren un archivo. En la línea de comandos todo funciona bien, pero dentro de Ruby no funciona. Descubrí que los comandos del sistema abrirán un nuevo proceso de shell secundario y cualquier fuente se realizará y no se podrá ver desde el proceso del shell primario que ejecuta el script de Ruby. Cuando finaliza la llamada al sistema, también se mata al shell hijo.

¿Cómo soluciono este problema?

Respuesta

7

Haga lo siguiente:

$ source whatever.sh 
$ set > variables.txt 

Y luego en Ruby:

File.readlines("variables.txt").each do |line| 
    values = line.split("=") 
    ENV[values[0]] = values[1] 
end 

Después de ejecutar esto, su entorno debería estar listo para funcionar.

+0

Lo intentaré. Entonces, ¿esto significa que el script puede alterar las variables de entorno de su proceso de shell que contiene y, por lo tanto, cualquier otro proceso secundario creado a través de llamadas al sistema con inherit? – robodisco

+1

No, pero cualquier proceso ejecutado desde el script de Ruby heredará las variables del script. – Geo

+0

Lo anterior funciona para un solo hilo y hago lo siguiente. Pero una pregunta que tengo ¿cómo uso una COPIA fusionada del entorno con IO.popen? de alguna manera no parece funcionar. con "sistema" que puedo hacer: # ... crear una nueva "ruta" aquí subEnv = Hash.new; subEnv.merge! (ENV); # copy old environment subEnv ['PATH'] = ruta; # establecer nuevos valores en la copia system (subEnv, commandLine); – peterk

2

No estoy seguro de si entiendo su pregunta correctamente. ¿Intentas obtener un script de shell antes de ejecutar otro? En este caso, la respuesta es sencilla:

#!/bin/env ruby 
system "source <path_to_source_file> && <command>" 

Si el archivo de origen contiene variables que el comando debe utilizar lo que tienes que export ellos. También es posible establecer variables de entorno dentro de su script de Ruby usando ENV['<name_of_var>'] = <value>.


actualización el 26 enero 2010 - 15:10

Puede utilizar IO.popen para abrir un nuevo shell:

IO.popen("/bin/bash", "w") do |shell| 
    shell.puts "source <path_to_source_file>" 
    shell.puts "<command>" 
end 
+0

No creo que la ejecución con el sistema va a ayudar, porque los VARs se establecerá sólo para el proceso de shell que obtiene dio lugar a ejecutar ese comando. – Geo

+0

ni siquiera puedo hacer que el sistema "fuente .bashrc" funcione en mi directorio de usuarios. Se queja comando no encontrado. ¿Estás seguro de que la fuente se puede usar como la publicaste? – robodisco

+0

Me funcionó. Intenté esto en OSX 10.6. ¿El shell del usuario que ejecuta el script se establece en/bin/bash? (También actualicé mi respuesta.) – t6d

0

lo hice porque no quería tener que escribir un archivo o mezclar mi código de rubí con estas cosas:

#!/usr/bin/env bash 
eval $(echo "$(cat .env) $1" | tr '\n' ' ') 

Pongo esto en ~/bin/run_with_env.sh y después de ejemplo que puedo correr:

% run_with_env.sh "rails console" 
2

Esto es horrible, pero ..

env = %x{. /some/shell/script/which/setups/your/env && env} 
env.split("\n").each do |line| 
    key, value = line.split("=", 2) 
    ENV[key] ||= value unless value.nil? or value.empty? 
end 
0

Modificación ENV sólo funciona para un solo hilo y hago la bel ow en cambio. Pero una pregunta que tengo ¿cómo uso una COPIA fusionada del entorno con IO.popen? de alguna manera no parece funcionar.

con "sistema" que puedo hacer:

# ... create new "path" here 

    subEnv = Hash.new; 
    subEnv.merge!(ENV); # copy old environment 
    subEnv['PATH'] = path; # set new values in copy 

    system(subEnv, commandLine); 
Cuestiones relacionadas