2010-04-18 14 views
36

¿Cómo exporto una variable de entorno desde un script de Ruby al shell primario? Por ejemplo, la implementación de una aplicación ingenua de la orden interna read Bash:Exportación de una variable de entorno en Ruby

#!/usr/bin/ruby 

varname = ARGV[0] 
ENV[varname] = STDIN.gets # but have varname exported to the parent process 
+2

He visto [una pregunta similar] (http://stackoverflow.com/questions/190168/persisting-an-environment-variable-through-ruby) pero yo no estoy satisfecho ed con la respuesta específica de la plataforma. – wilhelmtell

Respuesta

34

Respuesta simple: Puede no.

Respuesta más larga: No se puede, a menos que el entorno operativo proporcione ganchos para hacerlo. La mayoría no. Lo mejor que puede hacer normalmente es imprimir las asignaciones que desea hacer y hacer que el padre las ejecute.

+0

mira la respuesta de peterk, también funciona en Windows. Lo intenté con el comando sh de rake's sh que requiere env set dentro de rake. – kite

+5

@kite: "para el shell primario" –

+1

como alternativa, considere establecer un archivo punto credenciales en un directorio apropiado –

35

No puede exportar variables de entorno al shell en el que se ejecuta el script de ruby, pero puede escribir un script de ruby ​​que crea un archivo bash de capacidad de origen.

Por ejemplo

% echo set_var.rb 
#!/usr/bin/env ruby 
varname = ARGV[0] 
puts "#{varname}=#{STDIN.gets.chomp}" 
% set_var.rb FOO 
1 
FOO=1 
% set_var.rb BAR > temp.sh ; . temp.sh 
2 
% echo $BAR 
2 
% 

Otra alternativa es que el uso de ENV[]= sí establece variables de entorno para carcasas parciales abiertas desde dentro del proceso de rubí. Por ejemplo:

outer-bash% echo pass_var.rb 
#!/usr/bin/env ruby 
varname = ARGV[0] 
ENV[varname] = STDIN.gets.chomp 
exec '/usr/bin/env bash' 
outer-bash% pass_var.rb BAZ 
quux 
inner-bash% echo $BAZ 
quux 

Esto puede ser muy potente si se combina con el comando exec de la cáscara, que sustituirá a la cáscara exterior con el proceso de rubí (de modo que al salir de la carcasa interior, la cáscara auto exterior -existe también, evitando cualquier confusión de "Creo que establecí esa variable en este shell".

# open terminal 
% exec pass_var.rb BAZ 
3 
% echo $BAZ 
3 
% exit 
# terminal closes 
7

Acabo de probar esto y se ve bien.

cmd = "echo \"FOO is \\\"$FOO\\\"\"";         
system(cmd); 

# Run some Ruby code (same program) in the child process 
fork do 
    puts "In child process. parent pid is #$$" 
    ENV['FOO']='foo in sub process'; 
    system(cmd); 
    exit 99 
end 
child_pid = Process.wait 
puts "Child (pid #{child_pid}) terminated with status #{$?.exitstatus}" 

system(cmd); 

Esto parece funcionar bien - al menos en MacOSX

consigo

FOO is "" 
In child process. parent pid is 1388 
FOO is "foo in sub process" 
Child (pid 1388) terminated with status 99 
FOO is "" 

parece agradable en el que restaura estado anterior de forma automática

Ok - ahora intentó una diferente como esto no engendra 2 subprocesos

Use Process.spawn(env,command) 

pid = Process.spawn({ 'FOO'=>'foo in spawned process'}, cmd); 
pid = Process.wait(); 

Esto actúa como la llamada al sistema C y le permite especificar las tuberías y todo eso también.

0

¿Y en rubí impresión de código estándar de la exportación:

puts "export MYVAR=value" 

y luego usando backtick cáscara conseguirlo ejecutado en comands Shell:

$ `./myscript.rb` 

Esto tomará la salida del guión y ejecutarlo, funciona en conchas modernas como bash y zsh

+0

Desafortunadamente, eso tampoco funciona, porque todavía no está actuando directamente en el shell primario. – Julian

Cuestiones relacionadas